测试用户内购获取旧收据、react-native-iap沙箱订阅返回旧收据问题
沙盒环境react-native-iap自动续期订阅返回旧收据的根因与解决方案
该问题由苹果StoreKit的本地收据缓存机制导致,沙盒环境下自动续期订阅到期后,本地缓存的旧收据不会被自动清除,react-native-iap默认优先读取本地缓存,因此再次订阅时会返回旧的交易数据。以下是可落地的解决方案:
客户端侧修复方案
- 每次触发购买/恢复购买操作时,强制要求react-native-iap刷新收据,不要走本地缓存:iOS端调用
requestReceipt方法时传入refresh: true参数,强制从苹果服务器拉取最新收据,示例代码如下:
import { requestReceipt } from 'react-native-iap'; // 购买/恢复订阅前先强制刷新收据 const latestReceipt = await requestReceipt({ refresh: true });
- 交易验证完成后必须主动调用
finishTransaction方法关闭已完成的交易,避免旧交易残留被重复返回:
import { finishTransaction } from 'react-native-iap'; // 自动续期订阅属于非消耗品,isConsumable传false await finishTransaction({ transaction, isConsumable: false });
- 升级react-native-iap到v12及以上的最新稳定版,旧版本存在收据缓存未清空的已知bug,新版本已默认优化新交易触发时的无效缓存清理逻辑。
沙盒测试操作侧排查方案
- 测试前重置沙盒测试账号的购买记录:登录App Store Connect,进入「用户和访问」-「沙盒测试员」,选中对应测试账号,点击「清除购买记录」,清除后卸载重装测试应用再重试。
- 清理测试设备本地的沙盒账号缓存:打开iOS系统「设置」-「App Store」,拉到页面最底部找到已登录的沙盒账号,点击退出后重新登录,再开展测试。
- 单沙盒账号累计订阅测试超过20次后大概率会出现缓存异常,可新建沙盒测试账号对比验证,排除账号本身的异常问题。
后端验证侧兜底方案
- 不要信任客户端本地返回的订阅状态,所有客户端获取的收据必须传到后端调用苹果官方收据验证接口校验,校验时重点判断
expires_date字段是否晚于当前时间,original_transaction_id是否和当前新交易匹配,过滤掉已过期的旧交易数据。 - 若校验后发现收据中存在多笔历史交易,取最新的
purchase_date对应的交易作为有效订阅依据,避免旧收据的干扰。
内容的提问来源于stack exchange,提问作者Raghuvanshi Harsh
相关产品推荐
相关产品推荐

