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

如何将VerifyReceipt API支付状态映射到PurchaseStatus以调用completePurchase

问题解析

使用in_app_purchase包验证购买流程时,遇到以下核心问题:

  1. 调用buyNonConsumable完成购买后,服务器验证收据返回payment_state:1(已支付)和acknowledgement_state:0(未确认),此时purchaseDetails.pendingCompletePurchase为true,需执行completePurchase但因应用意外关闭未执行。
  2. 后续从服务器恢复购买数据时,缺少PurchaseStatus枚举值的官方映射规则,手动映射触发Android端断言错误:

    'package:in_app_purchase_android/src/in_app_purchase_android_platform.dart': Failed assertion: line 176 pos 7: 'purchase is GooglePlayPurchaseDetails': On Android, the purchase should always be of type GooglePlayPurchaseDetails.

Google Play & App Store 收据状态 ↔ PurchaseStatus 映射

Google Play

基于收据中的acknowledgement_state和payment_state字段映射:

  • acknowledgement_state:0 + payment_state:1 → PurchaseStatus.purchased(pendingCompletePurchase=true,需调用completePurchase)
  • acknowledgement_state:1 + payment_state:1 → PurchaseStatus.purchased(pendingCompletePurchase=false,无需操作)
  • payment_state:0 → PurchaseStatus.pending(支付中)或PurchaseStatus.error(支付失败),需结合订单上下文判断

App Store

基于交易状态字段映射:

  • 已支付但未执行finishTransaction → PurchaseStatus.purchased(pendingCompletePurchase=true)
  • 已支付且完成finishTransaction → PurchaseStatus.purchased(pendingCompletePurchase=false)
  • 支付中 → PurchaseStatus.pending
  • 支付失败 → PurchaseStatus.error
解决方案

1. 优先使用插件原生接口恢复购买状态

不要手动构造PurchaseDetails实例,直接调用插件的历史购买查询接口获取平台原生实例,彻底避免类型不匹配问题:

final queryResponse = await InAppPurchase.instance.queryPastPurchases();
for (final purchase in queryResponse.pastPurchases) {
  if (purchase.pendingCompletePurchase) {
    await InAppPurchase.instance.completePurchase(purchase);
  }
}

说明:Android端的GooglePlayPurchaseDetails和iOS端的AppStorePurchaseDetails由插件原生层生成,包含平台特定的订单元数据,能通过断言检查。

2. 服务器同步状态时的平台专属构造

若必须从服务器同步订单状态,需根据平台类型构造对应子类:

Android 示例

import 'package:in_app_purchase_android/in_app_purchase_android.dart';

if (Platform.isAndroid) {
  final androidPurchase = GooglePlayPurchaseDetails(
    productID: 'your_product_id',
    purchaseID: 'server_purchase_id',
    verificationData: PurchaseVerificationData(
      localVerificationData: 'local_receipt',
      serverVerificationData: 'server_returned_receipt',
      source: IAPSource.googlePlay,
    ),
    status: PurchaseStatus.purchased,
    pendingCompletePurchase: true,
  );
  await InAppPurchase.instance.completePurchase(androidPurchase);
}

iOS 示例

import 'package:in_app_purchase_storekit/in_app_purchase_storekit.dart';

if (Platform.isIOS) {
  final iosPurchase = AppStorePurchaseDetails(
    productID: 'your_product_id',
    purchaseID: 'server_purchase_id',
    verificationData: PurchaseVerificationData(
      localVerificationData: 'local_receipt',
      serverVerificationData: 'server_returned_receipt',
      source: IAPSource.appStore,
    ),
    status: PurchaseStatus.purchased,
    pendingCompletePurchase: true,
  );
  await InAppPurchase.instance.completePurchase(iosPurchase);
}

3. 增加类型检查兜底

调用completePurchase前先做类型校验,避免断言错误:

if (purchase is GooglePlayPurchaseDetails || purchase is AppStorePurchaseDetails) {
  await InAppPurchase.instance.completePurchase(purchase);
}

4. 启动时自动处理未完成订单

将历史购买查询和未完成订单处理逻辑放在应用启动入口(如main方法或首页初始化),确保每次启动都能补全未完成的completePurchase操作,避免状态不一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 22:17:34