退款保护
每当用户申请退款时,应用商店会先进行调查再做决定。为了判断退款是否合理,商店会向开发者索取该用户的活动信息。如果没有这些证据,即使是使用频繁的订阅也很可能被退款。
退款保护(Refund Saver)可自动处理这些请求,保护您的收入,并提高不合理请求被拒的概率。它同时支持 App Store 和 Google Play,涵盖所有应用内购买类型——自动续订订阅、一次性订阅、消耗型商品及非消耗型商品(包括永久授权产品)。
在用户取消前留住他们。 留存消息 会在 Apple 的取消订阅页面内展示一条自定义提示——在订阅者点击取消的那一刻,给他们一个留下来的理由。
Refund Saver 的工作原理
-
当用户发起退款请求时,商店会发送通知,询问交易和使用详情。
如果您忽略或延迟响应,商店很可能会批准退款。
-
Adapty Refund Saver 会自动响应这些通知,并向商店发送必要的数据。
这一自动化机制可降低不必要退款的概率,同时节省时间并保护您的收入。
-
Adapty 记录每次处理结果——已退款或已拒绝。这些数据将驱动看板中的 Refund Saver 数据图表。
各应用商店的差异
Refund Saver 在两个应用商店均可使用,但各自处理退款的方式有所不同。
| App Store | Google Play | |
|---|---|---|
| Refund Saver 的响应对象 | 针对某笔交易的消费请求 | 针对某笔订单的退款审核。由用户银行以拒付形式发起 |
| 用户同意 | 必须获得 | 无需获得 |
| Adapty 获知结果的方式 | App Store 发送通知 | Adapty 轮询订单状态,直至 Google 完成审核 |
在 Google Play 上,用户有两种方式申请退款。退款申请由 Google 直接决定,无需您的介入,因此 Refund Saver 无法介入处理。拒付则不同:用户向其银行申请撤销付款,Google 在争议结案前会征询您的意见,而 Refund Saver 会替您作出回应。一旦用户赢得拒付争议,您不仅会损失购买金额中属于您的部分,还需承担银行收取的拒付手续费。
特定商店前提条件
App Store
当用户向 Apple 申请退款时,Apple 会进行调查。在做出决定之前,它会向你发送一个消费请求——要求提供用户使用该购买项目的详细信息。Refund Saver 会根据你的首选结果和用户的消费数据来回应该请求。
要在 App Store 上使用 Refund Saver,你需要:
- 启用 App Store Server Notifications V2:Refund Saver 不兼容 V1 通知,Apple 已弃用该版本。
- 添加应用内购买密钥:Refund Saver 使用应用内购买密钥向 Apple 签署回复。Adapty 需要在 App settings → iOS SDK 中填写 Issuer ID、Key ID 和
.p8文件,以及您的 Bundle ID——缺少任意一项,都无法响应消费请求。请参阅生成应用内购买密钥。 - 在隐私政策中披露消费数据的使用方式:Apple 要求进行披露,这是您的责任,而非 Adapty 的责任。有关需要披露的内容,请参阅 Apple 的应用隐私详情。
- 获取用户数据共享授权:同样是您的责任——Apple 要求在 Adapty 共享用户数据之前获得有效的用户授权。请参阅获取用户授权。
Google Play
要在 Google Play 上使用 Refund Saver,需要连接商店并启用 RTDN——这两项均属于标准 Google Play 集成流程:配置 Google Play 商店集成和启用实时开发者通知(RTDN)。Google 通过 RTDN 发送每次退款审核通知,因此若未启用,审核请求将无法得到响应。无需用户同意——拒绝退款申诉不涉及任何个人数据共享。
开启 Refund Saver
Refund Saver 只需开启一次。开启后,Adapty 将自动处理来自 App Store 和 Google Play 的退款请求,前提是两者已正确连接到 Adapty,且你满足各商店的前置条件。
- 在 Adapty 看板中打开 Refund Saver 页面。
- 点击 Turn on refund saver。
配置 Refund Saver
启用该功能后,您可以对 Refund Saver 进行配置。设置分为两个层级:
- 应用级默认设置:每个商店的退款偏好,以及默认同意政策 — 即 Refund Saver 在没有记录用户同意值时所假定的同意状态。两者均在 Edit Refund saver preferences 窗口中设置。
- 按用户覆盖:针对特定用户的退款偏好和同意值。设置后,它们将优先于应用级默认设置。可通过看板、SDK 或服务端 API 设置偏好 — 三者写入的是同一个值。同意状态更新来自 SDK 或 API。
为每个应用商店设置退款偏好
退款偏好是 Adapty 在处理退款申请时所给出的建议。Adapty 会将其应用于该商店中的所有申请,而不是逐一决定。每个商店都有各自独立的偏好设置。该偏好仅作为建议——最终决定权由应用商店掌握。
- 如需修改偏好设置,请在 Refund Saver 页面中点击 Refund Saver Settings。
- 在 Edit Refund saver preferences 窗口中,选择 Apple 或 Google 标签页。
- 选择您的 Default refund request preference 选项:
| 选项 | 描述 |
|---|---|
| 拒绝首次退款申请,批准后续申请 | (默认)对于 Refund Saver 遇到的每笔交易,首次会请求商店拒绝退款。若同一笔交易再次出现,Refund Saver 则建议批准退款。此方式可减少因不公平拒绝退款而导致的用户不满——用户可以再次申请退款,且大概率会成功。 |
| 始终拒绝 | 请求商店拒绝所有退款申请,包括针对同一笔交易的重复申请。 |
| 始终退款 | 建议商店批准所有退款申请。 |
| 按比例退款 | 建议 Apple 仅退还未使用部分的费用,已使用部分的收入归您保留。仅适用于 App Store——Google 标签页不提供此选项。 |
| 无偏好 | 不向商店提供任何建议。在此情况下,商店将根据其内部政策和用户历史记录自行决定退款结果,不受您的设置影响。此选项是最中立的处理方式。 |
选择合适的偏好设置
拒绝所有退款请求并不能保证退款减少。商店会将你的回应仅视为建议。开发者反映,即使你要求拒绝所有请求,Apple 也可能批准更大比例的退款申请。对同一笔交易反复拒绝,还会让用户有理由再次提交申请。对于大多数应用来说,Decline first refund request, grant all next 既能保留拒绝首次申请的优势,又能避免形成反复拒绝的模式。
按比例退款是介于拒绝和批准之间的中间选项,仅适用于 App Store。与其冒着全额拒绝的风险,不如退还用户未使用部分的费用,同时保留已使用部分的收益。按比例退款适合用户已部分使用的购买场景——例如已花掉一半金币的金币包,或在第二个月取消的年度订阅。Google 在退款审核中只接受拒绝、批准或无偏好三种选项,因此 Refund Saver 无法在 Google 上申请部分退款。如需部分退款,您仍可在 Play Console 的 Order management 中手动处理。
Adapty 如何计算已消费份额
按比例退款涵盖购买中尚未消费的部分,因此 Apple 需要了解用户已消费了多少。
- 自动续费订阅:Apple 自行计算已消耗的份额,Adapty 仅将用户偏好发送给 Apple,不附带消耗百分比。
- 其他所有产品类型:Adapty 计算已消耗的份额,并连同用户偏好一起发送给 Apple。Adapty 从以下两个来源之一获取份额:
- 虚拟货币:该购买所赋予的虚拟货币余额中已消耗份额的平均值(跨所有赋予的货币计算)。消耗份额的准确性取决于你的应用通过服务端 API 上报的消费情况。
- 访问时长:已流逝时段的占比,当购买未赋予任何虚拟货币时使用此方式。
对于部分消耗的购买,Apple 仅接受按比例退款。在其他情况下,Adapty 会发送不同的处理意见:
- 对于已完全消耗的购买,Adapty 会要求 Apple 拒绝退款。
- 对于未使用的购买,Adapty 会要求 Apple 全额退款。
- 对于既没有虚拟货币也没有访问期限的购买,Adapty 没有消耗数据可供发送,因此会在不表明任何处理意见的情况下响应 Apple。未授予任何虚拟货币的消耗型商品属于此类情况。
设置默认同意策略
Default consent policy 适用于尚未记录同意值的用户——即你的应用尚未通过 SDK 或服务端 API 上报其同意状态的用户。该策略定义了 Refund Saver 对这些用户的处理方式。请根据你在获取用户同意中选择的同意方案进行匹配:在 Edit Refund saver preferences 窗口中,切换到 Apple 标签页,设置 Default consent policy 选项。
| 选项 | 描述 |
|---|---|
| Opt-out | (默认)如果 Adapty 不知道用户的同意状态,则默认视为已同意,Refund Saver 将向 Apple 共享退款相关数据。 |
| Opt-in | (Apple 推荐)如果 Adapty 不知道用户的同意状态,则默认视为未同意,Refund Saver 不会向 Apple 共享任何数据。 |
在看板中为特定用户设置退款行为
您可能需要为特定用户设置个性化偏好。打开该用户的用户画像,在左列底部找到 Refund saver settings 卡片。
每位用户的偏好设置对两个应用商店均适用。将 Refund request preference 设置为 Grant refund、Grant prorated refund、Decline refund 或 No preference。Adapty 会将该值应用于用户在 App Store 和 Google Play 上的退款请求。Grant prorated refund 在 Google Play 没有对应选项,因此 Adapty 在 Google Play 上会发送 No preference。
用户级别的偏好设置会覆盖应用级别的默认设置,包括”拒绝首次退款请求,批准后续退款”的行为。
获取用户同意
同意机制仅适用于 App Store——Google Play 退款审核不涉及个人数据,无需用户同意。
如何收集用户的数据共享同意权由您决定,但 Apple 要求在向其共享任何个人数据之前必须获得有效的用户同意。Apple 建议采用选择加入(opt-in)方式,即通过应用内提示说明数据的使用方式,并要求用户明确操作以表示同意。如果用户忽略或拒绝了提示,则不视为已同意。详情请参阅 Apple 的指南。
如果在您的应用中显式征得用户同意不太可行,可以考虑采用选择退出方式。这种方式需要在服务条款中加入数据共享条款,说明用户通过接受条款即表示同意数据共享。请务必清楚说明用户如何撤销其同意。
以下是选择退出方式的示例条款,包含您可能共享的数据类型。这仅供参考,用于帮助您起草自己的文本。您有责任确保最终版本符合所有适用法律及 Apple 的要求。
“如果我们收到应用内购买的退款申请,我们可能会向 Apple 提供该用户的应用内购买活动信息。这可能包括:自应用安装以来的时间、应用总使用时长、匿名账户标识符、应用内购买是否已完全消耗、是否包含试用期、总消费金额以及总退款金额。”
选择方案后,请在看板中设置对应的默认同意策略。
检查用户同意状态
查看用户的同意状态,确认其选择已成功同步至 Adapty。在 Adapty 看板中,打开该用户的用户画像,在 Refund saver settings 卡片中找到 Allow data sharing 设置。Yes 和 No 分别对应用户已记录的选择;Not set 表示 Refund Saver 将遵循您设置的默认同意策略。
您也可以使用服务端 API 来获取单个用户的退款与数据共享偏好设置。
跟踪退款申请节省情况
Refund Saver 部分会报告 Adapty 处理了多少退款申请以及每笔申请的处理结果。如需查看单个应用商店的数据,请在页面顶部选择 Apple 或 Google 标签页。All Platforms 则合并显示两个应用商店的数据。
Google 不会在退款审核结束后通知 Adapty,因此 Adapty 会持续轮询订单状态,直到审核完成。这导致 Google Play 的结果比 App Store 的显示得更晚。
Refund Saver 板块仅涵盖已进入 Refund Saver 流程的退款请求。若要查看应用内的所有退款(包括 Google 自行处理、无需您介入的退款),请参阅 Analytics 中的退款金额和退款事件数据图表。
通过应用代码管理退款保护功能
你的应用可以通过 iOS SDK 为每位用户写入以下两个值:
- 退款请求偏好:当 Adapty 响应该用户的退款请求时所推荐的处理方式。该值属于用户画像,而非某一特定平台,因此退款请求偏好同时适用于 App Store 和 Google Play。
- 数据共享授权:Adapty 是否可以将该用户的购买数据发送给 Apple。授权仅适用于 App Store。
在自己的 UI 中使用 SDK 处理用户的选择——例如同意提示、偏好开关。看板和服务端 API 写入相同的两个值。Android 没有对应的方法——多平台框架仅在 iOS 上写入这些值。
为用户设置退款偏好
您可以根据用户的操作,在应用代码中为每次安装单独设置退款偏好。该偏好适用于用户在两个应用商店的退款请求。使用以下代码片段来设置偏好:
SDK 仅接受 grant、decline 和 no-preference 值。若要为用户设置 Grant prorated refund,请使用看板或服务端 API。
更新用户的授权状态
要告知 Adapty 特定用户是否已提供授权,请使用 updateCollectingRefundDataConsent 方法。授权仅传递给 Apple:Google Play 退款审核不包含任何授权字段。该值会在服务端持久化存储于用户画像中,因此每次变更只需调用一次即可。