Skip to main content
/api/v1/subscription/update 只修改客户已有订阅上的金额,且只能调低。其他一切——不同的周期、更高的价格、不同的套餐、不同的币种——都属于通过 /api/v1/subscription/change 进行的套餐变更。本页是套餐变更的契约说明。仅改金额的变更见 订阅金额与分期计划。

套餐变更到底做了什么?

它不会编辑现有订阅。它会创建一个新订阅,让客户授权,然后让旧订阅退役。
  1. 你调用 /api/v1/subscription/change,传入原订阅的 originSubscriptionRequest,加上新套餐的完整描述和一个新的 subscriptionRequest。
  2. Waffo 创建新订阅并返回一个包含 webUrl 的 subscriptionAction。你把客户引导到该地址去授权新套餐。
  3. 当客户完成授权且新套餐的首次扣款成功时,变更提交:新订阅变为 ACTIVE,原订阅退役。
  4. 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 之后才把权益切换到新订阅。

接下来看哪里?