You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter使用in_app_purchase库iOS内购交易无法完成该如何解决?

问题根因与解决方案

一、重复触发校验的核心问题

你的代码存在3个关键逻辑错误,导致交易未正常结束:

  • 缺失PurchaseStatus.purchased分支的业务处理:普通首次购买成功后状态为purchased,只有恢复购买场景才会触发restored状态。当前代码在purchased分支仅打印日志,未做服务端校验,也未按业务要求处理交易完成逻辑,未完成的交易会一直留存在队列中,每次进入购买页都会被重新拉取触发校验。
  • forEach异步逻辑陷阱:Dart的List.forEach方法不会等待异步回调执行完成,会直接执行后续代码,导致你服务端校验还未返回结果,后面的pendingCompletePurchase判断就已经执行,逻辑时序完全错乱。
  • 全局调用completePurchase逻辑错误:当前代码不管服务端校验是否成功,只要pendingCompletePurchase为true就直接调用completePurchase,既会导致重复调用,也会出现校验失败但交易被提前结束的业务问题。

二、代码调整方案

将异步遍历改为普通for循环,抽离公共校验与完成逻辑,移除全局的completePurchase调用,修改后的参考代码如下:

void _listenToPurchaseUpdated(List<PurchaseDetails> purchaseDetailsList, Context<PayState> ctx) async {
  // 改用for循环实现异步等待
  for (final purchaseDetails in purchaseDetailsList) {
    if (purchaseDetails.status == PurchaseStatus.pending) {
      RestLog.logger("PurchaseStatus pending...${ctx.state.payModel.isAvailable}");
      _showPendingUI(ctx);
      continue;
    }

    if (purchaseDetails.status == PurchaseStatus.error) {
      RestLog.logger("PurchaseStatus error");
      _handleError(purchaseDetails.error!, ctx);
      continue;
    }

    // purchased和restored都需要走校验逻辑
    if (purchaseDetails.status == PurchaseStatus.purchased || purchaseDetails.status == PurchaseStatus.restored) {
      RestLog.logger("purchase successful trigger verify, productId: ${purchaseDetails.productID}");
      PayVerifyModel payVerifyModel = PayVerifyModel(
        orderId: purchaseDetails.purchaseID,
        receipt: purchaseDetails.verificationData.serverVerificationData
      );
      int result = await Pay.verifyUserPay(payVerifyModel);
      if(result == 0){
        RestLog.logger("verify success: $result");
        // 仅校验通过后再结束交易
        try {
          await InAppPurchase.instance.completePurchase(purchaseDetails);
          RestLog.logger("交易完成成功,订单号:${purchaseDetails.purchaseID}");
        } catch (e) {
          RestLog.logger("交易完成失败:$e");
        }
      }else{
        RestLog.logger("verify failed: $result");
      }
    }
  }
}

三、如何判断交易是否完成成功

completePurchase方法为Future<void>类型,执行失败时会抛出异常,执行成功无返回值,你可以通过两种方式确认执行结果:

  • 捕获调用异常:针对平台错误可以单独捕获PlatformException类型,获取具体错误码与错误信息
  • 校验状态字段:调用completePurchase后读取purchaseDetails.pendingCompletePurchase字段,若值变为false则说明交易已成功结束

如果是测试环境,iOS沙箱账号、谷歌支付沙箱环境偶发不稳定也会导致交易完成不生效,可以更换测试账号或切换网络重试。


内容的提问来源于stack exchange,提问作者Dolphin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.15 08:36:01