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

使用flutter_inapp_purchase校验订阅有效性时chcekSubscribed报错

报错核心原因

调用checkSubscribed出现类型转换错误,基本是三个问题导致:

  • 方法名拼写错误:代码中写的chcekSubscribed字母顺序错误,Dart找不到对应方法时会返回动态类型的null,后续操作很容易触发类型转换异常。
  • 传参类型不匹配:该方法要求入参为字符串类型的订阅商品ID,很多开发者误传入PurchasedItem实例、动态类型的Map结构值,触发强类型校验报错。
  • 版本兼容问题:flutter_inapp_purchase 5.0及以上版本调整了方法返回值类型,旧版本中直接将返回值强转为bool的写法不再适用,新版本返回值为Future<PurchasedResult?>类型,直接强转布尔值必然报错。
正确的订阅有效性校验实现

前置准备

首先在pubspec.yaml中锁定稳定版本依赖,避免dev版本的API变动问题:

dependencies:
  flutter_inapp_purchase: ^5.3.1

初始化阶段必须先完成商店连接,再拉取订阅商品信息,确保本地配置和商店后台配置一致:

// 初始化内购连接
await FlutterInappPurchase.instance.initialize();
// 配置你在商店后台上架的所有订阅商品ID
const List<String> kSubscriptionIds = ['pro_monthly', 'pro_yearly'];
// 拉取订阅商品信息,校验ID有效性
await FlutterInappPurchase.instance.getSubscriptions(kSubscriptionIds);

修复调用逻辑,规避类型错误

以下是会触发报错的典型错误写法,直接替换即可:

// 错误写法:拼写错误、传参错误、非法强转
bool isSubscribed = await FlutterInappPurchase.instance.chcekSubscribed(purchasedItem) as bool;

正确的校验逻辑,包含类型安全处理和兜底校验:

Future<bool> verifySubscriptionValid() async {
  bool validStatus = false;
  try {
    // 注意方法名拼写,传入字符串类型的商品ID
    final PurchasedResult? checkResult = await FlutterInappPurchase.instance.checkSubscribed(
      kSubscriptionIds.first,
    );
    // 先判空再判断状态,禁止直接强转bool
    if (checkResult != null && checkResult.status == PurchaseStatus.purchased) {
      // 拉取本地有效购买记录做二次校验,避免checkSubscribed跨平台返回异常
      final List<PurchasedItem>? availablePurchases = await FlutterInappPurchase.instance.getAvailablePurchases();
      if (availablePurchases != null) {
        validStatus = availablePurchases.any((item) {
          // 校验商品ID匹配
          if (!kSubscriptionIds.contains(item.productId)) return false;
          // 安卓端校验:未确认的订阅会在15天后自动退款,不算有效订阅
          if (Platform.isAndroid && (item.isAcknowledgedAndroid == false)) return false;
          // 校验交易时间在订阅周期内,按自己的订阅时长调整判断逻辑
          if (item.transactionDate == null) return false;
          final transactionTime = DateTime.fromMillisecondsSinceEpoch(int.parse(item.transactionDate!));
          return transactionTime.isAfter(DateTime.now().subtract(const Duration(days: 31)));
        });
      }
    }
  } catch (e) {
    // 异常兜底:直接拉取可用购买记录判断,避免接口报错导致校验失败
    final fallbackPurchases = await FlutterInappPurchase.instance.getAvailablePurchases();
    validStatus = fallbackPurchases?.any((p) => kSubscriptionIds.contains(p.productId)) ?? false;
  }
  return validStatus;
}

跨平台注意事项

  • 安卓端:本地校验仅做前端状态判断,正式环境建议搭配服务端校验Google Play返回的purchaseToken,避免本地伪造订阅状态。
  • iOS端:用户重装应用、跨设备登录时,需要先调用FlutterInappPurchase.instance.refreshReceipt()刷新本地收据,再执行校验逻辑,否则会返回错误的未订阅状态。
  • 调用时机:必须等内购初始化完成、和商店连接成功后再调用校验方法,初始化未完成时方法会返回动态类型null,触发类型转换错误。
类型错误快速排查清单
  • 核对方法名拼写,确认是checkSubscribed,无字母顺序错误
  • 核对入参类型:第一个参数必须是String类型的商品ID,禁止传入对象、Map等其他类型值
  • 核对返回值接收类型:使用PurchasedResult?接收返回值,禁止直接用bool类型接收并强转
  • 核对空安全处理:所有可空返回值必须做判空后再取属性,避免空值触发类型转换异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 23:03:24