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

Flutter内购purchase stream购买成功后未触发问题排查

解决Flutter in_app_purchase购买成功但Stream未触发的问题

针对你遇到的支付成功后_onPurchaseUpdate从未被调用的问题,以下是几个排查方向和解决方案:


1. 补充历史购买恢复逻辑

测试环境或已完成的购买可能不会自动触发Stream事件,需要主动恢复购买记录来同步状态。在Purchases类初始化时添加恢复逻辑:

Purchases() {
  final purchaseUpdated = iapConnection.purchaseStream;
  _subscription = purchaseUpdated.listen(
    (List<PurchaseDetails> purchaseDetailsList) {
      _onPurchaseUpdate(purchaseDetailsList);
    },
    onDone: _updateStreamOnDone,
    onError: _updateStreamOnError,
  );
  // 初始化时恢复历史购买
  _restorePurchases();
}

Future<void> _restorePurchases() async {
  try {
    await iapConnection.restorePurchases();
  } catch (e) {
    print('恢复购买失败: $e');
  }
}

2. 完善购买状态处理逻辑

你的_handlePurchase方法缺少对非成功状态的处理,且completePurchase的调用时机可能存在问题。调整为:

Future<void> _handlePurchase(PurchaseDetails purchaseDetails) async {
  switch (purchaseDetails.status) {
    case PurchaseStatus.purchased:
      if (purchaseDetails.productID == 'remove_ads') {
        // 执行移除广告逻辑,比如标记到本地存储
        alreadyBoughtproductsList.add('remove_ads');
        // 示例:SharedPreferences.getInstance().then((p) => p.setBool('no_ads', true));
      }
      // 确保完成购买确认
      if (purchaseDetails.pendingCompletePurchase) {
        await iapConnection.completePurchase(purchaseDetails);
      }
      break;
    case PurchaseStatus.error:
      print('购买错误: ${purchaseDetails.error?.message}');
      break;
    case PurchaseStatus.pending:
      print('购买待处理,请等待支付完成');
      break;
    default:
      break;
  }
  notifyListeners();
}

3. 验证Stream订阅的生命周期

确保Purchases实例在应用生命周期内唯一,未被意外销毁重建:

  • 在dispose方法中添加日志,确认是否被意外调用:
    @override
    void dispose() {
      print('Purchases实例被销毁');
      _subscription.cancel();
      super.dispose();
    }
    
  • 检查MultiProvider配置,确保Purchases始终是同一个实例(当前lazy: false配置是正确的,避免延迟初始化导致订阅丢失)。

4. 测试环境特殊配置检查

  • 确认Google Play Console中已将测试账号添加到许可测试列表
  • 内购商品已发布到测试轨道(至少是封闭测试)
  • 测试应用的签名与上传到Play Console的签名一致(包括调试签名的配置)

5. 强制触发Stream事件

如果以上操作后仍未触发,可以在buy方法结束后手动调用恢复购买,强制同步状态:

Future<void> buy(ProductDetails productDetails) async {
  final purchaseParam = PurchaseParam(productDetails: productDetails);
  switch (productDetails.id) {
    case 'remove_ads':
      await iapConnection.buyNonConsumable(purchaseParam: purchaseParam);
      // 手动触发恢复,确保Stream收到事件
      await _restorePurchases();
      break;
    default:
      throw ArgumentError.value(productDetails, '${productDetails.id} 不是已知商品');
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 20:21:07