Payment Intent未显示在发票下:Stripe先存卡后付订阅问题
问题分析与解决方案
你遇到的核心问题是订阅创建时无法生成并获取Payment Intent,主要原因出在绑卡流程的参数错误和订阅创建的配置逻辑上,以下是具体修复步骤:
一、修正绑卡流程的Setup Intent参数
你当前的Setup Intent代码误用了参数名,将setup_future_usage写成了usage,这会导致Stripe无法正确标记支付方式可用于后续自动扣费(off-session)。此外,绑卡流程存在冗余步骤——Setup Intent确认时会自动完成支付方式绑定和默认设置,无需手动调用paymentMethods.attach和customers.update。
修正后的绑卡代码:
// 创建Stripe客户 const customer = await stripe.customers.create({ name: req.user.name, email: req.user.email, metadata: { userId: req.user._id.toString(), createdAt: moment().format('YYYY-MM-DD HH:mm:ss'), } }); // 创建并确认Setup Intent,自动绑定支付方式到客户并标记为可用于off_session支付 const setupIntent = await stripe.setupIntents.create({ customer: customer.id, payment_method: paymentMethod, confirm: true, payment_method_types: ['card'], setup_future_usage: 'off_session', // 修正参数名 return_url: `${process.env.STRIPE_RETURN_AND_WEBHOOK_BASE_URL}/api/stripe/return`, }); // 确认Setup Intent状态成功后,将customer.id和paymentMethod存入数据库 if (setupIntent.status === 'succeeded') { // 此处写入你的数据库存储逻辑 }
二、调整订阅创建的配置
根据「先存卡后付款」的需求,分两种场景调整配置:
场景1:订阅创建时立即扣费(如首月费用)
确保配置能触发即时支付,同时处理可能的验证需求:
const subscription = await stripe.subscriptions.create({ customer: stripeCustomerId, items: [ { price: selectedPrice.id } ], payment_behavior: "default_incomplete", // 支付失败时订阅转为incomplete而非直接失败 collection_method: "charge_automatically", default_payment_method: dbCustomer.paymentMethodId, // 确保此ID是绑定到该客户的有效支付方式 payment_settings: { save_default_payment_method: "on_subscription" }, currency: 'usd', expand: ["latest_invoice.payment_intent"], // 仅当latest_invoice有支付意图时才会返回 metadata: { packageId: pkg._id.toString(), patientId: req.user._id.toString() } }); // 检查返回的Payment Intent状态 if (subscription.latest_invoice?.payment_intent) { console.log('Payment Intent ID:', subscription.latest_invoice.payment_intent.id); } else { // 无Payment Intent的情况:可能是订阅无初始费用,或支付方式未通过验证 console.log('未生成Payment Intent - 请检查订阅是否有初始费用,或支付方式是否有效'); }
场景2:订阅创建时不扣费(后续账单周期自动扣费)
若订阅无初始费用,创建时不会生成Payment Intent,只有当账单周期结束生成待支付发票时,Stripe才会自动创建Payment Intent用于扣费。此时无需额外调整代码,但需确保:
- 订阅价格为后付费型(如按月计费)
- 支付方式已通过Setup Intent验证并标记为可用于off_session支付
三、额外排查点
- 确认Webhook收到的Setup Intent状态为
succeeded,且支付方式的status为active - 检查Stripe Dashboard中该客户的支付方式是否已正确绑定,且标记为「可用于订阅」
- 若支付方式需要3DS验证,需在Setup Intent确认时处理
requires_action状态,确保支付方式完全验证通过
内容的提问来源于stack exchange,提问作者Abdullah Moudood
相关产品推荐
相关产品推荐

