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_KEY、REVENUECAT_PRO_ENTITLEMENT_ID 与 webhook 密钥。
1. App Store Connect:创建应用并完成付费应用要求
创建应用记录
在 App Store Connect → App → + →
新建 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 ID 与 Issuer 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 中添加:
| 字段 | 值 |
|---|---|
| URL | https://<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_id。app_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 并展示套餐。到 购买测试做端到端验证。
