Prerequisites
Before you start, you need:- A Dodo Payments merchant account
- An API key from Developer → API Keys in the dashboard, stored in
DODO_PAYMENTS_API_KEY - A webhook secret from Developer → Webhooks, stored in
DODO_PAYMENTS_WEBHOOK_KEY - At least one subscription product created under Products
API Integration
Checkout Sessions
Create a subscription by building a checkout session with your subscription product. The customer authorizes a payment method and the subscription activates when they complete checkout.- Node.js SDK
- Python SDK
- REST API
API 响应
响应包含一个checkout_url:
Webhooks
当订阅事件发生时,Webhooks 会通知您的服务器。在 dashboard 的 Developer → Webhooks 下设置您的 endpoint。 如需设置 webhook endpoint,请参阅 Webhooks。订阅事件类型
跟踪以下事件以管理订阅生命周期:subscription.active— 订阅已激活subscription.updated— 订阅中的某个字段发生更改subscription.on_hold— 续订或计划变更扣款失败subscription.failed— 订阅创建失败(终止状态;客户必须重新订阅)subscription.renewed— 周期性扣款成功subscription.past_due— 续订失败且宽限期已开始;客户会继续保留访问权限,直到past_due_ends_atsubscription.plan_changed— 计划已升级、降级或更改subscription.cancelled— 订阅已取消subscription.expired— 订阅已达到其期限结束时间
paused、unpaused 和 update_payment_method)请参阅 Subscription Webhooks。
支付场景
成功支付流程 Webhook 序列取决于订阅是否包含试用期。 立即计费(0 个试用日):subscription.active:mandate 已授权,订阅已激活。payment.succeeded:确认首次扣款。预计在 checkout 后 2–10 分钟内收到此事件。
- 试用期开始时(checkout): 支付方式获得授权后,
subscription.active触发。此时不会收取周期性扣款。 首次实际扣款会推迟到试用期结束。 - 试用期结束时: 系统会收取周期性金额,您会同时收到
payment.succeeded和subscription.renewed。
subscription.renewed:每个计费周期扣除续订款项时触发,始终与payment.succeeded一起发送。该事件还包含更新后的next_billing_date。
每当订阅产品实际扣款时,您都会收到
subscription.renewed 和 payment.succeeded。请使用 subscription.renewed(而不是单独使用 payment.succeeded)作为延长下一周期访问权限的信号。- 订阅失败
subscription.failed- 由于创建 mandate 失败,订阅创建失败。payment.failed- 表示支付失败。
- 订阅暂停
subscription.on_hold- 由于续订支付失败或计划变更扣款失败,订阅被暂停。如果您的业务设有宽限期,续订失败后订阅会先进入past_due(subscription.past_due),只有在宽限期结束后才会进入on_hold(或cancelled,具体取决于您的宽限期设置)。请参阅 Subscription States。- 订阅暂停后,在更新支付方式之前不会自动续订。
最佳实践:为简化实现,我们建议主要跟踪订阅事件来管理订阅生命周期。
subscription.failed 与 subscription.on_hold
这两个事件很容易混淆,但处理方式完全不同:
处理暂停的订阅
当订阅进入on_hold 状态时,您需要更新支付方式才能重新激活订阅。本节说明订阅何时会暂停以及如何处理。
订阅暂停的情况
在以下情况下,订阅会被暂停:- 续订支付失败:由于余额不足、卡片过期或银行拒绝,自动续订扣款失败
- 计划变更扣款失败:升级或降级计划期间的立即扣款失败
- 支付方式授权失败:无法为周期性扣款授权支付方式
从暂停状态重新激活订阅
要将订阅从on_hold 状态重新激活,请使用 Update Payment Method API。该 API 会自动执行以下操作:
- 为剩余应付款创建扣款
- 为该扣款生成 invoice
- 使用新的支付方式处理支付
- 支付成功后,将订阅重新激活为
active状态
1
Handle subscription.on_hold webhook
收到
subscription.on_hold webhook 后,更新应用状态并通知客户:2
Update payment method
客户准备好更新支付方式后,调用 Update Payment Method API:
如果客户已保存支付方式,您也可以使用现有的支付方式 ID:
3
Monitor webhook events
更新支付方式后,监控以下 webhook 事件:
payment.succeeded- 剩余应付款的扣款成功subscription.active- 订阅已重新激活
订阅事件 Payload 示例
更改订阅计划
您可以使用 change plan API endpoint 升级或降级订阅计划。这允许您修改订阅的产品、数量并处理按比例计费。Change Plan API Reference
按比例计费选项
更改订阅计划时,您有四种方式处理立即扣款:1. prorated_immediately
- 按剩余时间对当前计费周期的未使用部分进行抵扣。抵扣金额涵盖基础计划、数量和任何附加项
- 然后按新计划、数量和附加项收取一个完整周期的费用。该扣款本身不会按比例计算
- 立即净扣款 =(新的完整周期)减去(剩余比例 × 旧的完整周期)。如果抵扣金额更大,差额会作为订阅范围的 credit 留作未来续订使用
- 在试用期内,这会立即将用户切换到新计划,并立即向客户收费
2. full_immediately
- 按新计划的完整订阅金额向客户收费,不抵扣之前的周期
- 无论升级还是降级,客户都需要从头支付整个新计划价格
- 当您希望无论旧计划剩余多长时间都收取全额时,此选项非常有用
3. difference_immediately
- 客户只需支付旧计划价格与新计划价格之间的差额
- 金额不取决于周期内何时进行变更。在第 1 天和第 29 天进行相同升级,费用相同
- 升级时,客户会立即支付差额。例如,$30/月 → $80/月 = 立即收取 $50
- 降级时,价格差额会存储为订阅范围的 credit,并自动应用于未来续订。例如,$50/月 → $20/月 = 存储 $30 credit
4. do_not_bill
- 立即应用计划变更,但不会在变更时收费。新计划、数量和附加项可立即使用
- 由于现在不会收费,升级会让客户在当前周期剩余时间内免费享受更高等级计划。降级会立即生效,但不会抵扣客户已支付周期中未使用的部分
- 通过
do_not_bill授予的附加项不会在后续计划变更时抵扣,因为这些附加项从未计费。后续变更会按新的附加项数量全额计费 - 更新后的计划(以及数量/附加项)会在下一次计划续订时计费,并且会保留原始计费日期
行为
- 调用此 API 后,Dodo Payments 会根据您选择的按比例计费选项立即发起扣款
- 使用
prorated_immediately时,每次变更都会计算当前周期未使用部分的抵扣金额,无论升级还是降级均如此。如果抵扣金额超过新周期扣款,剩余金额会添加到订阅的 credit balance 中。这些 credit 专属于该订阅,只会用于抵扣同一订阅未来的周期性付款 - 使用
difference_immediately时,净额始终是确切的价格差额。对于降级,超出的金额会存储为订阅范围的 credit,与prorated_immediately相同 full_immediately选项会跳过 credit 计算,并收取完整的新计划金额do_not_bill选项会立即应用变更,但将计费推迟到下一次续订日期,并保留该日期
扣款处理
- 计划变更时发起的立即扣款通常会在 2 分钟内完成处理
- 如果立即扣款因任何原因失败,订阅会自动暂停,直到问题解决
按需订阅
按需订阅让您可以灵活地向客户收费,而不只是按照固定计划收费。所有账户均可使用此功能。
subscription_data.on_demand 字段。这样可以在不立即收费的情况下授权支付方式,或设置自定义初始价格。
向按需订阅收费:
对于后续扣款,请使用 POST /subscriptions//charge endpoint,并指定此次交易向客户收取的金额。
有关完整的分步指南(包括 request/response 示例、安全的重试策略和 webhook 处理),请参阅 On-Demand Subscriptions Guide。
关于订阅计费的关键事项
试用期会进行 $0 授权,而不是扣款。 订阅包含试用期时,试用期开始会创建一次 $0 mandate 授权以保存卡片;首次实际扣款会在试用期结束时进行。在 payments list 中,免费试用中的订阅恰好显示一笔金额为 0 的支付,其
total_amount 为 0。付费试用则会提前收取其 trial_amount。订阅生命周期:
past_due = 续订失败且宽限期正在运行(客户保留访问权限)。on_hold = 续订失败(可恢复:提示客户更新支付方式;适用 dunning 重试)。expired = 期限结束且未续订,无法重新激活。客户必须重新订阅。cancelled = 由客户或商户结束。大多数续订失败是发卡方拒绝(余额不足、卡片被拒),而不是 Dodo 错误。