Flutter in_app_purchase:恢复待处理购买权限异常问题排查
问题核心结论
这是代码逻辑的问题,恢复购买在支付待处理时,平台会返回对应的待处理状态,你的代码没有正确处理恢复后的购买状态,直接默认所有恢复的购买都是已完成状态,才导致提前授予权限。
代码中的关键问题
- 恢复购买的状态判断缺失:你的
HandlePurchases函数中,只要是PurchaseStatus.restored就直接调用PurchasePremium授予权限,但恢复的购买也可能处于pending(待处理)状态,你没有在恢复分支里校验这个核心状态。 - 本地存储逻辑过于绝对:一旦授予权限就直接把
premium设为true并永久存储,没有后续的状态回收逻辑,导致即使后续支付被取消或失败,用户依然能保留权限。
修复方案
1. 修正购买状态处理逻辑
统一处理所有购买(新购+恢复)的状态,只有当购买明确处于purchased完成状态时,才授予高级权限。修改HandlePurchases函数:
void HandlePurchases(List<PurchaseDetails> purchaseDetailsList){ purchaseDetailsList.forEach((PurchaseDetails purchaseDetails) async { switch(purchaseDetails.status) { case PurchaseStatus.error: PopUp("Error with Purchase"); _revokePremiumIfNeeded(); break; case PurchaseStatus.pending: PopUp("Purchase is Pending"); _revokePremiumIfNeeded(); break; case PurchaseStatus.purchased: PurchasePremium(true); if (purchaseDetails.pendingCompletePurchase) { await _iap.completePurchase(purchaseDetails); } break; case PurchaseStatus.restored: // 恢复时必须检查购买的实际完成状态,而不是直接恢复权限 if (purchaseDetails.purchaseState == PurchaseState.purchased) { PurchasePremium(false); if (purchaseDetails.pendingCompletePurchase) { await _iap.completePurchase(purchaseDetails); } } else { // 恢复的购买仍待处理,收回权限 _revokePremiumIfNeeded(); PopUp("Restored purchase is still pending"); } break; case PurchaseStatus.canceled: PopUp("Purchase was Cancelled"); _revokePremiumIfNeeded(); break; } }); } // 新增辅助函数:收回高级权限 void _revokePremiumIfNeeded() { if (hasPremium) { setState(() { hasPremium = false; prefs?.put('premium', false); }); if (contextReference != null) { ScaffoldMessenger.of(contextReference!).showSnackBar( SnackBar(content: Text("Premium access revoked due to incomplete payment")), ); } } }
2. 优化本地存储与权限校验
- 不要把
premium布尔值作为唯一权限判断依据,建议存储购买的凭证信息(比如purchaseDetails.verificationData),每次启动应用(在线时)重新校验凭证的有效性。 - 给本地缓存添加有效期:比如本地存储的权限状态最多保留24小时,超过时间后,必须在线拉取最新购买状态才能继续使用高级功能。
3. 解决离线与滥用问题
- 离线场景:离线时允许使用缓存的权限,但进入高级功能时提示用户“当前离线,权限基于上次验证结果”,并在联网后自动重新校验。
- 慢处理拒付卡滥用:
- 每次启动应用(在线状态)强制拉取
_getPastPurchases(),用最新的购买状态覆盖本地缓存。 - 若没有后端,可在客户端记录用户的购买历史,若短时间内出现多次“待处理-取消”的循环,临时限制该用户恢复购买的频率。
- 每次启动应用(在线状态)强制拉取
内容的提问来源于stack exchange,提问作者Blackshadow1Game
相关产品推荐
相关产品推荐

