问题描述
更新我构建了一个定价页面,该页面使用 Stripe Checkout 为产品 1 使用一次性付款按钮,为产品 2 使用订阅付款按钮。
我的目标是将一次性付款按钮重定向到一次性付款的 Stripe Checkout,并将订阅付款单独重定向到定期付款的结帐。
根据 STRIPE,这可以在 create-checkout-session.PHP(示例项目)的 CheckoutSession 中使用订阅作为模式来完成:
结帐会话的模式。使用价格或设置时需要 模式。如果结帐会话包括至少一个,则通过订阅 重复项目。
与 Stripe Docs 相反,以下代码行:'mode' => 'subscription',
仅激活订阅付款,但不会重定向一次性付款。要使一次性付款生效,我必须将其更改为:'mode' => 'payment',
但随后订阅付款不起作用。
<?PHP
require_once 'shared.PHP';
$domain_url = $config['domain'];
// Create new Checkout Session for the order
// Other optional params include:
// [billing_address_collection] - to display billing address details on the page
// [customer] - if you have an existing Stripe Customer ID
// [payment_intent_data] - lets capture the payment later
// [customer_email] - lets you prefill the email input in the form
// For full details see https://stripe.com/docs/api/checkout/sessions/create
// ?session_id={CHECKOUT_SESSION_ID} means the redirect will have the session ID set as a query param
$checkout_session = \Stripe\Checkout\Session::create([
'success_url' => $domain_url . '/success.html?session_id={CHECKOUT_SESSION_ID}','cancel_url' => $domain_url . '/canceled.html','payment_method_types' => ['card'],'mode' => 'subscription','line_items' => [[
'price' => $body->priceId,'quantity' => 1,]]
]);
echo json_encode(['sessionId' => $checkout_session['id']]);
这是 javascript 代码:
// Create a Checkout Session with the selected plan ID
var createCheckoutSession = function(priceId) {
return fetch("./create-checkout-session.PHP",{
method: "POST",headers: {
"Content-Type": "application/json"
},body: JSON.stringify({
priceId: priceId
})
}).then(function(result) {
return result.json();
});
};
// Handle any errors returned from Checkout
var handleResult = function(result) {
if (result.error) {
var displayError = document.getElementById("error-message");
displayError.textContent = result.error.message;
}
};
/* Get your Stripe publishable key to initialize Stripe.js */
fetch("./config.PHP")
.then(function(result) {
return result.json();
})
.then(function(json) {
var publishableKey = json.publishableKey;
var subscriptionPriceId = json.subscriptionPrice;
var onetimePriceId = json.onetimePrice;
var stripe = Stripe(publishableKey);
// Setup event handler to create a Checkout Session when button is clicked
document
.getElementById("subscription-btn")
.addEventListener("click",function(evt) {
createCheckoutSession(subscriptionPriceId).then(function(data) {
// Call Stripe.js method to redirect to the new Checkout page
stripe
.redirecttocheckout({
sessionId: data.sessionId
})
.then(handleResult);
});
});
// Setup event handler to create a Checkout Session when button is clicked
document
.getElementById("onetime-btn")
.addEventListener("click",function(evt) {
createCheckoutSession(onetimePriceId).then(function(data) {
// Call Stripe.js method to redirect to the new Checkout page
stripe
.redirecttocheckout({
sessionId: data.sessionId
})
.then(handleResult);
});
});
});
是否可以使用 Stripe Checkout 在同一页面上同时进行一次性付款和定期付款?我怎样才能做到这一点?
更新根据 Bemn:
$checkout_session = \Stripe\Checkout\Session::create([
'success_url' => $domain_url . '/success.html?session_id={CHECKOUT_SESSION_ID}','mode' => $body->mode
'line_items' => [[
'price' => $body->price_xxx,// For metered billing,do not pass quantity
'quantity' => 1,]],'line_items' => [[
'price' => $body->price_zzz,]]
]);
echo json_encode(['sessionId' => $checkout_session['id']]);
还有 JS:
// Create a Checkout Session with the selected plan ID
var createCheckoutSession = function(priceId,mode) {
return fetch("./create-checkout-session.PHP",body: JSON.stringify({
priceId: priceId,mode: mode // <-- passing the mode,e.g. 'payment' or 'subscription'
})
}).then(function(result) {
return result.json();
});
};
还有 HTML:
<div data-stripe-priceid="pricexxx" data-stripe-mode="payment" id="onetime-btn" class="bold mt-2 d-inline-block w-100-after-md max-width-xxs py-2 btn btn-secondary">Ore Time</div>
<div data-stripe-priceid="pricexxx" data-stripe-mode="subscription" id="subscription-btn" class="bold mt-2 d-inline-block w-100-after-md max-width-xxs py-2 btn btn-secondary">Ore Time</div>
解决方法
是否可以使用 Stripe Checkout 在同一页面上同时进行一次性付款和定期付款?
是。关键是您应该传递正确的选项以生成相应的 Stripe Checkout 会话 ID。
我怎样才能做到这一点?
-
后端:具有接受 Stripe 的价格 ID 和 付款方式 作为输入并返回 Stripe Checkout 会话 ID 作为输出的功能。
-
前端:将付款方式信息传递给
/create-checkout-session.php
。 (如果您无法这样做,请参阅注释)
详情
以下解决方案假设:
- 您在后端生成一个 Stripe Checkout 会话 ID。然后,该 ID 将传递给 js 前端中的
.createCheckoutSession()
。 - 您有一个一次性产品(我们称之为PAY)和一个循环订阅(我们称之为SUB)。
前端
我认为你很接近。您需要做的是将 mode
信息也传递给您的 API 端点:
// Create a Checkout Session with the selected plan ID
var createCheckoutSession = function(priceId,mode) { // <-- add a mode parameter
return fetch("./create-checkout-session.php",{
method: "POST",headers: {
"Content-Type": "application/json"
},body: JSON.stringify({
priceId: priceId,mode: mode // <-- passing the mode,e.g. 'payment' or 'subscription'
})
}).then(function(result) {
return result.json();
});
};
如果是这样,页面中的每个结帐按钮都应该有相应的 priceId 和付款方式信息。您可以通过使用数据属性存储它们来实现:
<div data-stripe-priceid="price_yyy" data-stripe-mode="subscription">Recurrent</div>
<div data-stripe-priceid="price_zzz" data-stripe-mode="payment">1-time</div>
如果是这样,您可以通过例如获取数据属性click
事件。
注意:如果您无法添加额外的参数来指示模式,则需要在后端确定给定的价格 ID 是 1 次还是循环产品。有关详情,请参阅 https://stripe.com/docs/api/prices/object?lang=php#price_object-type。
后端
以下是来自 Stripe 文档的 2 个示例代码片段。 直接复制它们不起作用。
PAY 参考:https://stripe.com/docs/checkout/integration-builder
$checkout_session = \Stripe\Checkout\Session::create([
'payment_method_types' => ['card'],'line_items' => [[
'price_data' => [
'currency' => 'usd','unit_amount' => 2000,'product_data' => [
'name' => 'Stubborn Attachments','images' => ["https://i.imgur.com/EHyR2nP.png"],],'quantity' => 1,]],'mode' => 'payment','success_url' => $YOUR_DOMAIN . '/success.html','cancel_url' => $YOUR_DOMAIN . '/cancel.html',]);
在您的情况下,您可能不需要定义 'price_data'
。相反,您应该使用 'price'
,就像下一个示例一样。
SUB 参考:https://stripe.com/docs/billing/subscriptions/checkout#create-session
$checkout_session = \Stripe\Checkout\Session::create([
'success_url' => 'https://example.com/success.html?session_id={CHECKOUT_SESSION_ID}','cancel_url' => 'https://example.com/canceled.html','payment_method_types' => ['card'],'mode' => 'subscription','line_items' => [[
'price' => $body->priceId,// For metered billing,do not pass quantity
'quantity' => 1,]);
- 看看这个参考:https://stripe.com/docs/api/checkout/sessions/create。对于
line_items
,您只需使用'price'
并传递价格 ID(例如price_xxx
),这意味着您的'line_items'
将如下所示:
'line_items' => [[
'price' => $body->priceId,
对于 'mode'
,使用您的 API 请求中的值。它应该是这样的:
'mode' => $body->mode
这意味着您最好在后端定义一个函数(例如 generate_checkout_session
):
- 解析 API 请求中收到的 json 正文
- 从解析的数据中获取
priceId
和mode
- 在
priceId
和 中使用 - 返回
checkout_session
ID
mode
和\Stripe\Checkout\Session::create
希望这(以及参考网址)可以帮助您。
,当您创建会话时,您既可以传递订阅经常性金额的价格,也可以传递您想要收取的一次性费用的另一个价格。您可以将多个经常性价格和一次性价格组合在一起。
$checkout_session = \Stripe\Checkout\Session::create([
'success_url' => $domain_url . '/success.html?session_id={CHECKOUT_SESSION_ID}','cancel_url' => $domain_url . '/canceled.html','line_items' => [
// Add a one-time Price for $10
[
'price' => 'price_123',// Add another one-time Price for $23
[
'price' => 'price_345',// Add a recurring Price for $100 monthly
[
'price' => 'price_ABC',]);
上面的代码将创建一个包含 3 个订单项的会话。一台每月 100 美元,一台只需 10 美元,一次只需 23 美元。第一次付款时,会议的总费用为 133 美元。它还将以每月 100 美元的价格开始订阅,未来的发票将按预期收取 100 美元。
,我所知道的是,您只需要为一次性或订阅添加一张支票,您就可以这样做:
JS FILE CHANGES:
var createCheckoutSession = function(priceId,$mode) {
return fetch("./create-checkout-session.php",paymentType: $mode,// This vary based on the button clicked either one-time or subscription.
})
}).then(function(result) {
return result.json();
});
};
/* Get your Stripe publishable key to initialize Stripe.js */
fetch("./config.php")
.then(function(result) {
return result.json();
})
.then(function(json) {
var publishableKey = json.publishableKey;
var subscriptionPriceId = json.subscriptionPrice;
var onetimePriceId = json.onetimePrice;
var stripe = Stripe(publishableKey);
// Setup event handler to create a Checkout Session when button is clicked
document
.getElementById("subscription-btn")
.addEventListener("click",function(evt) {
createCheckoutSession(subscriptionPriceId,'subscription').then(function(data) {
// Call Stripe.js method to redirect to the new Checkout page
stripe
.redirectToCheckout({
sessionId: data.sessionId
})
.then(handleResult);
});
});
// Setup event handler to create a Checkout Session when button is clicked
document
.getElementById("onetime-btn")
.addEventListener("click",function(evt) {
createCheckoutSession(onetimePriceId,'onetime').then(function(data) {
// Call Stripe.js method to redirect to the new Checkout page
stripe
.redirectToCheckout({
sessionId: data.sessionId
})
.then(handleResult);
});
});
});
现在我们需要对 PHP 文件进行更改:
PHP FILE CHANGES:
$checkout_session = \Stripe\Checkout\Session::create([
'success_url' => $domain_url . '/success.html?session_id={CHECKOUT_SESSION_ID}','mode' => $body->paymentType,// Here is what we have got from front-end
'line_items' => [[
'price' => $body->priceId,]]
]);