> ## Documentation Index
> Fetch the complete documentation index at: https://supastack.dev/llms.txt
> Use this file to discover all available pages before exploring further.
> For the full documentation corpus in one file, fetch: https://supastack.dev/llms-full.txt

# 设置 RevenueCat 购买

创建 RevenueCat 项目，关联你的 App Store 和 Play 商品，接入校验购买的 SDK 密钥与服务端密钥。

## 初学者演练

为什么有这一节：Apple 和 Google 要求应用内数字购买走它们自己的计费——绝不走 Stripe Checkout——套件强制这条边界。RevenueCat 架在两家商店之上，一次集成覆盖 iOS 和 Android：它跟踪收据、订阅和恢复，你的服务器向 RevenueCat 询问工作区是否已付款。

前提条件：移动端账户指南里的 Apple Developer Program（每年 99 美元）和 Google Play Console（一次性 25 美元）账户——商店商品必须先存在，RevenueCat 才能关联——再加上一个真正用来测试的 EAS 开发构建，因为 Expo Go 根本跑不了原生购买模块。RevenueCat 免费档够测试用；商品上线前这里的一切都不会扣款。

快速术语：RevenueCat 项目装着你关联到商店的应用。商品是在 RevenueCat 里镜像的商店物品。entitlement（权益）是订阅有效期间 RevenueCat 授予的标记——默认 `pro`。Offering 把商品组合成应用展示的付费墙。公开 SDK 密钥进移动端 env；API 密钥和 webhook 授权值留在服务端。

你要创建的：一个项目、两个关联商店的应用、商品、一个权益、一个 offering——约一小时，大半在等商店商品设置。

[创建移动端账户](https://supastack.dev/zh/docs/mobile/external-accounts.md)

[构建开发客户端](https://supastack.dev/zh/docs/mobile/eas-setup.md)


## 创建 RevenueCat 账户和项目

1. 打开 [app.revenuecat.com](https://app.revenuecat.com) → 注册，用你的产品名创建一个项目。

预期结果：空的项目仪表板，带 Apps、Products、Entitlements、Offerings 和 API keys 标签页——后面几节按顺序把它们填满。


## 先建商店商品，再关联两个应用

RevenueCat 能引用之前，商店侧的商品必须先存在。iOS：[appstoreconnect.apple.com](https://appstoreconnect.apple.com) → My Apps → 用你的 `ios.bundleIdentifier` 建应用记录 → In-App Purchases 或 Subscriptions → 创建你打算销售的订阅商品（测试期间可保持草稿）。Android：[play.google.com/console](https://play.google.com/console) → 建应用 → Monetize → Products → Subscriptions（或应用内商品）。

然后在 RevenueCat 内关联两者：Apps → New app。iOS 选 App Store，填 bundle id，并提供表单要求的 App Store Connect 凭据——每个字段都链到 RevenueCat 自己的设置文档。Android 选 Play Store，填包名，上传 Play 服务账号 JSON——链接的文档带你走完在 Google Cloud 中创建它的过程。

预期结果：两个应用列在项目下，商店控制台显示你的商品已存在——此阶段草稿状态没问题。


## 商品、权益、offering

1. Products → New：每个商店商品建一个 RevenueCat 商品，并附上对应的 App Store 或 Play 商品 ID——ID 必须与控制台完全一致。

2. Entitlements → New：按 `REVENUECAT_ENTITLEMENT_ID` 命名——套件默认 `pro`——并附上授予它的商品。

3. Offerings → New：建一个 offering，加入指向你商品的包，标记为 Current——应用渲染付费墙时读的是 `offerings.current`。

`REVENUECAT_ENTITLEMENT_KEY` 保持默认 `ai.reference-task`：这是套件内部的账本键——与自带 Web 方案授予的键相同——RevenueCat 访问记录在它名下。只有当你的产品方案键变化时才改名。


## 复制密钥并注册 webhook

Project → API keys 列出下面三种。各平台的公开 SDK 密钥（iOS 是 `appl_…`，Android 是 `goog_…`）进 `apps/mobile/.env.local`——它们标识应用、不带消费权限，`EXPO_PUBLIC_` 前缀对它们是正确的。

API 密钥（`sk_…`，v1 密钥）和 webhook 授权值在 `apps/web/.env.local` 中仅限服务端——绝不 `EXPO_PUBLIC_`，绝不提交。服务器用密钥调用 RevenueCat 的订阅者 API 来验证每个工作区的购买状态。

Webhook：RevenueCat → Integrations → Webhooks → URL 设为 `{APP_URL}/api/billing/webhook/revenuecat`，Authorization 标头值设为任意你编的长随机串——然后把完全相同的字符串放进 `REVENUECAT_WEBHOOK_AUTHORIZATION`。套件逐字比对标头，其余一律拒绝，因此续费、取消和退款不用等下次打开应用就能到达服务器。

沙盒购买在生产之外自动放行；生产 env 里的 `REVENUECAT_ALLOW_SANDBOX=true` 启动时会被拒绝，所以上线后保持不设置。

```
# apps/mobile/.env.local
EXPO_PUBLIC_MOBILE_PURCHASES_PROVIDER=revenuecat
EXPO_PUBLIC_REVENUECAT_IOS_API_KEY=appl_…
EXPO_PUBLIC_REVENUECAT_ANDROID_API_KEY=goog_…

# apps/web/.env.local — server side
MOBILE_PURCHASES_PROVIDER=revenuecat
REVENUECAT_SECRET_API_KEY=sk_…
REVENUECAT_WEBHOOK_AUTHORIZATION=<the exact Authorization value set on the webhook>
REVENUECAT_ENTITLEMENT_ID=pro
REVENUECAT_ENTITLEMENT_KEY=ai.reference-task
```


## 用沙盒购买验证

购买只在开发或生产构建内运行——Expo Go 完全没有原生模块，所以这一步假设 `eas build --profile development` 已产出开发客户端（EAS 指南负责构建它）。

1. 把开发构建装到登录了沙盒账户的设备或模拟器：iOS 用 App Store Connect → Users and Access → Sandbox Testers；Android 用 Play Console → license testing。

2. 在应用中打开付费墙，用沙盒账户购买。预期结果：购买在沙盒中完成——不真的扣款——恢复购买可用，工作区权益显示激活，服务端记录在 `ai.reference-task` 键下。

常见失败：付费墙为空表示 offering 不是 Current 或商品没关联；设备上购买失败表示商店商品仍是草稿或登错了沙盒账户；权益永不翻转表示 `MOBILE_PURCHASES_PROVIDER`/`EXPO_PUBLIC_MOBILE_PURCHASES_PROVIDER` 关着，或 webhook Authorization 不匹配——RevenueCat 仪表板列出每次 webhook 送达的状态。

[在设备上构建并验证](https://supastack.dev/zh/docs/mobile/builds.md)

[Web 结账改用 Stripe](https://supastack.dev/zh/docs/web/stripe-payments.md)


如果你想继续完成设置，可以阅读《[构建和设备验证](https://supastack.dev/zh/docs/mobile/builds.md)》。


## 下一篇

[构建和设备验证](https://supastack.dev/zh/docs/mobile/builds.md)
