如何用Stripe设置无固定间隔的未来多笔支付?相关问题咨询
问题描述
我需要实现无固定间隔的未来支付(例如立即支付一笔,之后在另外2个预设日期各支付一笔)。我手里有包含日期和金额的对象,目前的做法是给每笔支付单独创建订阅,并且在第二次扣费前取消该订阅。
现有代码如下:
const _payments = stripePayments.map(async (payment) => { try { const price = await stripe.prices.create({ unit_amount: payment.amount * 100, currency: 'usd', recurring: { interval: 'year' }, product: process.env.SCRIPE_PRODUCT }) const subscription = { customer: customerId, items: [{ price: price.id }], billing_cycle_anchor: payment.dueDate, cancel_at: addYears(new Date(payment.dueDate), 1) } return await stripe.subscriptions.create(subscription) } catch (error) { throw new Error('creating Stripe subscription failed ' + error) } })
我有两个疑问:
- 是否有更优的实现方式?
- 创建订阅后,账单里立即出现了一笔小额扣费,这是为什么?能不能取消这笔扣费?
解答
1. 更优的实现方式
你当前用订阅模拟单次未来支付的方式过于繁琐,Stripe有更贴合需求的原生方案:
方案一:发票项 + 预定发票
无需创建订阅,直接给客户添加发票项并设置发票的预定付款日期,到点自动扣费:
const _payments = stripePayments.map(async (payment) => { // 创建对应金额的发票项 await stripe.invoiceItems.create({ customer: customerId, amount: payment.amount * 100, currency: 'usd', description: `Scheduled payment on ${payment.dueDate}` }); // 生成预定发票,设置付款日期 const invoice = await stripe.invoices.create({ customer: customerId, collection_method: 'charge_automatically', scheduled_for: payment.dueDate }); return invoice; });
这个方案完全不需要处理订阅取消逻辑,每笔支付对应一个独立的预定发票,逻辑更清晰。
方案二:付款链接的预定付款
如果是面向终端用户的场景,可创建带预定付款的付款链接,用户完成初始支付后,后续预定支付会自动执行:
const paymentLink = await stripe.paymentLinks.create({ line_items: [{ price_data: { currency: 'usd', product: process.env.STRIPE_PRODUCT, unit_amount: payment.amount * 100, }, quantity: 1, }], payment_intent_data: { setup_future_usage: 'off_session', }, scheduled_payments: stripePayments.map(payment => ({ amount: payment.amount * 100, currency: 'usd', scheduled_at: payment.dueDate, })), });
适合需要用户主动触发初始支付,后续自动执行预定扣费的场景,后端无需频繁创建资源。
2. 小额扣费的原因及解决方法
你看到的小额扣费是Stripe的支付方式预授权验证,金额通常为$0.50或$1.00,目的是验证客户支付方式的有效性,防止欺诈。
- 产生原因:创建订阅时,即便设置了
billing_cycle_anchor为未来日期,Stripe默认会触发支付方式验证,生成预授权扣费。这笔费用不会实际入账,通常7-14天内会自动取消。 - 取消/避免方法:
- 创建订阅时添加
payment_behavior: 'default_incomplete'参数,跳过预授权验证:const subscription = { customer: customerId, items: [{ price: price.id }], billing_cycle_anchor: payment.dueDate, cancel_at: addYears(new Date(payment.dueDate), 1), payment_behavior: 'default_incomplete' } - 若支付方式支持,可设置
payment_method_options.card.verify_with_microcharge: false,但该参数仅适用于特定场景。
- 创建订阅时添加
注意:预授权扣费只是暂时冻结额度,不会真正扣除客户资金,若不是必须场景,也可以不用额外处理。
内容的提问来源于stack exchange,提问作者ilyo
相关产品推荐
相关产品推荐

