Advanced Commerce API 退款是 iOS 开发者发起退款的唯一途径,而最终决定权仍在 Apple
大多数 iOS 开发者无法给客户退款。接入 Apple Advanced Commerce API 的 App 可以申请退款、撤销订阅,或退还自定义金额。本文说明每个端点如何运作,Apple 仍可拒绝什么,以及钱在哪些环节容易出错。

要点
- 一位 Apple 工程师在 2026 年 6 月表示,对于普通的 App Store 购买,开发者无法直接发起退款。开发者唯一能提供的,是在回复 CONSUMPTION_REQUEST 时发送的消费数据和 refundPreference。
- 获准使用 Apple Advanced Commerce API 的 App 可以调用 Request Transaction Refund 端点,请求 App Store 为一次性扣款或订阅交易退款,另外还有 Revoke Subscription 和 Cancel a Subscription 端点。
- 要调用 Advanced Commerce API 的退款、撤销和取消端点,开发者的 Account Holder 必须签署 Advanced Commerce API Addendum(补充协议)。Apple 表示,如果未接受最新版本,调用会返回错误。
- Request Transaction Refund 端点的 refundType 可取 FULL、PRORATED 或 CUSTOM。以货币千分之一单位表示的 refundAmount 仅在 CUSTOM 下允许。Apple 表示,除加拿大和美国外,所有地区的金额都必须含税。
- Apple 的 refundRiskingPreference 字段默认为 true,这让 App Store 可以就开发者自己的退款请求发送 CONSUMPTION_REQUEST。Apple 要求在 12 小时内回复。
- Advanced Commerce API 的退款、撤销和取消端点在生产环境中限制为每个 App 每秒 5 个请求,沙盒环境只有其 10%。
- Revoke Subscription 调用成功后,Apple 会发送 REFUND 通知,并要求开发者以其中的 revocationDate 为准终止服务,而不是在通知到达之前。
普通 iOS 开发者无法给客户退款。2026 年 6 月,一位 App Store Commerce Engineer 在开发者论坛上只用一句话回答了这个问题:目前,开发者无法直接发起退款。例外只有一个,就在 Advanced Commerce API 里。获得 Apple 批准的 App 可以发送 Advanced Commerce API 退款请求,撤销订阅并退款,或申请自定义金额。钱退不退,仍由 Apple 决定。
Advanced Commerce API 是什么,谁能用
Apple 于 2025 年 1 月 23 日发布 Advanced Commerce API。它用于处理超大型目录的 Apple App 内购买,包括自定义的一次性购买、订阅,以及带可选附加项的订阅。你不必在 App Store Connect 中逐个创建产品,而是在自己的服务器上定义 SKU,在购买时发送给 Apple。
权限按 App 逐个授予。你需要填写申请表。Apple 的资格页面列出了三种商业模式,必须是 App 的核心业务:
- 超大型一次性购买目录,例如有声书、课堂、课程或小程序。
- 超大型订阅内容目录,每位创作者的内容各自是一个独立订阅。
- 带可选附加项的订阅,附加项与主订阅作为一笔购买一起续订,例如付费频道或体育内容。
如果其他计划需要用到该 API,Apple 也允许 App 申请。Mini Apps Partner Program 就要求使用它。该计划向成员支付托管小程序中合格 App 内购买销售额的 85%。
退款端点后来才加入,而且需要签署协议
2025 年 3 月 24 日发布的 1.1 版新增了 Request Transaction Refund 和 Revoke Subscription。Apple 的计划页面称,提供订阅内容的 App 也可能有资格使用 Cancel、Revoke 和 Refund API,用于处理取消、在购买后验证内容以及管理目录。每个端点页面都附加了同一个条件:你的 Account Holder 必须签署 Advanced Commerce API Addendum,如果未接受最新版本,调用会返回错误。列出各端点适用场景的是 Addendum,而不是文档。
三个端点对比
| Cancel a Subscription | Revoke Subscription | Request Transaction Refund | |
|---|---|---|---|
| 路径 | advancedCommerce/v1/subscription/cancel/{transactionId} | advancedCommerce/v1/subscription/revoke/{transactionId} | advancedCommerce/v1/transaction/requestRefund/{transactionId} |
| 适用范围 | 自动续期订阅 | 一个订阅及其所有项目 | 一次性扣款和订阅交易 |
| 退款 | 无 | FULL 或 PRORATED | FULL、PRORATED 或 CUSTOM,按 SKU |
| 访问权限 | 持续到当前周期结束 | 在 revocationDate 终止 | 通过 revoke 标志逐项设置 |
| 生产环境速率限制 | 每秒 5 个 | 每秒 5 个 | 每秒 5 个 |
Cancel a Subscription 停止下一次扣款
Cancel 会关闭自动续期。Apple 表示,客户在当前周期结束前仍可使用。不退任何款项。如果客户想退出,而且已经用完了付费的时间,这就是正确的选择。
Revoke Subscription 立即终止一切
Revoke 将自动续期设为 false,并以全额或按比例退款的方式撤销订阅。其请求体包含 refundReason、refundRiskingPreference、refundType 和 requestInfo。随后 Apple 会向你的 App Store Server Notifications V2 端点发送 REFUND 通知。Apple 的指示很明确:以该通知中的 revocationDate 为准关闭服务,不要在通知到达之前关闭。
Request Transaction Refund 逐项处理
这是最精确的工具。你提交一个项目列表,每个项目指定 SKU、refundReason、refundType 和 revoke 标志。使用 CUSTOM 时,还要以货币的千分之一单位发送 refundAmount,所以 4990 表示 4.99。如果在 FULL 或 PRORATED 下发送金额,Apple 会以错误 4000155 拒绝。响应包含已签名的交易信息,订阅还会附带已签名的续期信息。
Apple 接受以下 refundReason 值:UNINTENDED_PURCHASE、FULFILLMENT_ISSUE、UNSATISFIED_WITH_PURCHASE、LEGAL、OTHER 和 MODIFY_ITEMS_REFUND。第七个值 SIMULATE_REFUND_DECLINE 仅用于沙盒和 TestFlight 测试。它之所以存在,是因为 App Store 可以拒绝。
Apple 仍可拒绝你自己的退款请求
这个端点的名字很诚实。它只是一个请求。有两个字段说明了决定权真正在哪里。
refundRiskingPreference 会引来消费核查
Apple 对 refundRiskingPreference 的描述是:App Store 是否向你索取消费数据,作为退款决定的依据。它默认为 true。为 true 时,你会就自己的退款请求收到 CONSUMPTION_REQUEST,并通过 Send Consumption Information 回复。Apple 要求开发者在收到 CONSUMPTION_REQUEST 后 12 小时内回复。设为 false,就不会收到这条通知。
告诉你“不行”的错误
| 错误 | 代码 | Apple 的说明 |
|---|---|---|
| AlreadyRefundedError | 4030021 | 该交易已退款 |
| PendingRefundError | 4000181 | 该交易有待处理的退款 |
| TransactionNotRefundableError | 4030024 | 该交易不可退款 |
| TransactionCannotBeRefundedContactSupportError | 4030025 | 客户可以联系 Apple 支持 |
| RefundAmountWithoutCustomError | 4000155 | 未使用 CUSTOM 却发送了金额 |
最需要提前准备的是 PendingRefundError。一个常见原因是:在你的客服团队处理之前,客户已经通过 Report a Problem 向 Apple 提出了申请。Apple 的资格规则本来就要求这类 App 在 App 内提供退款途径,可以是 Report a Problem 链接,也可以是 beginRefundRequest API,所以两扇门会同时敞开。

Advanced Commerce API 退款让你付出的真金白银
主动退款感觉比应对争议更省钱。但钱还是流出去了,而且这个 API 会让某些错误很容易被大规模重复。
自定义金额里的税
Apple 表示,请求的 refundAmount 必须含税,加拿大和美国除外。如果团队按税前 SKU 价格计算 CUSTOM 退款,就会在其他所有店面少退给客户,然后还要花客服时间逐一修正。
收不回来的成本
- 分成支出:在创作者目录或小程序托管平台中,创作者的分成往往在销售时就已支付。给客户退款并不能把这笔钱收回。
- 内容授权:有声书或课程按作品向版权方支付的费用,根据合同可能在访问时就已触发,退款不会撤销这些费用。
- 计算资源:为这笔购买所做的流媒体传输、转码和任何服务器工作,费用已经计入你的账单。
- API 调用:按请求计费的第三方服务,从语音到模型推理,退款之后照样计费。
本想退一个项目,却全额退了
Revoke Subscription 会退款并终止整个订阅,附加项也包括在内。如果客户只对一个附加项有异议,Request Transaction Refund 可以只退该 SKU,并只对该项目设置 revoke。因为一个项目的投诉就调用 Revoke Subscription,会连基础套餐的收入也一并退还。
启用之前的开发检查清单
- 确认你的 Account Holder 已接受当前版本的 Advanced Commerce API Addendum,并在协议失效时针对返回的错误设置告警。
- 每个请求都生成新的 requestReferenceId UUID,只有在重试超时的调用时才复用同一个。
- 把退款调用放入队列。限制是每个 App 每秒 5 个,429 响应会带有以 UNIX 毫秒表示的 Retry-After 头。
- 在沙盒中用 SIMULATE_REFUND_DECLINE 测试拒绝情形,并记住沙盒限制是生产环境的 10%。
- 按具体情况决定 refundRiskingPreference。当它保持为 true 时,准备好消费数据响应程序,以应对 12 小时的回复窗口。
- 只在 REFUND 通知到达时终止访问,并以其中的 revocationDate 为准。
- 记录每个请求的原因、金额和 SKU,这样在 Apple 看到你的退款率之前,你自己先能看到。
常见问题解答
- iOS 开发者能直接给客户退款吗?
- 普通的 App Store 购买不行。一位 Apple 工程师在 2026 年 6 月表示,开发者无法直接发起退款。获准使用 Advanced Commerce API 且已签署 Addendum 的 App,可以通过 Request Transaction Refund 端点申请退款,但仍由 Apple 决定。
- Advanced Commerce API 中的 Cancel 和 Revoke 有什么区别?
- Cancel 关闭自动续期,客户在周期结束前仍可使用,不退款。Revoke 立即终止订阅及其所有项目,并退还全额或按比例的金额。撤销之后,Apple 会发送 REFUND 通知。
- 能用 Advanced Commerce API 退还自定义金额吗?
- 可以。将 refundType 设为 CUSTOM,并以货币的千分之一单位传入 refundAmount。Apple 表示,除加拿大和美国外,所有地区的金额都必须含税。在 FULL 或 PRORATED 下发送金额会返回错误 4000155。
- 我自己申请的退款,也会收到 CONSUMPTION_REQUEST 吗?
- 有可能。refundRiskingPreference 默认为 true,App Store 因此可以通过 CONSUMPTION_REQUEST 向你索取消费数据,Apple 要求在 12 小时内回复。设为 false,Apple 表示就不会发送这条通知。
- 为什么我的 Advanced Commerce API 退款请求失败了?
- 先看错误代码。4030021 表示该交易已退款,4000181 表示已有待处理的退款,4030024 表示不可退款,4030025 表示客户应联系 Apple 支持。未签署或版本过旧的 Addendum 也会返回错误。
来源和延伸阅读
- Apple Developer: Advanced Commerce API eligibility and requirements
- Advanced Commerce API: Request Transaction Refund
- Advanced Commerce API: RequestRefundItem
- Advanced Commerce API: refundRiskingPreference
- Advanced Commerce API: Revoke Subscription
- Advanced Commerce API: Rate limits
- Advanced Commerce API changelog
- App Store Server API: Send Consumption Information
- Apple Developer Forums: Refund option in App Store Server API
- Apple Developer: Mini Apps Partner Program
RefundHalt
App Store 和 Google Play 退款自动驾驶
继续阅读
过多的退款申请,代价可能远超退款本身,因为两大应用商店都把它当作质量信号
Apple 审核指南 5.6.4 把过多的退款申请列为应用未达质量标准的迹象,Google 的开发者分发协议也允许它依据退款率下架新开发者的应用。本文梳理两家商店的原文、下架的真实成本,以及如何避开风险。
在处理退款之前先验证 App Store 服务器通知,因为任何人都能向你的 webhook URL 发送请求
在检查签名之前,一条退款通知只不过是一个 HTTPS 请求。本文介绍如何验证 App Store 服务器通知和 Google Play RTDN 消息、每个商店签名的内容,以及伪造的退款或被错误拒绝的退款会让你付出什么代价。