使用Stripe Checkout创建订阅,如何避免首次发票立即扣费?
解决Stripe Checkout首次发票即时扣费问题
核心原因
Stripe托管的Checkout流程默认会自动完成首次发票的最终化和扣费,这是因为Checkout的设计逻辑是让用户完成付款后立即激活订阅,因此会跳过你期望的invoice.created事件后的手动确认环节。
具体解决方案
1. 修改Checkout Session创建参数,禁用自动发票最终化
创建Checkout Session时,添加subscription_data.payment_behavior: 'default_incomplete'参数,同时设置subscription_data.invoice_settings.auto_advance: false。这样首次发票会处于**draft(草稿)**状态,不会自动扣费,直到你主动触发最终化操作。
示例代码(Node.js):
const session = await stripe.checkout.sessions.create({ payment_method_types: ['card'], line_items: [ { price: 'price_123', quantity: 1, }, ], mode: 'subscription', success_url: 'https://yourdomain.com/success', cancel_url: 'https://yourdomain.com/cancel', subscription_data: { payment_behavior: 'default_incomplete', invoice_settings: { auto_advance: false, }, }, });
2. 在webhook中处理invoice.created事件,手动触发发票最终化
当收到invoice.created事件时,先完成你的业务逻辑校验(比如用户状态同步、权限配置等),确认无误后调用Stripe API的invoice.finalize_invoice接口,触发扣费流程。
示例代码(webhook处理逻辑):
// 监听invoice.created事件 if (event.type === 'invoice.created') { const invoice = event.data.object; // 执行自定义业务逻辑校验 const isBusinessLogicValid = await yourCustomValidation(invoice); if (isBusinessLogicValid) { // 手动最终化发票,触发扣费 await stripe.invoices.finalizeInvoice(invoice.id); } else { // 业务校验失败,取消发票 await stripe.invoices.cancel(invoice.id); } }
3. 处理订阅的incomplete状态
因为设置了payment_behavior: 'default_incomplete',订阅会先处于incomplete状态,直到发票成功扣费后才会变为active。你需要在webhook中监听subscription.updated事件,当订阅状态切换为active时,完成后续的用户激活逻辑。
注意事项
- 确保webhook的签名验证逻辑正确,避免恶意请求触发发票操作
- 监听
invoice.payment_failed事件,处理扣费失败的情况(比如付款方式失效),可设置重试机制或通知用户更新付款方式 - 测试阶段使用Stripe测试卡片,验证整个流程的状态变化是否符合预期
内容的提问来源于stack exchange,提问作者crackerbarrel321
相关产品推荐
相关产品推荐

