PAYATHON 2026

Flutter + Revenue Cat 提示用户不允许购买

支付阿杰

结论

Android 内购不要求应用正式发布到 Production。通过 Google Play 的 Internal testing、Closed testing 或 Open testing 分发的版本也可以完成购买,前提是安装来源、测试资格、Google 账号、商品地区和付款资料都符合要求。

PurchaseNotAllowedError 通常不代表 RevenueCat 商品 ID 同步失败。它表示 Google Play Billing 判定当前设备或 Google 账号不具备购买资格。RevenueCat 只是把 Google Play 返回的错误包装为:

PurchaseNotAllowedError

如果过去一个月几乎所有 Android 付款都失败,应先排查测试版本的安装渠道、测试人员资格、Play 国家或地区以及 Google Payments Profile,不必反复调整 RevenueCat Offering。

为什么会出现这个错误

Google Play Billing 返回的“设备或用户不允许购买”涵盖的情况较多,常见原因有:

  • 应用不是从 Google Play 测试轨道安装,而是通过 APK、ADB 或其他渠道安装。
  • 用户没有加入相应的 Internal、Closed 或 Open testing,或者加入测试后仍在使用旧版本。
  • 设备上登录了多个 Google 账号,而 Play Store 下载应用时使用的并非测试账号。
  • Google Play 账号的国家或地区不在商品开放范围内。
  • Google Payments Profile 被暂停、需要重新验证,或者没有适用于当前地区的付款方式。
  • 用户使用的是受监管账号,例如儿童账号、Family Link 账号或企业托管账号。
  • Play Store、Google Play Services 或设备认证状态异常。
  • 商品虽然是 Active 状态,却没有向当前测试轨道、国家或用户群开放。
  • 当前应用的 applicationId、签名或安装包与 Play Console 中的应用不一致。

如果 RevenueCat 中的商品 ID 配置有误,通常会表现为商品无法加载、Offering 为空或找不到产品,而不是明确返回 PurchaseNotAllowedError。

建议按以下顺序排查

1. 确认应用来自 Google Play

测试真实购买时,不要使用本地构建的 APK,也不要使用通过 flutter run 安装的版本。测试人员需要:

  1. 通过测试邀请链接加入相应的测试轨道。
  2. 在 Google Play 中确认自己已经成为测试人员。
  3. 卸载设备上原有的应用。
  4. 使用加入测试的同一个 Google 账号,从 Google Play 重新安装应用。

即使本地 APK 的包名和版本号相同,也不能说明它的购买环境与 Play 分发版本相同。

2. 检查设备上的 Google 账号

设备上有多个 Google 账号时,Play Billing 实际使用的账号可能和预期不同。可以找一台干净的测试设备进行验证,并确保:

  • Play Store 中只保留一个 Google 账号。
  • 该账号已经加入测试轨道。
  • 该账号可以正常打开 Google Play 的付款方式页面。
  • 应用由该账号从 Play Store 下载。
  • 账号不受 Family Link、企业策略或年龄限制约束。

如果更换账号后购买立即恢复,问题通常出在账号资格或 Payments Profile,而不是 Flutter 代码。

3. 核对国家和地区

如果应用主要在 Singapore 使用,需要分别确认:

  • Play Console 中的应用和商品是否向 Singapore 开放。
  • 测试用户的 Google Play country 是否属于受支持地区。
  • Google Payments Profile 的国家是否与实际付款方式匹配。
  • 用户近期是否迁移过国家、使用跨区账号或通过 VPN 访问 Play Store。

设备当前位于 Singapore,不等于 Google Play 账号所属国家就是 Singapore。Google Play 主要根据账号和 Payments Profile 判断购买资格。

4. 检查 Payments Profile

“开发者账号可以接收付款”和“消费者账号可以完成付款”属于两套不同的配置。

开发者的 Merchant/Payments Profile 正常,只能说明应用具备收款条件。每位购买用户仍需拥有可用的消费者付款资料。可以让购买失败的用户在 Play Store 中:

  • 打开“Payments & subscriptions”。
  • 查看付款方式是否过期或被拒绝。
  • 检查是否有身份、地址或付款资料验证提示。
  • 尝试购买其他 Google Play 商品。

如果同一账号购买其他应用或商品也失败,需要交由 Google Payments 支持继续处理。

5. 使用 License testing 隔离付款方式问题

在 Play Console 中配置 License testing,并用明确加入测试名单的账号进行测试。这样有助于判断问题来自应用集成,还是实际付款方式和风控。

License tester 与测试轨道中的测试人员不是同一个概念。账号通常既要能够访问相应的测试版本,也要根据测试目标正确配置 License testing。

6. 创建最小化测试矩阵

至少使用以下组合进行交叉验证:

安装来源Google 账号网络/地区结果
Play 测试轨道新测试账号Singapore记录结果
Play 测试轨道原失败账号Singapore记录结果
Play 测试轨道新测试账号另一台设备记录结果

如果新账号可以购买,原账号不行,应重点检查原账号的资格和付款资料。如果所有账号和设备都失败,再检查 Play Console 中的测试轨道、地区、商品和应用发布配置。

Flutter 中的错误处理

客户端无法绕过 Google Play 对购买资格的判定。应用应识别相应错误,停止自动重试,并向用户提供具体的排查提示:

import 'package:flutter/services.dart';
import 'package:purchases_flutter/purchases_flutter.dart';

Future<void> purchasePackage(Package package) async {
  try {
    final result = await Purchases.purchasePackage(package);

    // 根据当前 purchases_flutter 版本读取 CustomerInfo,
    // 并在服务端或客户端确认 entitlement 是否已生效。
    final customerInfo = result.customerInfo;
    final isActive =
        customerInfo.entitlements.active.containsKey('premium');

    if (!isActive) {
      throw StateError('Purchase completed but entitlement is not active.');
    }
  } on PlatformException catch (e) {
    final errorCode = PurchasesErrorHelper.getErrorCode(e);

    if (errorCode == PurchasesErrorCode.purchaseNotAllowedError) {
      // 不要循环重试。提示用户检查 Play Store 账号、地区和付款资料。
      throw StateError(
        'Google Play 不允许当前账号完成购买。'
        '请确认应用来自 Google Play、账号已加入测试,'
        '并检查 Play Store 的国家/地区和付款方式。',
      );
    }

    if (errorCode == PurchasesErrorCode.purchaseCancelledError) {
      return;
    }

    rethrow;
  }
}

不同版本的 purchases_flutter 可能会调整返回对象的结构,应以项目锁定版本的 API 为准。错误处理原则不变:识别 purchaseNotAllowedError,不要将其视为用户取消,也不要试图通过反复调用购买接口来绕过限制。

诊断时应记录什么

为了便于 RevenueCat 或 Google 支持定位问题,可以记录以下非敏感信息:

  • 应用版本、versionCode 和包名。
  • 应用是否从 Google Play 安装。
  • 应用所属的测试轨道。
  • RevenueCat App User ID。
  • RevenueCat 请求时间和相关日志。
  • 商品 ID 与商品类型。
  • 设备型号、Android 版本和 Play Store 版本。
  • Google Play 账号国家以及测试资格。
  • 错误码、readableErrorCode 和 underlyingErrorMessage。

不要记录银行卡号、完整付款资料、Google 密码或其他认证信息。

注意事项

一次购买成功,只能证明当时使用的账号、设备和商品配置有效,不能说明后续所有用户都具备购买资格。测试轨道、账号地区、付款资料和 Google 风控状态都可能发生变化。

如果失败集中在特定账号或地区,通常需要排查 Google Play 用户资格或支付环境。如果所有测试账号和设备都同时失败,应重点检查测试轨道、商品地区、安装来源、包名和签名。只有当 RevenueCat Dashboard 中出现商品无法加载、产品映射错误或 entitlement 未激活时,才需要把排查重点转到 RevenueCat 配置。

备注:内容仅供参考。