一位用户向 Apple 申请退款。十二小时后,你服务器上的一个窗口悄然关闭,而大多数团队甚至不知道它曾经打开过。
这个窗口属于 Apple CONSUMPTION_REQUEST——这是 App Store 在评估退款申请期间向你索取信息时发送的一条通知。它不是退款,也不是裁决。无论如何,最终的退款决定都由 Apple 做出。这条通知给你的,只是一次有限的机会,用来说明这笔购买实际发生了什么。
把它处理好是一个后端问题,而不是客服问题。通知必须能送达,交易必须能识别,用户同意状态必须已知,响应必须按时发出。
本文将说明这条通知的含义、Apple 目前要求提供哪些内容(字段列表比以前短得多),以及如何围绕它构建工作流。关于整体流程,可以先阅读我们的 App Store 退款管理指南了解背景。
要点速览
• CONSUMPTION_REQUEST 是 Apple 在退款评估期间向你索取信息,并不是退款通知。
• 最终退款决定由 Apple 做出。你的响应只是多项参考因素之一。
• 当前端点只接受五个字段,其中三个为必填——旧版本需要十二个。
• 用户同意是强制要求。如果 customerConsented 不为 true,Apple 会拒绝该请求。
• Apple 要求在收到通知后 12 小时内做出响应。
• 由于窗口很短,且通知随时可能到达,这一环节更适合自动化,而不是人工处理。
什么是 Apple CONSUMPTION_REQUEST?
CONSUMPTION_REQUEST 是一种 App Store Server Notification,用于告知你某位用户已向 Apple 申请退款,并且 App Store 邀请你提交关于该笔购买的消费信息。
面向开发者的 Apple 消费信息请求之所以存在,是因为信息存在缺口。Apple 能看到交易、账户和购买历史,却看不到你的应用内部发生了什么——内容是否已交付、是否正常运行、用户实际使用了多少。而你能看到。
有一点它绝对不是:否决权。你的响应不会阻止退款,Apple 也明确表示会综合权衡多种因素。
Apple CONSUMPTION_REQUEST 如何运作?
整个流程如下:
用户申请退款
↓
Apple 开始评估该申请
↓
CONSUMPTION_REQUEST 到达你的通知端点
↓
你验证通知并识别交易
↓
你检查用户同意状态并收集真实使用数据
↓
在满足要求的前提下,你发送消费信息
↓
Apple 做出退款决定
↓
REFUND 或 REFUND_DECLINED 到达;你更新状态
值得注意的是:在 Apple 当前的端点上,任何产品类型的退款申请都可能触发这条通知——消耗型、非消耗型、非续期订阅或自动续期订阅。旧文档和大多数第三方文章仍然说它只适用于消耗型商品和自动续期订阅。如果你的处理程序据此按产品类型过滤,那么它正在丢弃请求。
Apple 要求开发者提供哪些信息?
比以前少。这是大多数现有资料出错的地方,因此有必要说得精确一些。Apple 当前的 Send Consumption Information 端点接受五个字段——三个必填,两个可选。
字段 | 是否必填 | 对你意味着什么 |
customerConsented | 是 | 必须为 true,否则 Apple 会拒绝该请求。 |
deliveryStatus | 是 | 你的应用是否成功交付了可正常使用的购买内容。 |
sampleContentProvided | 是 | 用户在购买前是否获得了试用内容。 |
consumptionPercentage | 否 | 购买内容已被消费的比例,以毫单位(milliunits)表示。 |
refundPreference | 否 | 你倾向的处理结果:全额退款、拒绝退款或按比例退款。 |
有两个限制经常让人栽跟头。如果 deliveryStatus 不是已交付,consumptionPercentage 必须为零,否则请求会失败。另外,毫单位不是百分比——消费一半应写为 50000,而不是 50。
可选的退款倾向字段是较新加入的,值得了解。你可以表明自己倾向于全额退款、拒绝退款还是按比例退款。这是一种倾向,不是指令——Apple 会将其与其他所有因素一并权衡,最终结果可能与你的要求不同。
如果 Apple 批准了按比例退款,被撤销的部分会体现在交易载荷中,因此你的权益逻辑可能需要处理部分撤销,而不是把每次退款都当作全有或全无。
Apple 为什么需要消费信息?
因为 Apple 要做的决定,它自己只能看到一部分。
Apple 知道买了什么、何时购买、由哪个账户购买,以及该账户的历史记录。它不知道你的服务器是否发放了金币、解锁的功能是否正常运行,或者用户在申请退款前是否已经大量使用了该产品。这些上下文存在于你的系统中。
CONSUMPTION_REQUEST 的 Apple 退款流程,就是 Apple 在做决定之前获取这些上下文的方式。这也是为什么准确比辩护更重要。这些数据是对事实的描述,不是你在为自己申辩的案子——如果那样对待它,风险是实实在在的,回报却没有保证。
开发者如何响应 CONSUMPTION_REQUEST
八个步骤。大部分工作在请求到达之前就已完成。
1. 接收通知
App Store CONSUMPTION_REQUEST 通知会发送到你为 App Store Server Notifications V2 配置的服务器 URL。如果该端点缺失、未经验证或悄无声息地出错,请求就永远到不了你手里。Apple 的 App Store Server Notifications 文档涵盖了配置方法和载荷格式。
2. 验证通知
通知以签名的 JWS 载荷形式到达。在对其中任何内容采取行动之前,先根据 Apple 的证书链验证签名,并确认 bundle ID 与你的应用匹配。一个来者不拒、未经验证的端点,等于给了别人操控你退款逻辑的机会。
3. 识别交易
解码后的载荷包含交易标识符。你需要有已存储的购买记录与之匹配。没有记录就无法查找——也就无法就消费情况说出任何有用的信息。
4. 将交易匹配到正确的用户
在弄清是哪位用户之前,你无法描述这位用户的使用情况。这种映射正是 appAccountToken 的用途所在:它是你的应用在购买时附加的一个 UUID,会随通知载荷一起返回。没有它,团队只能依靠时间戳和启发式规则来匹配,而这恰恰在最需要速度的时刻既慢又不可靠。
5. 检查适用的用户同意要求
Apple 在这一点上毫不含糊:在共享用户数据之前,你必须获得有效同意,而获取同意是你的责任,不是 Apple 的。通知本身不带任何同意标记,因此你必须从自己的记录中得知。
如果用户未同意,Apple 的指导是根本不要响应。把同意字段设为 false 再发送请求是行不通的——App Store 会拒绝。Apple 还明确说明,App Tracking Transparency 提示不是用于此目的的机制;这是一项单独的同意,需要在你的应用内收集。
6. 收集真实的使用信息
从你的实际记录中提取交付状态和消费数据。如果你的服务器跟踪消耗型商品余额,你已经知道花掉了多少。如果某项功能解锁失败,你的日志同样记录在案。不要估算——编造的消费数字,就是在你为"准确数据"取得的同意之下向 Apple 发送不准确的数据。
7. 发送相应信息
使用通知中的原始交易标识符,向消费信息端点发送 PUT 请求进行响应。要处理错误响应,而不是发完就不管:验证失败会返回 HTTP 400 和具体的错误类型,如果没人检查,一次静默失败的调用看起来和成功的调用一模一样。
8. 记录结果
记录下请求、交易、你发送的内容、发送时间,以及 Apple 最终的决定。有了这份记录,你才能在几周后回答客服问题、发现各次退款之间的规律,并确认权益状态是正确的。退款生效后, 撤销退款后的访问权限——并做好准备,一旦 Apple 之后撤回决定,就恢复访问。
如果开发者错过了 CONSUMPTION_REQUEST 会怎样?
不会有什么戏剧性的后果,而这正是问题的一部分。
错过响应意味着你没有提供 Apple 允许你在该流程中提交的补充信息。Apple 照样会做决定。退款可能仍会基于 Apple 已有的信息被批准或拒绝。没有错误,没有警报,也没有任何明显的迹象表明有什么被跳过了。
错过的方式都很平常。通知在凌晨 2 点到达。负责处理程序的工程师正在休假。交易查找拖拖拉拉,因为标识符在一个系统里,使用数据却在另一个系统里。有人在周一才看到它,而窗口早已关闭。
为什么人工处理 CONSUMPTION_REQUEST 很困难
这个工作流中的每一项约束都指向同一个结论:不适合人工处理。
通知全天候到达。窗口只有 12 小时。每个请求都需要交易查找、用户匹配、同意检查、使用量计算、签名 API 调用和结果记录——七个步骤,没有一个有趣,每一个都有时限。
每周一个请求时,它只是个小麻烦。每天三十个时,它就成了某个人的全职工作——做好了没有任何产出,做晚了就是无声的损失。
自动化如何改变退款工作流
自动化不会让你左右 Apple 的决定。这一点值得重复,因为很多营销宣传暗示的恰恰相反。Apple 的决定始终属于 Apple。
自动化能做的,是让你这一侧保持一致。通知得到监控和验证。相关请求从数据流中被分离出来。交易被匹配到账户。响应数据从真实记录中组装,截止时间被跟踪,响应被提交并记录,结果则反馈到权益更新中。
这些步骤没有一个需要判断力。但每一个都需要在正确的时刻投入注意力,而这一点软件比人做得更好。
App Store 退款管理软件应该承担哪些工作?
如果你正在评估 App Store 退款管理软件,真正有用的问题是:它能否补上上面提到的那些具体缺口。
它应该监控并验证 App Store Server Notifications,这样事件不会消失在一个故障端点里。它应该单独跟踪 CONSUMPTION_REQUEST 事件,因为它们需要与退款结果不同的处理方式。它应该把交易匹配到账户,因为人工时间正是耗在这里。它应该跟踪响应窗口,因为这正是人们会错过的截止时间。
除此之外:尊重同意状态的消费数据工作流、可搜索的退款历史、结果跟踪、包含部分撤销在内的权益同步,以及清晰到足以呈现规律的报表。重要的是对整个工作流的覆盖程度,而不是功能列表的长度。
这些规则记录在哪里
三份 Apple 文档涵盖了上述所有内容。请直接阅读原文——这个领域最近有所变化,大量二手资料描述的仍是旧版本的 API。
Send Consumption Information——当前端点。涵盖同意要求、12 小时窗口、五字段请求体,以及消费信息适用于所有产品类型这一事实。对于标准 In-App Purchase,应以此为准进行开发。
App Store Server Notifications——通知如何到达你的后端、签名载荷格式,以及各种通知类型,包括 CONSUMPTION_REQUEST、REFUND 和 REFUND_DECLINED。
Send Consumption Information V1——早期端点,采用十二字段请求体,有些团队仍在对接它。Apple 在该页面上的说明明确指引标准 In-App Purchase 改用当前端点,并将 V1 的适用范围限定于使用 Advanced Commerce API 的购买。它适合用来判断你的集成对接的是哪个端点,而不是作为开发目标。
结语
CONSUMPTION_REQUEST 不是 Apple 的退款决定。它是一次短暂、有时限的机会,让你告诉 Apple 你的系统知道而 Apple 不知道的信息。
一个能可靠处理它的工作流,需要经过验证的通知端点、可识别的交易、可映射的用户、你确实收集到的同意、真实的使用数据、窗口内的响应,以及记录得足够完整、能在事后更新权益的结果。
如果读完本文你只做一件事,那就去检查你的集成调用的是哪个端点。如果它仍在为标准 In-App Purchase 向 V1 路径发送十二个字段,那就是最值得先补上的缺口。
如果退款量已经超出人工处理的能力
一旦退款活动频繁到靠人工盯着通知已不现实,一套专用系统可以监控事件、在窗口内准备并提交响应、跟踪结果,并让权益保持同步。 RefundSensor 自动化的是该工作流中开发者这一侧——不是 Apple 的决定,只是你需要负责的那部分。
常见问题
它是一种 App Store Server Notification,用于告知你的服务器某位用户已申请退款,且 Apple 可能需要消费信息。它不是退款决定。
Apple 会在用户申请退款后、Apple 审核该申请期间发送这条通知。它可能适用于不同的 App Store 产品类型。
你的服务器接收并验证通知,识别交易和用户,检查用户同意状态,然后在响应窗口内向 Apple 发送所需的消费信息。
验证通知,检查用户同意状态,提供准确的使用和交付数据,将其提交给 Apple,并记录响应内容和最终结果。
Apple 当前文档规定的响应窗口为 12 小时。开发者在实施前应核实 Apple 的最新要求。
它是关于用户如何使用这笔购买的信息。根据当前端点的要求,它可以包括用户同意、交付状态、试用内容、消费数据以及倾向的退款结果。
不能。最终决定由 Apple 做出。开发者可以提供消费信息并表明退款倾向,但最终裁定权在 Apple。
可以。开发者可以将通知验证、交易匹配、同意检查、数据准备、截止时间跟踪和响应记录自动化。






