Flutter in_app_purchase: ^3.1.4正式版内购功能异常求助
非消耗型内购正式版失效排查与修复
代码层面核心问题
你的代码在测试环境正常但正式环境失效,核心是几个关键逻辑缺失:
未处理Pending状态购买
正式支付流程中,部分场景(如用户身份验证、支付渠道延迟)会让购买处于PurchaseStatus.pending状态,当前代码完全遗漏该分支,导致购买完成后状态无法同步。未调用completePurchase
非消耗型商品购买成功后,必须调用purchase.completePurchase()告知应用商店购买已处理完成,否则商店会在每次APP启动时重复推送该购买记录,甚至阻塞后续购买流程。仅依赖本地缓存判断购买状态
只靠SharedPreferences保存状态,用户清除APP数据或换设备后会丢失购买记录,正式环境必须主动查询历史购买记录验证用户购买状态。商品加载无错误反馈
_loadProducts方法未处理response.error或商品加载为空的情况,正式环境若商品配置错误(如ID不匹配、未激活),无法快速定位问题。
正式发布环境必查项
除代码外,需确认商店后台配置:
- 商品状态:Google Play/App Store后台商品必须处于已激活状态,测试阶段的草稿/未激活商品正式版无法访问。
- 签名与ID匹配:Android正式签名的SHA-1需在Google Play后台配置;iOS的Bundle ID、签名证书必须与后台一致。
- 地区与定价:商品是否在目标用户所在地区上架,正式环境的地区限制会导致商品加载失败。
- 购买账号:正式版(非TestFlight/内部测试)中,iOS需用沙盒测试账号,Android需用Google Play授权的测试账号,不能用普通真实账号测试(除非真实支付)。
修复后的关键代码示例
1. 完善购买状态处理逻辑
void _handlePurchaseUpdates(List<PurchaseDetails> purchases) { for (PurchaseDetails purchase in purchases) { switch (purchase.status) { case PurchaseStatus.purchased: // 必须调用completePurchase告知商店 if (purchase.pendingCompletePurchase) { InAppPurchase.instance.completePurchase(purchase); } _savePurchaseStatus(true); setState(() { _isPurchased = true; }); break; case PurchaseStatus.pending: // 处理支付中状态,比如显示提示 setState(() { // 可添加loading状态或文本提示 }); break; case PurchaseStatus.error: // 打印错误信息方便排查 print('购买错误: ${purchase.error?.message}'); break; case PurchaseStatus.canceled: // 可添加取消购买的提示逻辑 break; } } }
2. 添加历史购买记录查询
在_checkPurchaseStatus中补充查询商店历史购买,替代单一本地缓存依赖:
Future<void> _checkPurchaseStatus() async { // 先查本地缓存 SharedPreferences prefs = await SharedPreferences.getInstance(); bool? localPurchased = prefs.getBool('isPurchased'); // 查询商店历史购买记录 QueryPurchaseDetailsResponse purchaseResponse = await InAppPurchase.instance.queryPastPurchases(); for (PurchaseDetails purchase in purchaseResponse.pastPurchases) { if (purchase.productID == 'urdubible' && purchase.status == PurchaseStatus.purchased) { _savePurchaseStatus(true); setState(() { _isPurchased = true; }); return; } } // 无历史记录时用本地缓存 if (localPurchased != null && localPurchased) { setState(() { _isPurchased = true; }); } }
3. 完善商品加载的错误处理
Future<void> _loadProducts() async { ProductDetailsResponse response = await InAppPurchase.instance.queryProductDetails(_productIds); if (response.error != null) { print('商品加载错误: ${response.error?.message}'); return; } if (response.productDetails.isEmpty) { print('未找到对应商品,请检查商品ID和后台配置'); return; } setState(() { _products = response.productDetails; }); }
内容的提问来源于stack exchange,提问作者joshua
相关产品推荐
相关产品推荐

