Flutter测试卡In-App Purchase支付后5分钟收到取消退款通知
Flutter 内购测试支付后自动取消退款问题排查与修复
你遇到的这个问题是Google Play测试环境下的典型场景:未正确完成购买确认流程,导致Google在5分钟后自动取消测试订单并退款。Google规定非消耗型内购必须在购买完成后3天内调用completePurchase确认,测试环境下这个时限被缩短到5分钟,未确认的订单会被自动回收。
你的代码里的核心问题
- 提前触发成功逻辑:在
purchaseFullVersion中,调用buyNonConsumable返回true就直接调用_handleSuccessfulPurchase,但这个返回值仅代表购买请求发起成功,不代表用户已经完成支付,此时PurchaseDetails还未进入purchased状态,后续的确认操作会无效。 - 重复确认逻辑:
_handlePurchaseDetailsList和_handleSuccessfulPurchase中都调用了_acknowledgePurchase,容易导致状态冲突或重复操作。 - 状态处理不完整:没有处理
PurchaseStatus.pending状态,部分测试卡支付会进入pending状态,需要等待状态更新后再处理确认。
修复步骤
1. 移除提前触发的成功逻辑
修改purchaseFullVersion方法,去掉buyNonConsumable后的_handleSuccessfulPurchase调用,仅提示购买已发起:
final bool purchaseResult = await _inAppPurchase.buyNonConsumable(purchaseParam: purchaseParam); if (purchaseResult) { _updateNotice('购买已发起,请等待支付完成...'); return true; } else { _updateNotice('购买发起失败,请重试'); return false; }
2. 统一通过监听流处理所有购买状态
完善_handlePurchaseDetailsList,覆盖所有PurchaseStatus,并只对未确认的订单执行确认:
List<PurchaseDetails> _handlePurchaseDetailsList(List<PurchaseDetails> purchaseDetailsList) { for (PurchaseDetails purchaseDetails in purchaseDetailsList) { switch (purchaseDetails.status) { case PurchaseStatus.pending: _updateNotice('购买处理中,请稍候...'); break; case PurchaseStatus.purchased: // 仅处理未确认的订单 if (!purchaseDetails.pendingCompletePurchase) { _handleSuccessfulPurchase(purchaseDetails); } break; case PurchaseStatus.error: _handlePurchaseError(PlatformException( code: purchaseDetails.error?.code ?? 'unknown_error', message: purchaseDetails.error?.message ?? '购买出错', )); break; case PurchaseStatus.canceled: _updateNotice('购买已取消'); break; } } _purchases.addAll(purchaseDetailsList); return _purchases; }
3. 简化成功处理逻辑,直接传入PurchaseDetails
修改_handleSuccessfulPurchase,直接使用流中返回的PurchaseDetails,避免从列表中查找的错误:
void _handleSuccessfulPurchase(PurchaseDetails purchaseDetails) async { _updateNotice('购买成功!'); homeProvider?.updatePurchaseStatus(true); String deviceId = await SharedPreferencesUtils.getStoredDeviceId(); // 存储购买信息到Firestore await FirestoreService.storePurchaseInfo(deviceId, [purchaseDetails.productID]); // 确认购买 await _acknowledgePurchase(purchaseDetails); // 移除已处理的订单 _purchases.remove(purchaseDetails); }
4. 确保确认逻辑的可靠性
检查_acknowledgePurchase,确保只在订单状态正确时调用:
void _acknowledgePurchase(PurchaseDetails purchaseDetails) async { try { if (purchaseDetails.status == PurchaseStatus.purchased && !purchaseDetails.pendingCompletePurchase) { await _inAppPurchase.completePurchase(purchaseDetails); _updateNotice('购买已确认'); } } on PlatformException catch (e) { _handlePurchaseError(e); } }
额外注意事项
- 必须使用Google Play官方提供的测试卡,例如卡号
4811 1111 1111 1111,有效期填未来日期(如12/30),CVV填任意3位数字。 - 应用必须上传到Google Play控制台的测试渠道(内部/封闭/开放测试),且测试账号已添加到测试列表中。
- 确认Google Play控制台内的内购商品状态为激活,未激活的商品无法完成正常购买流程。
内容的提问来源于stack exchange,提问作者M.Shaaban
相关产品推荐
相关产品推荐

