购买测试
测试 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_monthly、pro_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 购买的预期值:
| Column | Expected value |
|---|---|
user_id | RevenueCat app_user_id 使用的 Supabase UUID |
provider | play_store |
product_id | Play product id,例如 pro_monthly |
product_type | month、year 或 one_time |
status | trialing、active、canceled 或 expired |
period_start | 购买时间 |
period_end | 过期时间、grace-period 过期时间,或 lifetime 的远未来日期 |
排查支持问题时,也检查 subscription_id、customer_id、last_order_no 和
last_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。
常见失败
| Symptom | Likely cause | Fix |
|---|---|---|
| 付费墙提示购买不可用 | 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 返回 401 | RevenueCat Authorization 与 REVENUECAT_WEBHOOK_AUTH 不匹配 | 更新 dashboard header 或 Supabase secret |
| Webhook 返回 500 | Edge 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_STOREwebhook。 -
public.subscriptions中有预期的provider = play_store行。 - Showcase guides 由 Supabase 权益状态解锁。
