用 RevenueCat 做 IAP:30 分钟接入(2026)

30 分钟给 iOS App 接入内购:RevenueCat 截至 2026 年 6 月每月跟踪收入 $2,500 以内免费、超出抽 1%。含真实 product ID、SwiftUI 付费墙代码、沙盒测试,以及什么时候裸用 StoreKit 2 更合适。

RevenueCat 是 iOS 上做内购最快的方案,不用花一周去搞收据验证、恢复购买和一堆订阅边界情况。截至 2026 年 6 月,它每月跟踪收入(MTR)$2,500 以内免费,超出部分抽 1%。本文给你 30 分钟接入路径、SwiftUI 代码,以及一个诚实的判断:什么时候裸用 StoreKit 2 反而更划算。

一句话结论

  • 它是什么: Apple StoreKit 之上的一层托管服务,替你扛收据验证、订阅状态、跨平台身份,还自带一套服务端驱动的付费墙。
  • 价格(2026 年 6 月): 每月跟踪收入 $2,500 以内免费,超出抽 1%(按未扣 Apple 抽成的总收入算)。企业版另议价。(见官方价格页
  • SDK: purchases-ios 5.x(截至 2026 年 6 月 3 日为 5.76.0),在 iOS 16+ 上默认走 StoreKit 2。付费墙在 RevenueCatUI 这个包里。
  • 该用: 想这周就上内购、又不想自己维护一套验证后端。别用: 只有一个 App、只卖简单非消耗品,而且已经有成熟的服务端工程能力。

RevenueCat vs 裸 StoreKit 2

StoreKit 2 是 Apple 的原生框架,负责支付交易本身,现在也通过签名的 Transaction 对象在设备端做收据校验。但围绕它的一切——跨设备的持久订阅状态、跨平台身份、数据分析、免发版的付费墙——还是得你自己写。RevenueCat 把这层托管了。

RevenueCat裸 StoreKit 2
收据 / 交易验证服务端托管设备端 Transaction.verify;要给别处用就得自建服务器
跨设备 / 跨端订阅状态内置(CustomerInfo)自己写
跨平台(iOS + Android + 网页)一套 SDK、一个用户身份每个平台分别做
付费墙 UI服务端驱动(RevenueCatUI),免发版手写 SwiftUI
Webhook(续费 / 取消 / 退款)内置Apple App Store Server Notifications V2,自己解析
成本$2,500 MTR 以内免费,超出 1%$0(只花你自己搭基建的时间)
锁定迁移要几天

对 2026 年大多数独立和小团队 App 来说,这 1% 换回的是好几天的订阅管线工作,值。但当收入高到 1% 的总抽成超过自建基建成本,或者公司政策不允许把购买数据交给第三方时,账就反过来了。

30 秒做决定

下面大部分成立,就用 RevenueCat:

  • 你在给独立 App 加自动续订订阅或非消耗品。
  • 不想自己跑一台收据验证服务器。
  • 预期之后会扩展到多平台(iOS + Android + 网页)。
  • 跟踪收入还在 $2,500/月以内,或者能接受超出后抽 1%。

有以下情况就别用:有严格的”不外传购买数据”政策、收入很高 1% 的总抽成不是小数、或者已经有成熟的订阅后端。

接入步骤

1. 先在 App Store Connect 建产品

product ID 是永久的,建好不能改名,所以挑一套以后不会后悔的命名:

pro_monthly    自动续订订阅      $4.99/月
pro_yearly     自动续订订阅      $39.99/年
pro_lifetime   非消耗品          $79.99

每个都要在 App Store Connect → My Apps → Features → In-App Purchases(或 Subscriptions)里填本地化的展示名和说明。新建的订阅在你补全这些信息、附上一张审核截图之前,会一直停在 “Missing Metadata” 状态。

2. 把 App Store Connect 连到 RevenueCat

在 RevenueCat → Project Settings → API Keys 里拿 iOS 的公开 SDK key(以 appl_ 开头)。再到 Project Settings → Apple App Store,把 App Store Connect API 的 Issuer ID、Key ID 和 .p8 私钥填进去,这样 RevenueCat 才能读你的产品、收到服务端通知。

3. 配置 Entitlements 和 Offerings

这层间接关系,就是让你免发版也能改价、改打包组合的关键:

Entitlement: "pro"             (用户解锁了什么权限)
   关联到
Products:    pro_monthly、pro_yearly、pro_lifetime

Offering:    "default"         (付费墙展示什么)
   包含
Packages:    $rc_monthly  -> pro_monthly
             $rc_annual   -> pro_yearly
             $rc_lifetime -> pro_lifetime

权限判断永远按 entitlementpro)来,绝不按 product ID。以后加个新价格档,逻辑不用动就能生效。

4. 用 SPM 装两个 SDK 包

添加 https://github.com/RevenueCat/purchases-ios,勾选两个 product:RevenueCat(核心)和 RevenueCatUI(付费墙)。启动时初始化一次:

// App.swift
import RevenueCat

@main
struct MyApp: App {
    init() {
        Purchases.logLevel = .info
        Purchases.configure(withAPIKey: "appl_XXXXXXXXXXXXXXXX")
    }
    var body: some Scene { WindowGroup { ContentView() } }
}

SDK 5.x 在 iOS 16+ 上默认走 StoreKit 2,所以你免配置就拿到了 Apple 的签名交易校验和 async/await。

5. 展示付费墙(用 RevenueCatUI,别手写)

最快的路子是 presentPaywallIfNeeded 修饰符:它会拉取 current offering、渲染你在 dashboard 里设计好的付费墙,并且只在用户没有该权限时才弹出:

import SwiftUI
import RevenueCatUI

struct RootView: View {
    var body: some View {
        ContentView()
            .presentPaywallIfNeeded(
                requiredEntitlementIdentifier: "pro",
                purchaseCompleted: { _ in /* 已解锁 */ },
                restoreCompleted: { _ in /* 权限激活后自动关闭 */ }
            )
    }
}

想要一个手动触发的”升级 Pro”按钮?用 sheet 弹出 PaywallView()

.sheet(isPresented: $showPaywall) { PaywallView() }

因为付费墙是服务端驱动的,你能直接在 dashboard 里 A/B 测试布局和文案,不用重新提审。

6. 按 entitlement 判断权限

func userHasPro() async -> Bool {
    guard let info = try? await Purchases.shared.customerInfo() else { return false }
    return info.entitlements["pro"]?.isActive == true
}

7. 恢复购买(审核指南 3.1.1 强制要求)

任何卖非消耗品或订阅的 App 都必须提供”恢复购买”按钮,否则会被拒。RevenueCat 一行搞定:

func restore() async throws -> Bool {
    let info = try await Purchases.shared.restorePurchases()
    return info.entitlements["pro"]?.isActive == true
}

8. 用 webhook 在服务端校验

如果你有后端来发放权限,就别只信客户端。监听 RevenueCat webhook,让取消、续费、退款都能传到你的服务器:

// Vercel / Cloudflare Worker —— 最小 webhook 接收器
export async function POST(req: Request) {
  const sig = req.headers.get('Authorization');
  if (sig !== `Bearer ${process.env.RC_WEBHOOK_SECRET}`) {
    return new Response('unauthorized', { status: 401 });
  }
  const event = await req.json();
  // INITIAL_PURCHASE | RENEWAL | CANCELLATION | EXPIRATION | BILLING_ISSUE | ...
  await updateUserEntitlement(event.event.app_user_id, event.event.type);
  return new Response('ok');
}

9. 提审前先过一遍沙盒

App Store Connect → Users and Access → Sandbox → Test Accounts → +
  • 新建 test@example.com(用新邮箱,别用你自己的 Apple ID)
  • Region 选 United States
设备 → 设置 → 开发者 → 沙盒 Apple 账号 → 登录
TestFlight → 安装 build → 每个 package 都买一次 → 换台干净设备点 Restore

RevenueCat dashboard → Customer history 里几秒内就能看到沙盒交易;Apple 自己的销售报表要滞后几个小时。

别栽在这几个坑上

  • 把 product ID 硬编码进 App。 用 Offerings,这样改价、改打包都不用发版。
  • 没加”恢复购买”按钮。 3.1.1 直接拒。接好 restorePurchases()
  • 没处理 “pending purchase” 状态(Ask to Buy 家长审批、支付重试)。用沙盒的 Ask to Buy 测一遍。
  • 后端也做权限校验,却只信客户端。 任何高价值访问都要靠 webhook 在服务端确认状态。
  • 真卡被扣钱。 务必先建沙盒测试账号,用真 Apple 账号是真买真扣。
  • 以为免费额度无上限。 超过 $2,500/月跟踪收入就抽 1%,定价时要算进去。
  • 忘了 Apple 自己那一刀。 RevenueCat 的 1% 是叠在 Apple 抽成之上的,不是替代它(见 FAQ)。

FAQ

  • RevenueCat 收多少钱? 每月跟踪收入 $2,500 以内免费,超出抽 1%,按未扣 Apple 抽成的总收入计算,所以它叠在 Apple 的 15% 或 30% 之上,不在里头。企业版另议价。
  • Apple 自己抽多少? 标准 30%,但 App Store 小企业计划(Small Business Program)把它降到 15%,适用于年度净收入低于 $100 万的开发者(大多数独立开发者都符合);标准自动续订订阅在订阅者付费满一年后也会降到 15%。
  • 能在 TestFlight 用吗? 能。TestFlight build 走 StoreKit 沙盒,SDK 能正确处理沙盒交易,不会真扣钱。
  • 还需要懂 StoreKit 吗? 要懂一点。SDK 5.x 底层用 StoreKit 2,但产品、价格、税务还是你自己在 App Store Connect 里配,RevenueCat 不替你做这块。
  • Android 怎么办? 同一套 SDK 和统一 API 覆盖 Google Play。用一个 app_user_id 就能把用户在 iOS、Android、网页之间打通。
  • 以后能换掉 RevenueCat 吗? 能,但要预留几天。可以导出交易记录,重做到裸 StoreKit 2 / Google Play Billing,再重新校验权限。

相关阅读

标签: #独立开发 #App Store #IAP / 内购 #RevenueCat #变现