所有文章
实战指南阅读需 8 分钟

订阅取消原因通常比退款请求更早到达,而 Google Play 提供的信息远多于 Apple

Google Play 会通过取消调查记录订阅取消原因,Apple 只发送一个到期代码。本文说明两家商店各自告诉你什么,哪些信号预示即将到来的退款或拒付,以及每种情况会让你付出多少成本。

清晨的光线下,一位开发者坐在桌前查看手机上的订阅页面,旁边是记满计数符号的笔记本,正在整理订阅取消原因

要点

  • Google Play 会在订阅者取消时询问离开原因,答案通过 purchases.subscriptionsv2 中的 canceledStateContext.userInitiatedCancellation.cancelSurveyResult 传给开发者。
  • Google Play 的取消调查有五个开发者可读的答案:使用不够多、技术问题、费用相关、找到了更好的应用,以及其他。只有用户选择“其他”时,reasonUserInput 中才会有自由文本。
  • Google Play 的 SUBSCRIPTION_CANCELED 通知只携带购买令牌。取消原因必须通过 purchases.subscriptionsv2.get 获取,而且如果用户恢复订阅,Google 会清空所有取消相关字段。
  • Apple 的 App Store Server API 没有取消调查。它的 expirationIntent 字段给出五个代码之一:客户取消、账单错误、未同意涨价或优惠转换、产品不可用,或其他。
  • Apple 的 DID_CHANGE_RENEWAL_STATUS 通知若带有 AUTO_RENEW_DISABLED 子类型,可能表示客户申请退款后 App Store 关闭了自动续订,而不只是客户自己关掉了它。
  • 取消原因从不会让开发者对退款拥有发言权。只有 Apple 的 CONSUMPTION_REQUEST(需在 12 小时内回复)和 Google Play 通过 orders.reviewrefund 发起的拒付审查(需在 24 小时内回复)会要求你提供证据。
  • 因技术问题取消的 Google Play 订阅者最有可能想要退款。对于 2026 年 8 月 3 日之后下的订单,若对方拒付成功,开发者将损失购买价格减去 Play 服务费的部分,外加银行收取的费用。

大多数最终获得退款的订阅者都会先取消订阅。取消会附带一个原因,而两家商店给你的信息量差别很大。Google Play 会做一个简短的调查,并把答案(包括自由文本)传给你的服务器。Apple 只发送一个数字代码,说明订阅是怎么结束的,而不是客户为什么想离开。把两者都读懂,你就能在还来得及采取行动时,提前看到退款请求的到来。

Google Play 告诉你哪些订阅取消原因

用户在 Play 订阅中心取消时,Google 会询问原因。答案出现在你通过 purchases.subscriptionsv2.get 获取的订阅资源中,位于 canceledStateContext 之下。这个对象只在订阅处于已取消或已过期状态时存在,它会说明是谁结束了订阅:用户、Google 的系统、你,或者是替换操作(例如更换套餐)。

如果是用户取消的,userInitiatedCancellation 对象会包含两个字段。cancelTime 表示取消时间,cancelSurveyResult 保存调查答案。

调查原因Google 的描述它通常意味着什么
CANCEL_SURVEY_REASON_NOT_ENOUGH_USAGE订阅使用不够多使用量低,账户上投入的成本很少
CANCEL_SURVEY_REASON_TECHNICAL_ISSUES使用应用时遇到技术问题最强烈的退款和拒付信号
CANCEL_SURVEY_REASON_COST_RELATED费用相关问题对价格敏感,有时是意料之外的续订
CANCEL_SURVEY_REASON_FOUND_BETTER_APP用户找到了更好的应用竞争对手胜出,很少引发争议
CANCEL_SURVEY_REASON_OTHERS其他原因查看 reasonUserInput,即用户自己的原话
CANCEL_SURVEY_REASON_UNSPECIFIED未指定的取消调查原因没有可用的答案

最右一列是我们的解读,不是 Google 的说法。前两列直接来自 API 参考文档。

通知本身不包含原因

订阅被取消会触发 SUBSCRIPTION_CANCELED 实时开发者通知,类型为 type 3。Google 明确表示,这类通知只告诉你购买状态发生了变化。负载中只有一个购买令牌,没有其他有用信息,所以你的处理程序必须调用 purchases.subscriptionsv2.get 才能读取调查答案。

Play Console 中的视图

查看汇总数据不需要写代码。Play Console 的订阅报告中有一张“取消”卡片,把流失分为自愿、非自愿和其他三类,还有一张“取消调查回复”卡片,展示选择作答的用户。选择“其他”的用户所填写的自由文本,可以从“其他回复”卡片下载为 CSV。下载需要 View financial data 权限,也就是你授予读取订单的工具的同一项权限。

Apple 告诉你什么,又省略了什么

Apple 没有任何会向开发者反馈结果的取消调查。最接近的字段是签名续订信息中的 expirationIntent,它描述的是订阅如何结束,而不是客户怎么想。

expirationIntentApple 的含义对应的 EXPIRED 子类型
1客户取消了订阅VOLUNTARY
2账单错误,例如付款信息无效BILLING_RETRY
3未同意需要确认的涨价或优惠转换PRICE_INCREASE
4续订时该产品无法购买PRODUCT_NOT_FOR_SALE
5其他原因无子类型

代码 1 是唯一描述客户主动选择的代码,但它完全不说明动机。因为应用频繁崩溃而离开的客户,和只是刚好完成了一个项目的客户,看起来一模一样。

藏在 AUTO_RENEW_DISABLED 里的信号

有一个 Apple 通知值得仔细看。带有 AUTO_RENEW_DISABLED 子类型的 DID_CHANGE_RENEWAL_STATUS 通常表示客户关闭了自动续订。Apple 的文档还补充了第二种情况:客户申请退款后,App Store 也会关闭自动续订。

因此在 iOS 上,一个关闭续订的事件可能是退款请求的第一个迹象。如果购买的是消耗型项目或自动续期订阅,随后可能会收到 CONSUMPTION_REQUEST,从那一刻起你有 12 小时发送消耗数据。如果关闭续订事件到来时,你的应用里看不到任何相应操作,就值得把它当作提醒,提前准备好该账户的使用数据。

Apple 与 Google 对比

Google PlayApple App Store
是否询问用户原因是,有取消调查没有开发者可见的调查
原因存放位置purchases.subscriptionsv2 中的 canceledStateContext续订信息中的 expirationIntent
自由文本reasonUserInput,仅限“其他”无
谁取消的用户、系统、开发者或替换操作根据代码和子类型推断
通知SUBSCRIPTION_CANCELED,然后调用 getDID_CHANGE_RENEWAL_STATUS、EXPIRED
用户重新订阅后是否丢失是,恢复时被清空续订信息反映当前状态
控制台“取消调查回复”卡片没有原因相关视图
木桌上的打印调查卡片被分成几小堆,旁边放着一部手机和一杯咖啡,就像开发者在给订阅取消原因分类

取消在什么时候变成退款

取消会停止下一次扣款,但不会退回上一次的款项。钱能否退回,取决于客户接下来进入哪个退款流程,而这些流程大多不需要你参与。

  • 在 Google Play 上,买家可以在购买后 48 小时内自行获得退款,由 Google 决定。
  • 通过 Google 或 Apple 客服申请的退款,由商店决定。
  • Apple 的 CONSUMPTION_REQUEST 会向你索取消耗数据,回复时限为 12 小时。
  • Google Play 的拒付审查通过 orders.reviewrefund 向你索取证据,回复时限为 24 小时。银行对拒付的裁决是最终结果。

取消原因不会改变以上任何规则。它改变的是你能多早知道哪位客户不满意,以及当两个需要证据的流程之一到来时,你的证据是否已经准备好。

每种原因会让你付出多少

调查答案也能粗略反映一个账户已经花掉了多少服务成本,这正是退款后由你承担的那部分钱。

技术问题

这是代价最高的一种。客户用得足够多才会遇到问题,所以你已经为他们的会话支付了计算资源、为他们的请求支付了模型 API 调用、为他们创建的内容支付了存储,还可能要向他们使用过其内容的创作者支付分成。如果他们随后获得退款,货款会退回,而这些成本仍由你承担。如果他们在 Google Play 上找银行拒付,2026 年 8 月 3 日之后下的订单会让你损失购买价格减去 Play 服务费的部分,外加银行收取的费用。

费用相关

价格投诉的实际成本比看起来要低,除非背后藏着一次意料之外的续订。那正是典型的拒付情节,所以要检查取消是否紧跟在一次续订扣款之后,以及你的续订提醒是否已经发出。

使用不够多

使用量低意味着服务成本低,所以这类退款退回的大多是你没花多少成本就赚到的钱。如果 Apple 要求提供消耗数据,诚实的数据也能清楚展示客户用了什么、没用什么。

找到了更好的应用

这些客户很少提出争议,他们只是转投了竞争对手。这个原因对产品决策有用,但几乎帮不上退款防御。

读取取消原因的日常流程

  • 每次收到 Google Play 的 SUBSCRIPTION_CANCELED,都调用 purchases.subscriptionsv2.get,并把 canceledStateContext 连同购买令牌和 cancelTime 一起保存。
  • 当原因是“其他”时,原样保存 reasonUserInput。这是两家商店中唯一会给你的自由文本。
  • 每次收到 Apple 带有 AUTO_RENEW_DISABLED 的 DID_CHANGE_RENEWAL_STATUS,都记录该事件并调出该账户的使用数据,以防随后收到 CONSUMPTION_REQUEST。
  • 每次收到 Apple 的 EXPIRED 通知,都记录子类型和 expirationIntent,避免把自愿流失和账单失败混在一起。
  • 对于以技术问题为由取消的 Google Play 订阅,检查该账户的错误日志,并在客户找银行之前主动联系对方。
  • 保留每个账户的使用日志,这样 CONSUMPTION_REQUEST 能在 12 小时内得到回复,拒付审查能在 24 小时内得到回复。

常见问题解答

如何查看 Google Play 订阅者取消的原因?
调用 purchases.subscriptionsv2.get,读取 canceledStateContext.userInitiatedCancellation.cancelSurveyResult。其中的原因字段保存调查答案,用户选择“其他”时,reasonUserInput 保存自由文本。Play Console 也会在“取消调查回复”卡片中显示汇总数据。
Apple 会告诉开发者客户为什么取消订阅吗?
不会。Apple 没有开发者可见的取消调查。expirationIntent 字段说明订阅如何结束,代码分别对应客户取消、账单错误、未同意涨价、产品不可用或其他,但不包含客户的动机。
SUBSCRIPTION_CANCELED 通知包含取消原因吗?
不包含。Google Play 的实时开发者通知只告诉你购买状态发生了变化。你需要用 purchases.subscriptionsv2.get 获取订阅来读取原因,并立即保存,因为如果用户恢复订阅,Google 会清空取消相关字段。
Apple 的 AUTO_RENEW_DISABLED 通知可能意味着退款请求吗?
可能。Apple 的文档说明,AUTO_RENEW_DISABLED 子类型既包括客户自己关闭自动续订,也包括客户申请退款后 App Store 关闭自动续订。
订阅者取消后,我可以撤销其访问权限吗?
在 Google Play 上,只要用户仍有权使用就不可以。Google 表示,已取消的订阅者在当前计费周期结束前保留访问权限,提前撤销访问违反 Google Play 的订阅政策。请根据 expiryTime 决定访问何时结束。

来源和延伸阅读

RefundHalt

App Store 和 Google Play 退款自动驾驶

继续阅读

下一项退款请求已经在路上。

读完又一封关于未能申辩退款的支持邮件所需的时间,足够您完成 RefundHalt 设置。