/api/v1/subscription/update 只修改客户已有订阅上的金额,且只能调低。其他一切——不同的周期、更高的价格、不同的套餐、不同的币种——都属于通过 /api/v1/subscription/change 进行的套餐变更。本页是套餐变更的契约说明。仅改金额的变更见
订阅金额与分期计划。
套餐变更到底做了什么?
它不会编辑现有订阅。它会创建一个新订阅,让客户授权,然后让旧订阅退役。- 你调用
/api/v1/subscription/change,传入原订阅的originSubscriptionRequest,加上新套餐的完整描述和一个新的subscriptionRequest。 - Waffo 创建新订阅并返回一个包含
webUrl的subscriptionAction。你把客户引导到该地址去授权新套餐。 - 当客户完成授权且新套餐的首次扣款成功时,变更提交:新订阅变为
ACTIVE,原订阅退役。 - Waffo 向你在变更请求中传的
notifyUrl推送SUBSCRIPTION_CHANGE_NOTIFICATION。/api/v1/subscription/change/inquiry可按需返回同样的视图。
subscriptionId 会变。 从变更提交那一刻起,你自己的记录要以新的 subscriptionId 为键,旧的仅作历史保留。
我必须给客户一个支付页面吗,还是可以静默完成?
必须给页面。变更是由客户在收银台完成授权的——这正是subscriptionAction.webUrl 的用途。不存在复用现有授权的服务端到服务端套餐变更。
要为客户放弃支付的情况做好准备:在他们授权之前,什么都没有改变,原订阅继续正常扣款。
变更状态有哪些?
CLOSED 是有意设计的所有非成功结局的统一归类——客户支付失败、授权窗口超时,或你用一个更新的变更替换了这个变更。它不区分「超时」与「被拒绝」,所以不要把它当作可区分的信号去分支处理。
看到 CLOSED 该做什么:不做任何自动动作。原订阅仍然存在并继续扣款。如果客户仍想要新套餐,发起一个新的变更请求;不要重试旧的,也不要复用它的 subscriptionRequest。
remainingAmount 是什么,由谁计算?
remainingAmount 在每个变更请求上都是必填的,并且是由你计算的值。Waffo 不计算按比例分摊,也没有分摊字段——见
金额页的分摊章节。
Waffo 会怎么处理它:以变更请求的 currency 把该数值作为变更上的抵扣余额持有,并在新订阅的扣款中逐步抵扣。当被抵扣的某笔扣款是被关闭而非收款成功,或实际抵扣少于预留金额时,未使用的部分会退回余额而不会丢失。
实操规则:
- 这是你的数字。如果你要表达「客户付了 30 天、用了 12 天」,你自己做这个算术并把结果传过来。
- 以变更请求的
currency传入。不会为你做换算。 - 它是对未来扣款的抵扣,不是退款。如果客户应得的是退钱而不是往后抵扣,请改为退还原始扣款——见 退款。
remainingAmount也会在/api/v1/subscription/change/inquiry中返回,所以你可以直接读取剩余值而无需自己跟踪。
套餐变更能同时切换币种或支付方式吗?
两者都可以——变更请求是从零开始描述新订阅的,所以这些只是请求上的字段:
因为
remainingAmount 是以变更请求的 currency 表达的,切换币种意味着你必须用新币种表达结转金额。Waffo 不会为你换算旧币种的余额。
旧订阅上的任何东西都不会被继承。凡是你没有重新声明的都会消失,包括分期金额计划——如果价格阶梯需要保留,请在变更请求中重新声明 scheduledAmounts。
一个变更请求能带多个套餐吗?
productInfoList 是一个列表,每个条目描述一个套餐。把它当作客户要迁移到的一个套餐的结构来用:变更产生的订阅只有一个周期、一个期数和一个金额,所以描述两个不同周期的请求没有连贯的意义。如果客户确实在按不同周期购买两样东西,那应该是两个订阅。
旧订阅是立即停止,还是在周期结束时停止?
两种都有,由你通过startTime 来选择:
第二行就是「升级在下个周期生效」的实现方式,既不重复扣款也不需要自己写调度器。这也是 Waffo 唯一执行的周期末退役——
/api/v1/subscription/cancel 始终是立即生效的,相关内容见
托管管理页。
变更的 startTime 有两个约束:
- 不得早于原订阅的下一次预定扣款。落在客户已付费周期内的开始时间会被拒绝。
- 通用的创建限制仍然适用:必须严格在未来、最多 365 天以内,且在承载新订阅的协议的有效期窗口之内。
客户一直没付升级链接的钱,现在又想换另一个套餐怎么办?
用他们实际想要的套餐再次调用/api/v1/subscription/change。
Waffo 会在这次调用中替你结清待处理的变更:待处理新订阅上未支付的扣款被取消,该新订阅被作为「已替换」关闭,待处理变更转为 CLOSED,原订阅被释放以便在其上构建新的变更。你不需要找支持人员清理,也不需要单独的取消调用——之所以没有「取消变更」接口,正是因为下一次变更会自动完成这件事。
重要的注意事项:结清可能失败,失败时新的变更不会被创建。你会收到以下之一,而待处理变更仍是当前有效的那个:
A0048 和 A0049 容易混淆。A0048 表示钱在流转中,停下来等结果;A0049 表示我们还不知道,再问一次。在 A0048 上重试没有用,而把 A0049 当作致命错误会让客户卡住。
我能一口气同时改金额和改套餐吗?
不能,而且在任一操作进行中时二者互斥。Waffo 按订阅串行化update、change 和 cancel:其中一个在处理时,其他的会以 A0055(“The subscription is being modified, please retry later”)被拒绝。
A0055 可重试。如果你在批量重新定价,把它当作背压而不是失败——但不要对同一订阅并发地发起 update 和 change 并期望两者都成功。
新套餐上的分期金额和试用期会怎样?
什么都不会延续。新订阅的amount、trialPeriodAmount、numberOfTrialPeriod 和 scheduledAmounts 完全来自变更请求。省略 scheduledAmounts,新订阅每期都按新的 amount 扣款。
在升级时授予试用期之前要考虑一点:试用期计数会重新开始,因为这是一个新订阅。已经享受过你试用期的客户,如果你配置了试用期,会再得到一次。
以哪条记录为准?
/api/v1/subscription/change/inquiry,以新的 subscriptionRequest 加 originSubscriptionRequest 为键。它返回变更状态、授权仍在等待时的 subscriptionAction、当前的 remainingAmount,以及你发送的完整新套餐描述。
SUBSCRIPTION_CHANGE_NOTIFICATION 告诉你何时去看;查询接口告诉你什么是真实的。从中持久化新的 subscriptionId,并只在变更读到 SUCCESS 之后才把权益切换到新订阅。
接下来看哪里?
- 订阅创建与校验
——新套餐必须满足的取值范围,以及
startTime规则。 - 订阅金额与分期计划
——
update能做什么,以及为什么没有按比例分摊。 - 订阅到底什么时候扣款? ——新套餐的日期是如何推导的。