应用内购买:如何校验已恢复订阅的有效性?
如何判断恢复的订阅是否有效且未被取消?
恢复订阅时返回已取消的记录是正常行为——restorePurchases()会拉取用户所有历史购买记录,包括已取消或过期的订阅,仅靠PurchaseStatus.restored无法判断当前有效性。你可以通过以下方式处理:
1. 利用购买记录的内置字段判断有效性
每个PurchaseDetails对象包含两个关键字段,可直接辅助判断:
isAutoRenewing:如果值为true,说明订阅处于活跃状态且会自动续期;如果为false,要么用户主动取消了自动续期,要么订阅已过期。purchaseDate+subscriptionPeriod:结合购买时间和订阅周期,计算出订阅到期时间,和当前时间对比,判断是否仍在有效期内。
2. 解决pendingCompletePurchase始终为true的问题
对所有状态为restored的购买记录,无论是否有效,都调用completePurchase()完成本地流程,确保客户端状态和平台同步。部分已取消的订阅可能因平台状态延迟导致pending状态残留,重复调用通常能解决。
3. 服务器验证(权威方案)
将恢复得到的purchaseToken发送到你的后端服务器,调用对应平台的官方验证API(Google Play Developer API 或 App Store Server API),获取最准确的订阅状态。客户端本地判断仅作辅助,服务器验证才能避免篡改和状态不同步问题。
修改后的代码示例
Future<void> initializeProAccountPurchase(context) async { available = await IAPService.checkIAPAvailability(); if (available) { final restoredPurchases = await IAPService.restorePurchases().onError((error, stackTrace) { print("error restore"); print(error.userInfo); return []; }); for (var purchase in restoredPurchases) { if (purchase.status == PurchaseStatus.restored) { // 先完成本地购买流程 await IAPService.completePurchase(purchase); bool isActive = false; // 先判断自动续期状态 if (purchase.isAutoRenewing) { isActive = true; } else { // 计算到期时间判断是否仍在有效期 final purchaseDate = purchase.purchaseDate; final subPeriod = purchase.subscriptionPeriod; if (purchaseDate != null && subPeriod != null) { final expiryDate = purchaseDate.add(subPeriod.duration); isActive = expiryDate.isAfter(DateTime.now()); } } if (isActive) { // 处理有效订阅逻辑 await getProAccountDetails({'subs_item_purchase', 'pro_account'}); } else { // 忽略已取消/过期订阅 print("已取消/过期订阅: ${purchase.productID}"); } } } } }
注意事项
subscriptionPeriod和purchaseDate可能为null,需做好非空判断,不同平台的字段返回逻辑有差异。- 服务器验证是生产环境的必要步骤,客户端本地判断仅适合快速展示临时状态。
内容的提问来源于stack exchange,提问作者Neli
相关产品推荐
相关产品推荐

