RevenueCat 配置

控制台侧配置:App Store Connect 商品、RevenueCat offering 与 webhook。

在付费墙能展示包并完成购买之前,你需要配置它背后的两个控制台:App Store Connect(Apple 售卖的 商品)与 RevenueCat(应用读取的目录 + offering,以及把权益写入你的 subscriptions 表的 webhook)。 这些都是账户侧的工作——除三个密钥外无需改动代码。

你需要一个付费的 Apple Developer 账户以及应用的 bundle id(默认 com.soarstarter.SoarStarterSwift)。所有商品 / offering 工作都在浏览器里完成;应用只需要 REVENUECAT_IOS_KEYREVENUECAT_PRO_ENTITLEMENT_ID 与 webhook 密钥。

1. App Store Connect:创建应用并完成付费应用要求

创建应用记录

App Store ConnectApp+新建 App:选择 iOS,填写名称,选择 Xcode 使用的 bundle id,并设置一个内部 SKU(如 soar-ios)。 若 bundle id 不存在,先到 Apple Developer 的证书、标识符与描述文件 → 标识符中创建。

完成付费应用协议

业务(或协议、税务与银行业务)中完成每一项付费应用前置条件:付费应用协议银行账户税务表格。在这些完成之前,StoreKit 无法拉取商品——这是付费墙为空最常见的原因。

2. 创建商品

用下列精确 ID 创建三个内购商品(付费墙只渲染 offering 中包含的子集,因此你可以少发几个):

变现 → App 内购买项目下,新增一个非消耗型

类型:非消耗型
参考名称:SoarStarter Swift Lifetime
商品 ID:soar_starter_swift_lifetime

变现 → 订阅下,创建一个订阅群组(如 SoarStarter Pro),然后在群组内添加两个自动续期 订阅,以便 Apple 处理升级 / 降级与按比例结算:

参考名称:SoarStarter Pro Monthly
商品 ID:soar_starter_swift_pro_monthly
时长:1 个月

参考名称:SoarStarter Pro Yearly
商品 ID:soar_starter_swift_pro_yearly
时长:1 年

可选地在任一商品上加入介绍性免费试用。

为每个商品填齐必填元数据——价格、显示名称、描述、审核截图、已获销售许可。之后每个商品会从 Missing Metadata 变为 Ready to Submit

Ready to Submit 是首次提交 App 审核前的预期状态——它不是错误,且足以进行沙盒购买测试。

3. 创建两个 App Store Connect 密钥

RevenueCat 需要两个不同的密钥——不要混淆。两者都在用户和访问 → 集成下创建:

密钥位置用途
App Store Connect API 密钥集成 → App Store Connect API校验商品元数据、状态、定价(角色:App 管理
App 内购买密钥集成 → App 内购买StoreKit 2 交易处理

下载各自的 .p8,并复制其 Key IDIssuer ID。若 RevenueCat 的 Products 页稍后显示 Could not check,说明缺少 App Store Connect API 密钥或其权限不足。

4. 配置 RevenueCat 应用

添加 App Store 应用

在 RevenueCat → Apps & providers → 添加一个 App Store 应用。将 bundle id 设为完全一致

com.soarstarter.SoarStarterSwift

上传 App 内购买密钥并添加 App Store Connect API 凭据,然后保存。复制公开的 App Store SDK 密钥—— 它以 appl_ 开头:

REVENUECAT_IOS_KEY = appl_xxxxxxxxxxxxxxxxx

创建商品

Product catalog → Products 下,用第 2 步中完全一致的 ID 创建 App Store 商品:

soar_starter_swift_pro_monthly
soar_starter_swift_pro_yearly
soar_starter_swift_lifetime

创建权益

Product catalog → Entitlements 下创建一个权益,并挂上全部三个商品,使任意一次购买都能授予 访问权。把它的标识符填入 Secrets.xcconfig

REVENUECAT_PRO_ENTITLEMENT_ID = pro

创建 offering

Product catalog → Offerings 下创建名为 default 的 offering 并加入这些包。付费墙会按月付 → 年付 → 终身排序并预选年付:

包类型:Monthly   商品:soar_starter_swift_pro_monthly
包类型:Annual    商品:soar_starter_swift_pro_yearly
包类型:Lifetime  商品:soar_starter_swift_lifetime

确保 default活跃 / 当前 offering(在 RevenueCat 新版 UI 中以蓝色对勾表示)。应用读取 offerings.current,因此非活跃的 offering 会导致付费墙为空。

权益标识符 ≠ 显示名。 应用用 REVENUECAT_PRO_ENTITLEMENT_ID 去匹配权益的标识符 (Entitlements 下的那个 slug),而非其显示名。这里不一致,就是经典的“购买成功却什么都没解锁”的坑。

5. 把 webhook 接到你的 Supabase 表

这正是让权益账户绑定的关键。RevenueCat 把购买事件 POST 到你的 revenuecat-webhook Edge Function, 后者写入 subscriptions 行。在 RevenueCat → Integrations → Webhooks 中添加:

字段
URLhttps://<project-ref>.supabase.co/functions/v1/revenuecat-webhook
Authorization 头与你设为 REVENUECAT_WEBHOOK_AUTH Edge 密钥相同的值

该函数通过(时间安全地)比较 Authorization 头与 REVENUECAT_WEBHOOK_AUTH 来鉴权——没有请求体 HMAC。它以 --no-verify-jwt 部署,因为 RevenueCat 不是登录用户。部署它并从 Supabase 配置设置该密钥。

身份绑定形成闭环:应用用 Supabase 用户 UUID 登录 RevenueCat,因此每个 webhook 事件都带着 app_user_id == subscriptions.user_idapp_user_id 非 UUID 的事件(匿名客户)会被处理器忽略。

期望的最终状态

App Store 应用  → bundle id com.soarstarter.SoarStarterSwift,SDK 密钥 appl_...
商品            → 3 个 App Store 商品,状态 Ready to Submit(或有效)
权益            → 标识符 "pro",挂上全部 3 个商品
Offering        → "default",活跃,包含 Monthly/Annual/Lifetime
Webhook         → https://<ref>.supabase.co/functions/v1/revenuecat-webhook
                  Authorization = REVENUECAT_WEBHOOK_AUTH

一旦 Apple 完成商品同步(可能需 15 分钟到数小时),TestFlight 构建就能加载 offering 并展示套餐。到 购买测试做端到端验证。

相关页面

On this page