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

Apple 和 Google 只退各自商店的款,跨平台订阅必须由你在其他所有平台终止访问

当 Apple 或 Google 为跨平台订阅退款时,你的 Android 应用、iPhone 应用和网站并不会自动得知。本文说明如何把每笔商店购买关联到同一个账户、撤销正确的权益,并停止为已退款用户承担服务成本。

桌上并排放着一部 iPhone、一部 Android 手机和一台笔记本电脑,三者都登录着同一个跨平台订阅账户

要点

  • Apple 的 App Review Guideline 3.1.3(b) 允许跨多个平台运营的应用,让用户访问其在其他平台或开发者网站上获得的内容和订阅,前提是这些项目在应用内也以 App 内购买项目的形式提供。
  • Apple 和 Google 只为在自家商店完成的购买退款,因此 Apple 对跨平台订阅的退款不会波及客户在 Google Play 或网站上的计费。开发者的服务器必须在每个平台上移除其授予的访问权限。
  • Apple 在为消耗型项目、非消耗型项目、非续期订阅或自动续期订阅退款时,会通过 App Store Server Notifications V2 发送 REFUND 通知,并明确表示开发者有责任存储、监控并处理每一笔已退款交易。
  • Apple 的 appAccountToken 是开发者附加到 App 内购买的一个 UUID,App Store Server API 的 Set App Account Token 端点可以事后为应用外完成的购买(例如兑换的优惠代码)补充该值。
  • Google Play 的 setObfuscatedAccountId 将购买关联到开发者应用中的账户,长度上限为 64 个字符;如果其中包含电子邮件等明文个人数据,购买将被拦截。
  • Google Play 的 Voided Purchases API 会报告已退款和已发生拒付的购买,附带 orderId 以及 voidedSource,取值 0 表示用户、1 表示开发者、2 表示 Google。
  • 对于 2026 年 8 月 3 日之后下的 Google Play 订单,一旦拒付成立,开发者需承担扣除 Play 服务费后的购买价款,外加银行收取的拒付手续费。

你的订阅用户向 Apple 付了款,当天下午打开了你的 Android 应用,现在又在公司使用你的网站。随后 Apple 给他退了款。Google Play 不知道,你的网站计费系统也不知道。除非你自己的服务器终止访问,否则一个已退款的跨平台订阅会在所有读取你账户数据库的设备上继续可用。商店一次只为一个店面退款,而完整的订阅只存在于你的账户系统中。因此,也只有它能终止这份订阅。

为什么单个商店的退款无法终止跨平台订阅

Apple 明文允许这种做法。App Review Guideline 3.1.3(b),即 Multiplatform Services 条款规定,跨多个平台运营的应用可以让用户访问其在其他平台或你的网站上获得的内容、订阅或功能,前提是这些项目在应用内也以 App 内购买项目的形式提供。

Apple 关于在多个应用中提供同一订阅的指南描述了实际的运作方式。由你的服务器借助统一的账户数据库授予访问权限,每个应用都从中读取。同一指南还提醒,如果某笔购买没有同步到其他应用,用户可能会为同一项服务重复付费。

这种设计有一个常被忽视的后果。权益存放在你的数据库里,但每个商店只知道自己的收据。Apple 可以为 iPhone 上的购买退款并通知你的服务器,却无法通知你的 Android 应用或网站。如果退款处理逻辑只更新 iOS 客户端,客户既拿回了钱,又在其他所有地方保留着订阅。

付款渠道由谁决定退款你的服务器如何得知谁能停止续订
App StoreAppleApp Store Server Notifications V2 中的 REFUND 通知客户本人,在 App Store 订阅设置或你的应用打开的管理页面中操作
Google Play前 48 小时内由 Google 决定,之后由你或 Google 决定Voided Purchases API 和实时开发者通知客户本人,或由你通过 purchases.subscriptionsv2.cancel 操作
你的网站你支付处理商的 webhook你

退款后如何在每个平台撤销访问权限

将每笔商店购买关联到同一个账户

难点在于把退款对应到具体的人,因为每个商店都用自己的方式标识买家。两家都提供了一个字段,供你填写自己的账户 ID。每笔购买都要用上它。

  • 在 Apple 上,于购买开始时设置 appAccountToken,即由你生成的一个 UUID。App Store 会在交易信息和续订信息中返回同一个 UUID。Apple 表示,同一客户的所有交易可以复用同一个值。
  • 如果客户是在你的应用之外购买的,例如在 App Store 中兑换优惠代码,该交易就没有 token。Set App Account Token 端点可以为其补上。对于自动续期订阅,它只作用于当前及之后的续订,不影响过去的交易,而且不适用于通过家人共享获得的购买。
  • 在 Google Play 上,启动结算流程时通过 setObfuscatedAccountId 传入经过混淆的账户 ID。长度上限为 64 个字符。Google 表示,电子邮件等明文个人数据会导致购买被拦截,建议使用加密或单向哈希。

同时监听两家商店,再写入同一条权益记录

Apple 为任何类型的产品退款时都会发送 REFUND,自动续期订阅也包括在内。当 Apple 因客户提出的争议而撤回已批准的退款时,会发送 REFUND_REVERSED。在 Google Play 上,Voided Purchases API 会列出已退款和已拒付的购买,每条都带有 orderId,用于标识具体是哪一次购买或续订。你的网站支付处理商也会发送自己的退款事件。这三者都应进入同一个处理程序,并修改同一条记录。

撤销的是权益,而不是账户

退款取消的是一笔购买,而不是一个人。先移除由这笔已退款购买带来的访问权限,再重新计算该账户还剩哪些权益。如果客户在另一家商店还有有效订阅,就通过那份订阅保留访问权限。如果没有,每个客户端在下一次向你的服务器核验时都会失去高级功能。

同一个人在两家商店都订阅时

重复订阅是问题的另一半。有人在 Android 上订阅,换了新 iPhone 后没有登录,又订阅了一次。现在他为同一项服务付了两份钱,其中一笔通常会变成退款申请。Apple 商务团队在 Apple Developer Forums 上回复开发者时说得很直接:应用的账户系统应当包含防止在另一个平台重复购买的逻辑。

显示付费墙之前先检查所有商店

在显示付费墙之前让用户登录,在服务器上查询他的所有有效购买,如果其中任何一笔已覆盖当前平台,就不再展示购买选项。这一项检查就能在大多数重复扣款发生之前将其拦下。

重复购买已经发生时,应该退哪一笔?

退你能掌控的那一笔。在 Google Play 上,你可以在 Play Console 中自行退款,并通过带 DEVELOPER_REQUESTED_STOP_PAYMENTS 的 purchases.subscriptionsv2.cancel 停止下一次扣款。网站订阅完全由你决定是否退款。App Store 的退款由 Apple 决定,所以如果重复的那份在 iPhone 上,需要客户向 Apple 申请,你的应用可以通过 StoreKit 的退款申请 API 打开该申请。

漏掉某个平台的退款会让你付出什么代价

退款金额只是第一笔损失。如果客户的 Apple 退款从未传达到你的 Android 应用或网站,他会继续使用你花钱运营的服务。每次会话仍在消耗算力,每个 AI 功能仍在调用需要你付费的第三方 API。他的文件仍占用存储空间,如果你的应用按浏览量或使用量向创作者付费,这些分成也会继续发出。对于年度方案,这可能意味着要为一个已不再付费的账户承担整整一年的服务成本。

走银行渠道的情况更糟。对于 2026 年 8 月 3 日之后下的 Google Play 订单,Google 表示,一旦拒付成立,开发者需承担扣除 Play 服务费后的购买价款,外加金融机构收取的拒付手续费。拒付在银行端即为终局。一位发起了拒付却仍保有访问权限的客户,会让你同时损失价款、手续费和服务成本。

漏撤销后仍在持续发生的支出由谁承担
Android 或网页端每次会话的服务器算力你
你的功能所调用的第三方 API你
用户文件和历史记录的存储你
按使用量或浏览量向创作者支付的分成你
2026 年 8 月 3 日之后 Google Play 订单的拒付手续费你,此外还需承担扣除 Play 服务费后的购买价款
一只手拿着智能手机,旁边是一台打开的笔记本电脑,另一部手机屏幕朝下放着,这是跨平台订阅用户的日常配置

跨平台使用记录同样是证据

当商店要求你提供说明时,跨平台统一的账户同样有帮助。Apple 的消耗信息会询问客户消耗了消耗型项目、非消耗型项目或非续期订阅的多大比例。对于自动续期订阅,你无需发送百分比,因为 Apple 会根据已过去的时间自行计算。Google Play 的拒付审核最多接受 1,000 条消耗使用事件,每条都可以附带混淆后的账户 ID。只要使用记录记在同一个账户 ID 下,无论来自哪台设备,都是你可以出示的使用证据。

哪些退款根本不会征求你的意见

大多数退款的决定都与你无关。Google Play 可能会在 48 小时内通过自己的退款流程为购买退款。商店客服退款、作废的购买,以及 Google 对你始终未确认的购买在约 72 小时后自动退款,都是先发生、后通知。对于这些情况,上文的撤销逻辑就是你要做的全部工作。

只有两种流程会要求你提供证据。Apple 的 CONSUMPTION_REQUEST 给你 12 小时发送消耗信息。Google Play 的拒付审核从 PendingRefundReviewNotification 起给你 24 小时,通过 orders.reviewrefund 作出答复,且 Google 只记录你的第一次调用。RefundHalt 会在时限内答复这两类请求,所用的是你已在收集、并在各应用间以同一账户为键的使用数据。

跨平台退款简明检查清单

  • 在 Apple 购买上设置 appAccountToken,在 Google Play 购买上设置混淆后的账户 ID。
  • 对于兑换优惠代码产生的购买,使用 Set App Account Token 补齐缺失的 Apple token。
  • 将 Apple 的 REFUND 和 REFUND_REVERSED、Google Play 的作废购买以及网站退款统一导入同一个处理程序。
  • 存储每笔购买及其来源,并根据所有有效购买计算访问权限。
  • 在任何平台显示付费墙之前,先检查所有商店的购买记录。

常见问题解答

我可以让 iPhone 用户使用他们在 Android 或我的网站上购买的订阅吗?
可以。Apple 的 App Review Guideline 3.1.3(b) 允许跨多个平台运营的应用,让用户访问其在其他平台或你的网站上获得的内容、订阅或功能,前提是这些项目在 iPhone 应用内也以 App 内购买项目的形式提供。
如果 Apple 给订阅用户退了款,Google Play 或我的网站计费系统会知道吗?
不会。Apple 只会通过 App Store Server Notifications V2 中的 REFUND 通知告知你的服务器,不会通知其他任何地方。你的服务器必须移除这笔购买在 Android、网页以及该账户登录的其他任何地方授予的访问权限。
如何把 App Store 的退款对应到用户账户?
使用 appAccountToken,即你的应用附加到购买上的一个 UUID,App Store 会在交易信息中将其返回。对于在应用外完成的购买,例如兑换优惠代码,Apple 的 Set App Account Token 端点可以添加或替换该 token。它不支持家人共享的交易。
一位客户同时在 App Store 和 Google Play 订阅了,应该退哪一份?
退你能掌控的那一份。你可以在 Play Console 中为 Google Play 订单退款,并通过 purchases.subscriptionsv2.cancel 停止其下一次扣款。App Store 的退款由 Apple 决定,因此 iPhone 上的重复订阅要走 Apple 的退款申请,你的应用可以通过 StoreKit 打开该申请。
我网站或 Android 应用上的使用记录,能在退款审核中作为证据吗?
记录在同一账户下的使用数据可以支持你的答复。Apple 的消耗信息会询问消耗型项目、非消耗型项目或非续期订阅被消耗了多大比例,而 Google Play 的拒付审核最多接受 1,000 条可附带混淆账户 ID 的使用事件。

来源和延伸阅读

RefundHalt

App Store 和 Google Play 退款自动驾驶

继续阅读

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

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