概览
按需订阅允许您一次性授权客户的支付方式,然后在需要时收取可变金额,而不是固定的日程表。所有账户都可使用此功能,无需审批。 使用本指南:- 创建按需订阅(授权带有可选初始价格的授权)
- 通过自定义金额触发后续收费
- 使用webhook跟踪结果
先决条件
- Dodo Payments商家账户和API密钥
- 配置的webhook密钥和接收事件的端点
- 目录中的订阅产品
按需如何运作
- 您使用
on_demand对象创建订阅以授权支付方式,并可选择收取初始费用。 - 随后,您可以使用专用的收费端点根据该订阅创建自定义金额的收费。
- 您可以监听webhook(例如,
payment.succeeded,payment.failed)来更新您的系统。
创建按需订阅
端点:POST /checkouts 关键请求字段(正文):请查看创建结账会话
创建按需订阅
- Node.js SDK
- Python SDK
- Go SDK
- cURL
Success
按需订阅的收费
授权授权后,按需创建所需的费用。 端点:POST /subscriptions/{subscription_id}/charge 关键请求字段(正文):- Node.js SDK
- Python SDK
- Go SDK
- cURL
Success
处理失败的收费
当对按需订阅的收费失败时,您可以决定接下来会发生什么。与计划订阅不同,按需订阅在失败后仍然可以收费。您可以调用收费端点作为自己的重试逻辑的一部分。失败时发生的事情
1
Charge attempt fails
POST /subscriptions/{subscription_id}/charge请求返回错误响应或异步完成并发出带有拒绝原因的payment.failed webhook。2
Subscription may transition to on_hold
订阅可能会移动到
on_hold状态并发出subscription.on_hold webhook(请参阅订阅状态→暂停)。这是一个信号,而不是锁定。对于按需订阅,on_hold并不会阻止您再次收费。3
Retry the charge (your call)
对于按需流程,Dodo不会自动重试。您可以随时再次调用
POST /subscriptions/{subscription_id}/charge进行重试。应用下方的安全重试策略——使用指数回退,跳过硬拒绝,并避免突发模式,以便我们的欺诈和风险系统不会标记重试。4
Optionally, ask the customer for a new payment method
如果重试因支付方式本身失效(过期卡、关闭账户等)而持续失败,使用
POST /subscriptions/{subscription_id}/update-payment-method从客户那里收集新的。在成功时,订阅返回到active,并依次发出payment.succeeded和subscription.active webhook。按需 vs 计划:对于计划订阅,Dodo会自动进行续订重试和扣款通知。对于按需订阅,您负责重试策略,因为只有您知道下次收费什么时候应该发生(由您的使用情况事件驱动,而不是日历)。
按需收费失败的webhook顺序
事件3和4只有在后续收费成功后才会触发。
重试责任
订阅扣款通知——内置的电子邮件恢复序列——仅限于计划订阅的续订付款失败和客户主动取消。它并不适用于按需收费失败。当您决定需要更新支付方式时,请直接与客户沟通(例如,事务性电子邮件或应用内提示)。付款重试
我们的欺诈检测系统可能会阻止激进的重试模式(并可能将其标记为潜在的卡测试)。请遵循安全重试政策。安全重试政策的原则
- 后退机制:在重试之间使用指数退避。
- 重试限制:限制总重试次数(最大3-4次尝试)。
- 智能筛选:仅对可重试的失败进行重试(例如,网络/发卡行错误、资金不足);绝不要对硬拒绝进行重试。
- 卡测试防范:不要重试诸如
DO_NOT_HONOR,STOLEN_CARD,LOST_CARD,PICKUP_CARD,FRAUDULENT,AUTHENTICATION_FAILURE等失败。 - 可变元数据(可选):如果您维护自己的重试系统,通过元数据区分重试(例如,
retry_attempt)。
建议的重试时间表(订阅)
- 第一次尝试:您创建收费时立即进行
- 第二次尝试:3天后
- 第三次尝试:再过7天(总共10天)
- 第四次尝试(最后一次):再过7天(总共17天)
避免突发重试;与授权时间对齐
- 将重试固定在原始授权时间戳上,以避免在您的投资组合中出现“突发”行为。
- 示例:如果客户在今天的1:10开始试用或授权,请按您的退避时间安排后续重试在后续天的1:10(例如,+3天→1:10,+7天→1:10)。
- 或者,如果您存储了上次成功支付的时间
T,请安排下次尝试在T + X days以保持时间对齐。
时区和DST:使用统一的时间标准进行安排,仅在显示时进行转换以保持间隔。
您不应重试的拒绝代码
STOLEN_CARDDO_NOT_HONORFRAUDULENTPICKUP_CARDAUTHENTICATION_FAILURELOST_CARD
有关拒绝原因的完整列表及其是否可由用户纠正,请参见交易失败文档。
实现指南(无代码)
- 使用调度程序/队列持久化精确时间戳;在相同的HH:MM计算下次尝试。
- 维护和引用上次成功支付的时间戳
T来计算下次尝试;不要在相同时刻将多个订阅聚集在一起。 - 始终评估最后的拒绝原因;对于上面的跳过列表中的硬拒绝停止重试。
- 限制每个客户和每个账户的并发重试,以防止意外激增。
- 积极沟通:通过电子邮件/SMS通知客户更新其支付方式,以便在下次计划尝试前更新。
- 元数据仅用于可观测性(例如,
retry_attempt);切勿通过旋转无关紧要的字段“规避”欺诈/风险系统。
取消
按需订阅与计划订阅的取消流程不同,因为没有固定的计费周期可用于锚定即时结束日期。客户门户行为
当客户从客户门户取消按需订阅时,取消计划在下一个计费日期。对于按需订阅,有意不显示立即取消选项。 原因:按需订阅没有可预测的定期续订日期——下次收费时间完全由您的使用情况事件驱动。将取消安排在下一个计费日期,保持授权有效,直到期间结束,以便对正在进行的使用情况收取费用,然后干净地结束订阅。 客户确认取消后:- 订阅保持
active,并通过POST /subscriptions/{id}/charge收费,直到安排的取消日期。 cancel_at_next_billing_date设置为true。- 取消生效时会发出
subscription.cancelledwebhook。
如果您需要立即结束订阅(例如,响应退款或支持请求),请通过API而不是依赖客户门户流程程序化地取消它。
程序化取消
您可以随时通过API取消按需订阅。您可以选择取消是立即生效还是计划的。 端点:PATCH /subscriptions/{subscription_id}- Cancel immediately
- Cancel at next billing date
将订阅
status设置为cancelled以立即结束。授权被撤销,无法创建进一步的收费。cURL
取消时的webhook
使用webhook跟踪结果
实施webhook处理以跟踪客户旅程。参见实现Webhooks。- subscription.active: 授权授权并激活订阅
- subscription.failed: 创建失败(例如,授权失败)
- subscription.on_hold: 订阅已暂停(例如,未付款状态)
- subscription.cancelled: 订阅完全取消(参见取消)
- payment.succeeded: 收费成功
- payment.failed: 收费失败
测试和下一步
1
Create in test mode
使用您的测试API密钥创建订阅,然后打开返回的
checkout_url并完成授权。2
Trigger a charge
调用收费端点,使用小型
product_price(例如,100),并验证您收到payment.succeeded。3
Go live
验证事件和内部状态更新后,切换到您的实时API密钥。
故障排除
- 422 无效请求:确保在创建时提供了
on_demand.mandate_only,并且在收费时提供了product_price。 - 货币错误:如果您覆盖
product_currency,请确认您的账户和客户是否支持。 - 未收到webhooks:验证您的webhook URL和签名密钥配置。