iOS端设备重置/换新后重装应用如何检测历史IAP购买记录
跨设备/重装场景的IAP购买状态检测方案
首先要明确的是,你现在基于UserDefaults存储购买状态的方案,本质是把数据存在app沙盒内部——一旦用户卸载app、抹掉整台设备,这块数据会被直接清空,根本当不了可信的购买凭证,完全撑不住换设备、抹机重装的场景。
具体的检测逻辑苹果从IAP设计之初就已经搭好了基础框架,不需要从零搭建持久化存储,按下面的逻辑落地即可:
- 核心能力直接依赖StoreKit的苹果侧交易持久化
IAP系统从设计根源上就不会把购买记录绑定在你的本地存储或者单台设备上:所有非消耗类商品、自动续期订阅、固定时长非续期订阅的购买记录,都会永久绑定在用户完成交易时所用的Apple ID上。
你不需要额外想办法把购买记录同步到云端,只要在app启动、进入核心权益页面时,主动调用StoreKit的交易校验接口即可:使用旧版StoreKit1时,只要正确添加了SKPaymentQueue的交易观察者,调用restoreCompletedTransactions就会从苹果服务器拉取当前登录Apple ID下所有和当前app关联的历史购买;使用新版StoreKit2时,直接遍历Transaction.currentEntitlements就能拿到当前账号下所有已经生效的购买记录。
这些接口返回的交易数据是经过苹果加密签名的,你只要本地校验签名合法,拿到对应的商品ID就可以直接解锁权益,整个过程完全不依赖你之前本地存的任何内容。 - 有自有账号体系的话,加一层服务端映射更稳妥
如果你已经做了app的账号登录功能,可靠性最高的方案是:用户每完成一笔新的IAP交易,就把苹果返回的完整交易票据(base64编码的receipt)传到自己的后端,由后端向苹果的校验接口验真之后,把「用户账号ID-已购商品ID」的对应关系存在自己的数据库里。
后续不管用户换什么新手机、把旧设备抹多少次,只要他登录自己的app账号,你直接查询数据库里的已购清单即可,这套方案比纯靠客户端拉取StoreKit记录的兼容性更强,也能覆盖用户在设备上登不同Apple ID的场景。 - 之前写的
UserDefaults存储逻辑别直接删除,但要调整定位
UserDefaults和Keychain的作用应该是本地缓存层,绝对不能作为可信的购买判断依据。比如你等StoreKit跑完一次完整的权益校验,把校验结果存在UserDefaults里,下次app冷启动的时候可以先读取本地缓存快速渲染UI,不让用户等网络请求转圈圈;后台再静默跑一次StoreKit的全量校验,一旦发现校验结果和本地缓存对不上,就立刻以苹果返回的真实结果为准,覆盖本地缓存。
别觉得把UserDefaults里的购买记录挪到Keychain里就万事大吉了:Keychain的数据虽然在你卸载app的时候不会被清除,但只要用户把整台设备抹掉,Keychain的所有内容也会一起被清空,同样扛不住跨设备、整机抹除的场景。
常见踩坑提醒
- 别等用户主动点“恢复购买”按钮才触发校验逻辑:按照苹果的审核要求,所有非消耗类、订阅类的商品,必须在app启动的时候自动完成权益校验,“恢复购买”的UI入口只是做体验兜底的,不能作为触发校验的唯一路径。
- 永远把苹果返回的签名交易记录作为最终判断依据:不管你本地存了什么、数据库里记了什么,只要和StoreKit拉取到的Apple ID有效购买记录对不上,就必须以苹果的结果为准,不能反过来拿本地存储的内容限制用户的正常权益。
内容的提问来源于stack exchange,提问作者user1924451
相关产品推荐
相关产品推荐

