Stripe结账流程:能否先收一次性费用再未来启动订阅?
实现Stripe访客模式下的「一次性费用+未来启动月度订阅」多订单项结账
我要集成Stripe实现多订单项的结账订阅功能,要求先收取一次性费用,之后在指定未来日期启动月度订阅。注意:结账为访客体验,无客户ID信息。
已尝试的方案及问题
方案1:创建0美元订阅后更新订阅计划
先创建0美元订阅,再通过Webhook调用stripe.subscriptionSchedules.update调整金额并设置start_date指定订阅启动日期,触发错误:
StripeInvalidRequestError: There is a gap between phase 0
(1693390410, 1696068810)and phase 1(1703956194, 1725037794).
方案2:更新价格同时暂停订阅
尝试在Webhook里更新订阅计划价格的同时暂停订阅,指定后续恢复日期,但不确定测试方法,代码如下:
// 更新订阅计划为新的月度价格 schedule = await stripe.subscriptionSchedules.update( schedule.id, { end_behavior: "cancel", phases: [ ...phases, { items: [ { price: 'abc', quantity: 1, }, { price: 'xyz', quantity: 1, } ], // trial_end: 1703956194, start_date: 1703956194, iterations: 8 } ], } ) // 暂停订阅,后续在指定日期恢复 const subscription = await stripe.subscriptions.update( checkoutSession.subscription, { pause_collection: { behavior: 'void', resumes_at: 1703956194 }, } );
正确实现方案
核心思路(推荐)
访客模式下无需绕弯,直接通过Checkout Session同时配置一次性费用和延迟启动的订阅:
- 把一次性费用作为
line_items添加到结账会话,确保结账时立即收取。 - 在
subscription_data里配置订阅项,通过trial_end设置未来的订阅启动时间——试用期结束后自动开始月度计费,无需额外修改订阅计划。
示例代码
const session = await stripe.checkout.sessions.create({ mode: 'subscription', payment_method_types: ['card'], // 一次性收费项 line_items: [ { price: '你的一次性费用价格ID', quantity: 1, }, ], // 延迟启动的订阅配置 subscription_data: { items: [ { price: '月度订阅价格ID1', quantity: 1, }, { price: '月度订阅价格ID2', quantity: 1, }, ], // 设置为未来要启动订阅的时间戳,试用期内不扣费 trial_end: 1703956194, }, // 确保一次性费用自动收取 payment_intent_data: { capture_method: 'automatic', }, success_url: 'https://你的域名.com/success', cancel_url: 'https://你的域名.com/cancel', });
方案1错误修复
错误提示的「阶段间隙」是因为订阅计划的各阶段必须连续,前一阶段的结束时间必须等于后一阶段的开始时间。如果非要用订阅计划实现:
- 创建0美元订阅时,第一阶段的
end_date设为未来订阅启动的时间戳。 - 更新订阅计划时,第二阶段的
start_date必须和第一阶段的end_date完全一致,不能有时间差。
方案2测试方法
如果坚持用暂停订阅的方案,按以下步骤测试:
- 用Stripe测试卡号(如
4242 4242 4242 4242)完成结账。 - 登录Stripe后台「订阅」页面,查看该订阅的「暂停状态」是否正确显示恢复日期。
- 手动把
resumes_at改成当前时间后10分钟左右,观察是否自动恢复并生成账单。 - 监听
customer.subscription.resumed、invoice.paid等Webhook事件,验证流程是否正常触发。
内容的提问来源于stack exchange,提问作者Adi
相关产品推荐
相关产品推荐

