订阅退款与一次性退款的运作方式不同,而你能有多少话语权由所在的商店决定
订阅退款撤销的是整个计费周期,而不是单笔销售。在 App Store 上,由 Apple 做决定,你的服务器只会得知结果。在 Google Play 上,你自己选择全额退款还是按比例退款。下面介绍每家商店如何处理订阅退款,以及一笔退款会让你付出什么代价。

要点
- 订阅退款和一次性退款不一样。被撤销的单位是一个计费周期,而且在两家商店上,对订阅订单退款都会取消订阅并切断访问权限。
- 在 App Store 上,每一笔订阅退款都由 Apple 决定。客户在 reportaproblem.apple.com 向 Apple 提出申请,Apple 做出裁定,你的服务器只能通过 REFUND、REFUND_DECLINED 或 REFUND_REVERSED 通知得知结果。
- 当 Apple 批准订阅退款时,该交易会获得一个 revocationDate,并且订阅的 autoRenewStatus 被设为 false,因此它会停止续订,客户失去访问权限。
- Apple 按已过去的时间来衡量自动续订订阅,而不是按你的用量指标。某人在年度套餐中已过去六个月,就消耗了约 50%,GRANT_PRORATED 是你能为它表达的唯一退款偏好。
- 在 Google Play 上,退款由你自己发起。purchases.subscriptionsv2.revoke 接受 fullRefund(退还整个当前周期)或 proratedRefund(只退还未使用的权益时间)。
- 你在 Google Play 上对哪一笔订单退款会改变结果。对最近一笔订单退款,订阅会立即被移除,未来的续订被取消。对较早的一笔订单退款,订阅仍然有效。
- Google Play 的限制很严格。超过 three years 的订单无法退款,部分退款仅适用于 March 2018 之后下的订单,不适用于付费应用,而且退款一经发放就无法撤销。
对订阅退款和对单笔应用内购买退款,感觉像是按同一个按钮。其实不是。一次性购买是你退还的一笔扣款。订阅是带有实时权益的循环扣款,因此订阅退款必须回答两个一次性退款从不会问的问题:当前周期你退还多少,以及订阅是否继续运行。App Store 和 Google Play 对这两个问题给出的答案正好相反,而这种差异决定了你能掌控多少,以及有多少钱离开你的账户。
这是简明的对照图。在 App Store 上,Apple 拥有决定权,你事后才得知。在 Google Play 上,你掌握控制权,自己选择全额还是按比例。本文会走一遍两家商店、每家使用的确切字段和通知、当订阅已多次计费时你该处理哪一笔订单,以及一旦把你已经花掉的算力算进去,订阅退款实际会让你付出什么。
订阅退款与一次性退款有何不同
两家商店都把退款视为撤销某一笔特定订单。对于一次性购买,只有一笔订单,因此没什么可选。订阅是一串订单,每个计费周期一笔,并附带一项处于激活或未激活状态的权益。正是这种结构,让订阅退款带有一次性退款所没有的选择。
被撤销的单位是一个计费周期
当你为订阅退款时,你并不是在退还一辈子的付款。你处理的是这串订单中的一笔,通常是最近的一笔,也就是单个计费周期。全额退款退还整个周期。按比例退款只退还客户尚未使用的那部分周期。无论哪种,你撤销的销售都是一个周期的价格,而不是客户在应用上的全部历史。
谁来决定才是真正的区别
更鲜明的分野在于权限。在 App Store 上,是否发生订阅退款完全由 Apple 决定,你顶多提供一些背景信息。在 Google Play 上,由你决定,API 严格照你说的执行。对客户来说结果一样,但开发者所处的位置完全不同,这也改变了你要为处理各自情况而构建的东西。
App Store 如何处理订阅退款
在 Apple 这边,你是个拿着小话筒的旁观者。客户与 Apple 沟通,Apple 做出裁定,你的服务器读取结果。
客户向 Apple 申请,由 Apple 裁定
App Store 客户在 reportaproblem.apple.com 申请订阅退款,而不是找你。Apple 依据自己的信号审核请求并决定。你不批准它,也没有哪个 Apple 控制台按钮能让你像在 Google Play 那样发放订阅退款。Apple 自购买起最多有 90 days 的时间来受理审核请求,而一旦它做出裁定,决定权就在 Apple。
退款到达时你的服务器会看到什么
你通过 App Store Server Notifications V2 得知结果。已批准的退款会以 REFUND 通知到达,该交易现在带有一个标记访问权应何时结束的 revocationDate。订阅的 autoRenewStatus 被设为 false,因此它停止续订,客户失去权益。如果 Apple 拒绝了请求,你会收到 REFUND_DECLINED;如果 Apple 后来撤销了它已经批准的退款,你会收到 REFUND_REVERSED,订阅会恢复。你的工作是读取这些通知并切换访问权,而不是投票。
| 通知 | 含义 | 你要做什么 |
|---|---|---|
| REFUND | Apple 批准了退款;该交易获得一个 revocationDate | 撤销访问权,将 autoRenewStatus 视为 false |
| REFUND_DECLINED | Apple 拒绝了客户的退款请求 | 一切不变;订阅继续有效 |
| REFUND_REVERSED | Apple 撤销了它已批准的退款 | 恢复访问权和这笔销售 |
Apple 按时间而非你的指标来衡量订阅
对于消耗型商品,你可以通过消耗数据告诉 Apple 使用了多少。对于自动续订订阅,Apple 会自行根据已过去的时间计算消耗。Apple 自己的例子是一位在年度订阅中已过去六个月的客户,已消耗其中约 50%。所以你的用量指标并不决定订阅的这个数字。你唯一能拉动的杠杆是 refundPreference,而对于订阅,相关的值是 GRANT_PRORATED,它表示你希望 Apple 只退还未使用的部分。这是一种偏好,不是决定。仍然由 Apple 裁定。
Google Play 如何处理订阅退款
Google Play 把决定权交到你手里。有一个 Play Console 界面和一组 API 方法,让你直接为订阅退款、选择退多少,并决定是否结束访问权。这与 Apple 的姿态正好相反,也伴随着你必须做对的选择。
全额还是按比例,由你决定
当前退款并撤销订阅的方式是 purchases.subscriptionsv2.revoke,调用时带上一个 revocationContext。传入 fullRefund,Google Play 会终止订阅并退还当前计费周期的全部金额。传入 proratedRefund,Google Play 会终止订阅,只退还剩余的、未使用的权益时间。较旧的方法只能做全额退款,这正是使用较新方法的理由。按比例撤销是一个两行的请求体,一个包裹着 proratedRefund 的 revocationContext,你把它换成 fullRefund 就能退整个周期。任何一种撤销都会触发一条 SUBSCRIPTION_REVOKED 实时开发者通知,这就是你切断访问权的信号。
你对哪一笔订单退款会改变结果
Google Play 还允许你通过 orders.refund 在不撤销的情况下为订单退款,这里有一条微妙的规则会起作用。如果你对订阅中最近的一笔订单退款,该订单被退款,订阅会立即被移除,未来的续订被取消。如果你对这串订单中较早的一笔退款,那笔订单被退款,但订阅仍然有效。在 orders.refund 上,revoke 参数只在订单是最近一笔时才会撤销,因此要结束一个有效订阅的访问权,你应改用 purchases.subscriptionsv2.revoke。
| 操作 | 被退款的订单 | 订阅会怎样 |
|---|---|---|
| 对最近一笔订单退款 | 最新的计费周期 | 立即移除,未来续订被取消 |
| 对较早的一笔订单退款 | 过去的一个计费周期 | 仍然有效,继续续订 |
| subscriptionsv2.revoke,全额或按比例 | 当前周期 | 立即终止,发送 SUBSCRIPTION_REVOKED |

让开发者栽跟头的那些限制
有几个硬性的边界会绊住人,而且没有一个位于顺利路径上。
- 超过 three years 的订单根本无法退款。
- 部分退款仅适用于 March 2018 之后下的订单,且永远不适用于付费应用购买。
- 你可以在一笔订单上叠加多次部分退款,但总额不能达到或超过订单金额。
- 退款一经发放就无法撤销。
Google Play 通常在一天内返回退款决定,不过也可能长达四天。当退款需要反映到你自己的访问控制中时,要为这段延迟做好准备。
订阅退款实际会让你付出什么
被退还的扣款从来都不是全部账单。订阅订单被交付的那一刻,你就已经为它花掉了真金白银:算力、模型 API 调用、存储,以及与该周期挂钩的任何分成支付。退款退还的是销售额。它不退还你为提供服务所花掉的东西。对订阅而言,损失的形态取决于你发放哪种退款。
全额还是按比例,是一个关于钱的决定
在 Google Play 上,全额退款退回整个当前周期,因此你损失整个周期的收入,同时保留你在该周期已经产生的每一笔成本。按比例退款只退回未使用的那一小块,因此你保留客户实际拥有的那部分收入。如果客户在一个 10 美元的月度套餐中已过完 60%,全额退款会让你损失整整 10 美元,而按比例退款只让你损失约 4 美元,即未使用的 40%。Apple 在确定订阅退款额度时,在它那一侧也采用同样的按已过时间计算的逻辑。
| 退款类型 | 客户拿回什么 | 你保留什么 |
|---|---|---|
| 全额退款 | 整个当前周期,10.00 | 本周期一无所留 |
| 按比例退款 | 未使用的 40%,约 4.00 | 已使用的 60%,约 6.00 |
那些永远回不来的成本
无论你发放哪种退款,该周期的下游成本都已经没了。你付费的一次模型 API 调用、你渲染的一段视频、你预置的存储、你已经发出的一笔创作者分成,当订阅退款结清时,这些都不会逆转。按客户实际使用的量来确定退款额度,永远不要按他们订阅了多久,因为已过去的时间不是成本,两家商店也都不把它当成成本。而且在 August 3, 2026 之后,如果一笔 Google Play 订阅扣款以银行拒付而非你发放的退款收场,你还要承担银行的拒付费用,而先由你主动发放退款则可以避免这笔费用。
如何在无人盯守的情况下处理订阅退款
这一切都不应该等着某人去看仪表盘。通知在任何时刻都会到达,访问权应在退款落地的那一刻切换,而不是等到第二天早上。
读取结果并在两家商店上撤销访问权
在 App Store 上,监听 REFUND、REFUND_DECLINED 和 REFUND_REVERSED,并利用 revocationDate 和 autoRenewStatus 自动结束或恢复访问权。在 Google Play 上,监听 SUBSCRIPTION_REVOKED 和已作废购买的信号,做同样的事。这就是 RefundHalt 为你运行的管道:通知进来,匹配账户,切换访问权,无人介入。
在争议发生前就备好证据
那些确实需要你输入的狭窄窗口,Apple 针对消耗型商品的 12 小时 CONSUMPTION_REQUEST 和 Google Play 的 24 小时拒付审核,只有在证据已经存在时才有用。给每一笔购买附上一个账户标识符,在 Apple 上是一个 appAccountToken UUID,在 Google Play 上是一个 64 characters 或更短的哈希 setObfuscatedAccountId,并记录每个付费周期交付了什么。这样当令牌到达时,案件已经建好,在窗口内作答就成了机器的活儿,而不是一场手忙脚乱。
常见问题解答
- 为订阅退款和为一次性购买退款不一样吗?
- 不一样。一次性购买是你退还的单笔订单。订阅是一串带有实时权益的订单,因此订阅退款作用于一个计费周期,同时还决定订阅是否继续运行。在 App Store 和 Google Play 上,对订阅订单退款都会取消订阅并结束访问权,而且你通常可以在退还整个周期还是只退未使用部分之间选择。
- 开发者能直接发放 App Store 订阅退款吗?
- 不能。App Store 订阅退款由 Apple 决定。客户在 reportaproblem.apple.com 提出申请,Apple 做出裁定,你通过 REFUND、REFUND_DECLINED 或 REFUND_REVERSED 通知得知结果。你能提供的唯一输入是一个 refundPreference,比如 GRANT_PRORATED,而 Apple 把它当作偏好,不是决定。
- 如何在 Google Play 上发放按比例的订阅退款?
- 调用 purchases.subscriptionsv2.revoke,将 revocationContext 设为 proratedRefund。Google Play 会终止订阅,只退还剩余的、未使用的权益时间,然后发送一条 SUBSCRIPTION_REVOKED 通知。改为传入 fullRefund 则退还整个当前周期。较旧的撤销方法只能做全额退款。
- 为什么我的 Google Play 退款没有取消订阅?
- 因为你退款的是这串订单中较早的一笔。在 Google Play 上,对最近一笔订单退款会立即移除订阅并取消未来的续订,但对较早的一笔订单退款只会退还那个周期,而订阅仍然有效。orders.refund 上的 revoke 参数只在订单是最新一笔时才撤销,所以要结束一个有效订阅,请使用 purchases.subscriptionsv2.revoke。
- 订阅订单最早可以追溯到多久前退款?
- 在 Google Play 上,超过 three years 的订单无法退款。部分退款仅适用于 March 2018 之后下的订单,且永远不适用于付费应用,退款一经发放也无法撤销。在 App Store 上,Apple 自购买起最多受理 90 days 的客户退款请求,并各自做出裁定。
来源和延伸阅读
- Android Developers: Manage subscriptions and one-time purchases
- Play Console Help: Manage your app's orders and issue refunds
- Google Play Developer API: orders.refund
- Google Play Developer API: purchases.subscriptionsv2.revoke
- Google Play Help: Refund policies for apps, games, and in-app purchases
- Apple Developer: Handling refund notifications
- Apple Developer WWDC21: Support customers and handle refunds
RefundHalt
App Store 和 Google Play 退款自动驾驶
继续阅读
儿童未经授权的应用内购买几乎每次都会退款给家长,而成本由你承担
当孩子在家长的手机上购买一个金币包时,Apple 和 Google 都会退款,而且都不会先征询你的意见。监管机构就是这样设计的。下面介绍这些未经授权的应用内购买退款在每个商店如何运作、资金流失的那 15 分钟窗口,以及一次退款到底会让你付出多少代价。
应用退款税从来不是你的,所以退款损失的是你的那一份,而不是收据上的总额
为一笔应用内购买办理退款,收据上会显示价格加税一并退回。那笔税从来都不是你的钱。Apple 和 Google 作为登记商户负责收取并上缴,退款时再以同样方式冲回,完全不动你的那一份。这篇讲清楚一笔退款到底损失多少,以及唯一一种让税变成你责任的设置。