跳转到主要内容

Change Plan API

Full API docs for updating subscriptions.

Plan Change Preview

See charge amounts before changing plans.

Integration Guide

Step-by-step subscription setup.

What is a subscription upgrade or downgrade?

Changing plans lets you move a customer between subscription tiers or quantities. Use it to:
  • Align pricing with usage or features
  • Move from monthly to annual (or vice versa)
  • Adjust quantity for seat-based products
Plan changes can trigger an immediate charge depending on the proration mode you choose.

When to use plan changes

  • Upgrade when a customer needs more features, usage, or seats
  • Downgrade when usage decreases
  • Migrate users to a new product or price without cancelling their subscription

Plan Change Flow

Prerequisites

Before implementing subscription plan changes, ensure you have:
  • A Dodo Payments merchant account with active subscription products
  • API credentials (API key and webhook secret key) from the dashboard
  • An existing active subscription to modify
  • Webhook endpoint configured to handle subscription events
For detailed setup instructions, see our Integration Guide.

Step-by-Step Implementation Guide

Follow this comprehensive guide to implement subscription plan changes in your application:
1

Understand Plan Change Requirements

Before implementing, determine:
  • Which subscription products can be changed to which others
  • What proration mode fits your business model
  • How to handle failed plan changes gracefully
  • Which webhook events to track for state management
Test plan changes thoroughly in test mode before implementing in production.
2

Choose Your Proration Strategy

Select the billing approach that aligns with your business needs:
Best for: SaaS applications wanting to charge fairly for unused time
  • Calculates exact prorated amount based on remaining cycle time
  • Charges a prorated amount based on unused time remaining in the cycle
  • Provides transparent billing to customers
3

Implement the Change Plan API

Use the Change Plan API to modify subscription details:
subscription_id
string
必填
The ID of the active subscription to modify.
product_id
string
必填
The new product ID to change the subscription to.
quantity
integer
必填
新计划的单位数量(针对基于席位的产品)。
proration_billing_mode
string
必填
How to handle immediate billing: prorated_immediately, full_immediately, difference_immediately, or do_not_bill.
addons
array
Optional addons for the new plan. Leaving this empty removes any existing addons.
on_payment_failure
string
Controls behavior when the plan change payment fails:
  • prevent_change: Keep subscription on current plan until payment succeeds
  • apply_change (default): Apply plan change immediately regardless of payment outcome
If not specified, uses the business-level default setting.
discount_codes
array
可选的 stacked 折扣代码应用于新计划(最多20个,按数组顺序应用)。行为取决于您传递的内容:
  • 未提供 / null — 如果适用于新产品,现有的折扣与 preserve_on_plan_change=true 会被保留。
  • [](空数组) — 从订阅中移除所有现有折扣。
  • ["CODE_A", "CODE_B", ...] — 用该堆叠集替换任何现有的折扣。
discount_code
string
已弃用
已弃用 — 新的集成优先使用 discount_codes。此字段仍然保留后向兼容性,但不能在同一请求中与 discount_codes 结合使用。
effective_at
string
默认值:"immediately"
何时应用计划更改:
  • immediately(默认):立即应用计划更改
  • next_billing_date:为下一个账单日期安排更改。客户在账单周期结束前保持当前计划。
对降级使用 next_billing_date,以便客户在账单周期结束前保留当前计划的好处。
4

Handle Webhook Events

设置 webhook 处理以跟踪计划更改的结果:
  • subscription.active:计划更改成功,订阅已更新
  • subscription.plan_changed:订阅计划已更改(升级/降级/插件更新)
  • subscription.on_hold:计划更改费用失败,订阅暂停
  • payment.succeeded:计划更改的即时费用已成功
  • payment.failed:即时费用失败
始终验证 webhook 签名并实现幂等事件处理。
5

Update Your Application State

根据 webhook 事件更新您的应用程序:
  • 根据新计划授予/撤销功能
  • 使用新计划详细信息更新客户仪表板
  • 发送有关计划更改的确认电子邮件
  • 记录账单更改以供审核
6

Test and Monitor

彻底测试您的实现:
  • 使用不同场景测试所有比例模式
  • 验证 webhook 处理是否正常工作
  • 监控计划更改的成功率
  • 为计划更改失败设置警报
您的订阅计划更改实施现在已准备好用于生产环境。

预览计划更改

在确认计划更改之前,使用预览 API 向客户展示他们将被收取的确切费用:
使用预览 API 构建确认对话框,在客户确认计划更改之前显示他们将被收取的确切金额。

更改计划 API

使用更改计划 API 修改活动订阅的产品、数量和比例行为。

快速启动示例

Success
只有在计划更改期间创建即时费用和/或发票时,字段如invoice_idpayment_id才会返回。总是依赖 webhook 事件(例如payment.succeededsubscription.plan_changed)来确认结果。
如果即时费用失败,订阅可能会移动到 subscription.on_hold,直到付款成功。

管理插件

在更改订阅计划时,您还可以修改插件:
插件包含在比例计算中,将根据所选的比例模式收费。

应用折扣代码

在更改订阅计划时,您可以应用一个或多个 stacked 折扣代码(最多20个,按数组顺序应用)。这对于在升级或迁移时提供促销价格很有用。

计划更改时的折扣行为

该端点上的单一 discount_code 字段 已弃用 但仍然可以用于后向兼容性 — 现有集成不需要立即更改。它不能与 discount_codes 在同一请求中结合使用。方便时迁移到数组形式。
使用 预览计划更改 APIdiscount_codes,在确认计划更改前向客户展示他们节省的确切金额。

比例模式

选择在更改计划时如何向客户收费:

prorated_immediately

  • 对当前周期的部分差异收费
  • 如果在试用期内,立即收费并转换为新计划
  • 降级:可能生成预付抵用金,用于未来续订

full_immediately

  • 立即全额收费
  • 忽略旧计划的剩余时间
使用difference_immediately进行的降级所创建的抵用金是订阅范围内的,与基于抵用的结算权利相区别。它们会自动应用于同一订阅的未来续订,不能在订阅之间转移。

difference_immediately

  • 升级:立即收费旧计划和新计划之间的价格差异
  • 降级:将剩余价值作为内部抵用金添加到订阅,并在续订时自动应用

do_not_bill

  • 不计算任何费用或抵用金
  • 客户立即切换到新计划,没有任何账单调整
  • 账单周期保持不变
  • 最适合礼遇迁移、免费计划切换或吸收成本差异

示例场景

使用这些规范数字保持一致:
  • 当前计划:Basic 每月 $30
  • 升级目标:Pro 每月 $80
  • 降级目标(从 Pro):Starter 每月 $20
  • 账单周期:30天,从 1月1日 开始
  • 计划更改发生在 1月16日(剩余 15 天,已使用 15 天)

每种模式如何处理账单

选择 prorated_immediately 进行公平的时间计费;选择 full_immediately 重启账单周期;使用 difference_immediately 执行简单升级并在降级时自动抵用;或使用 do_not_bill 在不进行任何账单调整的情况下切换计划。

处理支付失败

控制计划更改支付失败时的行为,使用 on_payment_failure 参数。

支付失败模式

如果未指定,on_payment_failure 参数使用您的仪表板中配置的业务级别默认设置。

何时使用每种模式

处理 webhooks

通过 webhooks 跟踪订阅状态以确认计划更改和支付。

处理的事件类型

  • subscription.active:订阅已激活
  • subscription.plan_changed:订阅计划已更改(升级/降级/插件更改)
  • subscription.on_hold:费用失败,订阅暂停
  • subscription.renewed:续订成功
  • payment.succeeded:计划更改或续订的支付成功
  • payment.failed:支付失败
我们建议从订阅事件中驱动业务逻辑,使用支付事件进行确认和对账。

验证签名并处理意图

有关详细的负载架构,请参见订阅 webhook 负载支付 webhook 负载

最佳实践

请遵循以下建议,以实现可靠的订阅计划更改:

计划更改策略

  • 彻底测试:在生产之前始终在测试模式下测试计划更改
  • 仔细选择比例方式:选择符合您业务模型的比例方式
  • 优雅地处理失败:实现适当的错误处理和重试逻辑
  • 监控成功率:跟踪计划更改成功/失败率并调查问题

Webhook 实施

  • 验证签名:始终验证 webhook 签名以确保真实性
  • 实现幂等性:优雅地处理重复的 webhook 事件
  • 异步处理:不要用繁重的操作阻塞 webhook 响应
  • 记录一切:保持详细日志以进行调试和审计

用户体验

  • 清晰沟通:告知客户账单变化和时间
  • 提供确认:为成功的计划更改发送电子邮件确认
  • 处理边缘案例:考虑试用期、比例调整和支付失败
  • 立即更新 UI:在您的应用程序界面中反映计划更改

常见问题及解决方案

解决订阅计划更改中遇到的典型问题:
症状:API 调用成功但订阅仍保留在旧计划常见原因
  • Webhook 处理失败或延迟
  • 在接收到 webhooks 后应用程序状态未更新
  • 在状态更新期间出现数据库事务问题
解决方案
  • 实现强大的 webhook 处理和重试逻辑
  • 对状态更新使用幂等操作
  • 添加监控以检测和提醒遗漏的 webhook 事件
  • 验证 webhook 终端是否可访问并正确响应
症状:客户降级但未看到抵用余额常见原因
  • 比例方式期望:降级使用 difference_immediately 抵用全额计划价格差异,而 prorated_immediately 根据周期内的剩余时间创建比例抵用金
  • 抵用金是订阅特定的,不会在订阅之间转移
  • 客户仪表板上未显示抵用余额
解决方案
  • 对降级使用 difference_immediately ,当您希望自动抵用时
  • 向客户解释抵用适用于同一订阅的未来续订
  • 实现客户门户显示抵用余额
  • 检查下一个发票预览以查看应用的抵用金
症状:由于签名无效,Webhook 事件被拒绝常见原因
  • 错误的 webhook 秘钥
  • 在签名验证前修改了原始请求主体
  • 错误的签名验证算法
解决方案
  • 验证您使用的 DODO_WEBHOOK_SECRET 是否正确,并来自仪表板
  • 在任何 JSON 解析中间件之前阅读原始请求主体
  • 使用适用于您的平台的标准 webhook 验证库
  • 在开发环境中测试 webhook 签名验证
症状:API 返回 422 不可处理的实体错误常见原因
  • 无效的订阅 ID 或产品 ID
  • 订阅未处于活动状态
  • 缺少必需参数
  • 产品不可用于计划更改
解决方案
  • 验证订阅是否存在且处于活动状态
  • 检查产品 ID 是否有效且可用
  • 确保提供所有必需的参数
  • 查看 API 文档以获取参数要求
症状:计划更改启动但即时费用失败常见原因
  • 客户的支付方式上的资金不足
  • 支付方式过期或无效
  • 银行拒绝交易
  • 欺诈检测阻止了收费
解决方案
  • 适当地处理 payment.failed webhooks 事件
  • 通知客户更新支付方式
  • 为临时故障实现重试逻辑
  • 考虑允许在即时费用失败的情况下进行计划更改
症状:计划更改费用失败,订阅移至 on_hold 状态发生了什么: 当计划更改费用失败时,订阅会自动进入 on_hold 状态。直到更新支付方式,订阅才会自动续订。解决方案:更新支付方式以重新激活订阅要在计划更改失败后从 on_hold 状态重新激活订阅:
  1. 使用更新支付方式 API 更新支付方式
  2. 自动收费创建:API 自动为剩余款项创建费用
  3. 生成发票:为费用生成发票
  4. 支付处理:使用新支付方式处理支付
  5. 重新激活:在支付成功后,将订阅重新激活到 active 状态
要监控的 Webhook 事件
  • subscription.on_hold:订阅已暂停(在计划更改费用失败时接收)
  • payment.succeeded:剩余费用支付成功(在更新支付方式后)
  • subscription.active:支付成功后订阅重新激活
最佳做法
  • 在计划更改费用失败时立即通知客户
  • 提供有关如何更新支付方式的明确说明
  • 监控 webhook 事件以跟踪重新激活状态
  • 考虑为临时支付故障实施自动重试逻辑

Update Payment Method API Reference

查看完整的 API 文档以更新支付方式并重新激活订阅。

测试您的实现

按照以下步骤彻底测试您的订阅计划更改实现:
1

Set up test environment

  • 使用测试 API 密钥和测试产品
  • 创建具有不同计划类型的测试订阅
  • 配置测试 webhook 终端
  • 设置监控和日志记录
2

Test different proration modes

  • 使用各种账单周期位置测试 prorated_immediately
  • 为升级和降级测试 difference_immediately
  • 测试 full_immediately 以重置账单周期
  • 测试 do_not_bill 以进行无费用/无抵用的计划切换
  • 验证抵用计算是否正确
3

Test webhook handling

  • 验证是否收到了所有相关的 webhook 事件
  • 测试 webhook 签名验证
  • 优雅地处理重复的 webhook 事件
  • 测试 webhook 处理失败情况
4

Test error scenarios

  • 测试无效的订阅 ID
  • 测试过期的支付方式
  • 测试网络故障和超时
  • 测试资金不足
5

Monitor in production

  • 为失败的计划更改设置警报
  • 监控 webhook 处理时间
  • 跟踪计划更改成功率
  • 查看客户支持票据以解决计划更改问题

错误处理

在您的实现中优雅地处理常见的 API 错误:

HTTP 状态代码

计划更改请求已成功处理。订阅正在更新,支付处理已经开始。
请求参数无效。检查所有必填字段是否已提供并正确格式化。
无效或缺失的 API 密钥。请验证您的 DODO_PAYMENTS_API_KEY 是否正确且拥有适当的权限。
订阅 ID 未找到或不属于您的帐户。
订阅无法更改(例如,已取消,产品不可用等)。
服务器发生错误。稍作延迟后重试请求。

错误响应格式

下一步

计划变更请求已成功处理。订阅正在更新,支付处理已开始。
请求参数无效。检查是否提供了所有必填字段,并且格式正确。
API 密钥无效或缺失。验证你的 DODO_PAYMENTS_API_KEY 是否正确且具有适当的权限。
未找到订阅 ID 或不属于你的账户。
无法更改订阅(例如,已取消、产品不可用等)。
服务器发生错误。请稍后重试请求。

错误响应格式

后续步骤

最后修改于 2026年6月26日