购买测试

在 TestFlight 中基于 Apple 沙盒测试购买,并验证 webhook 是否触发。

你无法在模拟器里对真实商品完成一次真正的 StoreKit 购买——Apple 的购买弹窗需要真机、一个 TestFlight 构建,以及一个沙盒测试员账户。本页走完整个闭环:沙盒购买 → 确认 RevenueCat 看到权益 → 确认 webhook 写入了你的 subscriptions 行。

仅在 RevenueCat 配置完成、且 Apple 已完成商品同步(应用能加载 offering)之后再做本页。沙盒购买不会产生真实扣费。

两个 Apple 概念,分别配置

概念含义位置
TestFlight 测试员安装 beta 构建App Store Connect → TestFlight
沙盒测试员用于测试购买的假 Apple IDApp Store Connect → 用户和访问 → 沙盒技术员

同一个人两者都会用到,但它们在不同地方设置。

1. 发一个 TestFlight 构建

归档并上传

在 Xcode 中归档应用并上传(完整归档流程见 App Store 发布)。等构建在 TestFlight 中处理完成。

创建内部测试群组

TestFlight创建群组(内部)→ 把自己加为测试员 → 加入该构建。内部群组跳过外部 beta 审核。 若构建显示 Missing Compliance,先完成导出合规提示。

TestFlight/Release 构建里必须用 appl_ SDK 密钥,绝不能用 test_ 密钥。 模拟商店密钥会触发 RevenueCat 的发布守卫,构建在启动时崩溃循环(checkForSimulatedStoreAPIKeyInRelease 处的 EXC_BREAKPOINT)。设好 REVENUECAT_IOS_KEY = appl_…,提升 build number,重新上传。

2. 创建沙盒测试员并登录

创建测试员

用户和访问 → 沙盒技术员 → +,填一个尚未成为 Apple ID 的邮箱,并选择地区。

在设备上登录

先从 TestFlight 安装应用,然后在 iPhone 上登录沙盒账户。路径因 iOS 版本而异——通常是 设置 → App Store → 沙盒账户设置 → 开发者 → 沙盒 Apple 账户。(若没有“开发者”菜单,把设备 连一次 Xcode 以开启开发者模式。)

3. 跑一次购买测试

购买

启动应用 → 登录你的应用账户 → 打开付费墙 → 确认 offering 加载出来 → 点继续 → 确认 Apple 的沙盒 弹窗。付费墙应关闭,应用应翻转到已解锁状态。

确认 RevenueCat 看到了

在 RevenueCat 里切到沙盒数据,找到该客户(其 app_user_id 即你的 Supabase 用户 UUID)。所 配置的权益(REVENUECAT_PRO_ENTITLEMENT_ID,默认 pro)应为活跃

确认 webhook 写入了行

这是账户绑定的另一半。在 Supabase 里检查 subscriptions 表,应有一行以同一 user_id 为键, status = active(或 trialing)且 product_type 正确。只要它在,EntitlementController 就会读到它, 每个 PremiumGate 都会跨平台解锁。

沙盒事件永远只触及该测试员自己的那一行——RLS 加上以 user_id 为键的 upsert,意味着一个测试员 影响不到另一个。应用的 pollAfterPurchase() 循环(0.8s → 1.6s → 3.0s)会消化购买与 webhook 写入 之间的那几秒。

4. 测试恢复购买

验证一个已购账户能重新解锁:

  1. 删除并重装 TestFlight 应用。
  2. 登录同一个沙盒账户。
  3. 打开付费墙 → 点恢复购买 → 权益解锁。

若要再次测试首次购买流程,请用一个全新的沙盒测试员,或在 App Store Connect 里清空当前测试员的 购买历史。

常见问题

症状可能原因解决
启动即崩溃(SIGTRAPRelease/TestFlight 构建里用了 test_ SDK 密钥改用 appl_ App Store 密钥,提升 build,重新上传
付费墙为空 / “无法加载套餐”offering 未激活、无包,或商品仍是 Missing Metadata激活 default、挂上包、补齐商品元数据
错误码 23(配置错误)StoreKit 拉不到商品商品 ID + bundle id 完全一致;完成协议 / 税务 / 银行;等待 Apple 同步(可能数小时)
RevenueCat 商品显示 “Could not check”缺失 / 权限不足的 App Store Connect API 密钥上传具备 App 管理 角色的 API 密钥;核对 Key ID + Issuer ID
已购买,但什么都没解锁权益标识符REVENUECAT_PRO_ENTITLEMENT_ID匹配标识符(非显示名);默认 pro
“已购买”,不弹购买弹窗沙盒测试员已拥有换一个测试员,或清空其购买历史
RevenueCat 里权益已活跃,但 subscriptions 行缺失webhook URL/密钥有误,或 app_user_id 非 UUID复查 webhook URL + REVENUECAT_WEBHOOK_AUTH;确认应用用 Supabase UUID 登录

更底层、与 App Store 无关的问题(Keychain 会话、深度链接、xcconfig 替换)见 疑难排查。本页只保留购买流程特有的问题。

有用的日志

在 debug 构建下于真机上看 RevenueCat 的详细日志——模板已在 DEBUG 中设为 Purchases.logLevel = .warn。要临时更详细:

#if DEBUG
Purchases.logLevel = .debug
#endif

一次健康的购买前日志显示权益为空;购买 / 恢复后,活跃列表会包含你的权益 id:

activeEntitlements=[]              // 购买前
activeEntitlements=["pro"]         // 购买 / 恢复后

在 Xcode 中,查看调试控制台(View → Debug Area → Activate Console)或设备日志 (Window → Devices and Simulators → Open Console),按 RevenueCat / Purchases / StoreKit 过滤。

相关页面

On this page