购买测试

测试 Google Play Billing、RevenueCat 购买、restore 和权益状态。

Android 购买测试使用 Google Play license testers 和 Play 测试轨道。先把它当作 Play Console 流程,再验证 RevenueCat 和 Supabase。

你要测试什么

完整路径是:

License tester installs Play-delivered build
  -> tester buys a RevenueCat package through Google Play Billing
  -> RevenueCat sends PLAY_STORE webhook
  -> revenuecat-webhook upserts public.subscriptions
  -> EntitlementController refreshes and unlocks PremiumGate

这和 Apple sandbox 测试不同。你不需要创建 App Store sandbox users。你要把 Google 账号加入 Play license testers,上传应用到测试轨道,然后让 tester 通过轨道 opt-in link 安装。

前置条件

  • Play Console app 的 package name 与 Android applicationId 一致。
  • Internal testing 轨道已经上传 .aab
  • Tester Google 账号已加入 license testers 和 track testers。
  • Play 商品已激活:pro_monthlypro_yearly 和/或 pro_lifetime
  • RevenueCat Android offering 已把 packages 挂到 entitlement pro
  • local.properties 中有 REVENUECAT_ANDROID_KEY
  • Supabase revenuecat-webhook 已部署并配置到 RevenueCat。
  • 购买前设备上已有一个登录的 Supabase 用户。

购买权益绑定到 Supabase user UUID。如果 RevenueCat 发送匿名或非 UUID 的 app_user_id,webhook 会忽略事件,应用仍保持锁定。

执行购买测试

构建并上传

创建 release bundle,并上传到 Internal testing:

./gradlew bundleRelease

文件位置:

app/build/outputs/bundle/release/app-release.aab

以 tester 身份安装

把 tester 加入 Internal testing 轨道,用同一个 Google 账号打开 opt-in link,并从 Play 安装应用。直接 adb install 的构建适合 UI 开发,但不是验证真实 Play Billing 的 可靠路径。

登录 Supabase

在应用里创建或使用一个 Supabase 账号。PurchasesController 会用该用户 UUID 登录 RevenueCat,它会成为 webhook 的 app_user_id

打开付费墙

从 Home 的 Upgrade to Pro 或 Me 页的订阅入口进入付费墙。确认 offering packages 显示出来。如果 Annual 存在会默认选中 Annual,否则选中排序后的第一个 package。

完成 sandbox purchase

用 license tester 账号购买 monthly、yearly 或 lifetime 商品。RevenueCat 购买成功后, 付费墙会关闭;随后 EntitlementController 会轮询 Supabase,等待 webhook 写入行。

确认 Pro 内容解锁

打开 Showcase -> Guides。只要 public.subscriptions 中当前登录用户有有效权益行, 指南正文就会解锁。

验证 Supabase 行

在 Supabase SQL editor 运行:

select user_id, provider, product_id, product_type, status, period_start, period_end
from public.subscriptions
where user_id = '<supabase-user-uuid>';

Google Play 购买的预期值:

ColumnExpected value
user_idRevenueCat app_user_id 使用的 Supabase UUID
providerplay_store
product_idPlay product id,例如 pro_monthly
product_typemonthyearone_time
statustrialingactivecanceledexpired
period_start购买时间
period_end过期时间、grace-period 过期时间,或 lifetime 的远未来日期

排查支持问题时,也检查 subscription_idcustomer_idlast_order_nolast_paid_at

Restore 和管理

付费墙的 restore 按钮会调用 RevenueCat restore。如果恢复出的 CustomerInfo 有 active entitlement pro,付费墙会关闭。ManageSubscriptionScreen 也提供 restore、RevenueCat management URL,以及 Google Play subscriptions fallback URL。

兑换码测试使用 RedeemCodeScreen,它会打开:

https://play.google.com/redeem?code=<code>

兑换码产生 RevenueCat 事件后,验证同一张 subscriptions 行。

本地 webhook smoke test

如果想绕过 Play 先验证后端函数,在本地启动 functions:

supabase functions serve --env-file supabase/functions/.env

然后发送一个带签名的 RevenueCat 形状事件:

curl -i \
  -X POST http://localhost:54321/functions/v1/revenuecat-webhook \
  -H "Authorization: ${REVENUECAT_WEBHOOK_AUTH}" \
  -H "Content-Type: application/json" \
  --data '{
    "api_version": "1.0",
    "event": {
      "type": "INITIAL_PURCHASE",
      "store": "PLAY_STORE",
      "app_user_id": "11111111-1111-1111-1111-111111111111",
      "product_id": "pro_monthly",
      "period_type": "NORMAL",
      "purchased_at_ms": 1782940800000,
      "expiration_at_ms": 1785532800000,
      "transaction_id": "gpa.test",
      "original_transaction_id": "gpa.test"
    }
  }'

部署环境测试时,把 URL 换成:

https://<ref>.supabase.co/functions/v1/revenuecat-webhook

只要 auth header 匹配且事件被接受,响应体应为 success

常见失败

SymptomLikely causeFix
付费墙提示购买不可用REVENUECAT_ANDROID_KEY 为空添加 Android SDK key 到 local.properties 并重建
Offering 为空商品未激活、没有 current offering、package name 错误,或应用不在测试轨道检查 Play products、RevenueCat offering、package name 和 Internal testing 上传
购买 UI 打不开Tester 安装的是 sideload build,或设备没有 Play services在有 Play services 的设备/模拟器上通过 Play opt-in 安装
Webhook 返回 401RevenueCat AuthorizationREVENUECAT_WEBHOOK_AUTH 不匹配更新 dashboard header 或 Supabase secret
Webhook 返回 500Edge secret 缺失或数据库写入失败查看 Supabase function logs 和 subscriptions schema
RevenueCat 事件到了但应用仍锁住app_user_id 是匿名/非 UUID,或行属于另一个 Supabase 用户购买前登录,并确认 RevenueCat 使用 Supabase UUID 登录
另一个平台的购买看起来消失较短的跨 provider 事件尝试接管Webhook 会保留 period_end 更晚的那一行

验证

  • License tester 安装的是 Play-delivered build。
  • 付费墙 packages 来自 RevenueCat 并能渲染。
  • Purchase、restore 和 redeem 路径都已测试。
  • RevenueCat 投递了 PLAY_STORE webhook。
  • public.subscriptions 中有预期的 provider = play_store 行。
  • Showcase guides 由 Supabase 权益状态解锁。

相关页面

On this page