RORK LABEN
NATIVE — Rork Max では AR / LiDAR スキャン、Metal を使った 3D、Dynamic Island、Siri Intents、HealthKit、NFC、App Clips、Core ML まで届きますIOS27 — iOS 27 Developer Beta 4 で Siri AI の対象が iPhone 15 Pro / 15 Pro Max・16 シリーズ・17 系へ広がり、応答が初期ベータより明確に速くなりましたDESIGN — iOS・iPadOS・macOS 27 向けの Apple 純正デザインキットが Figma と Sketch 向けに公開されました。新 OS の UI を組む段階で参照できますCANARY — Android 17(Cinnamon Bun)は従来の Developer Preview を廃し、継続更新される Canary ビルドへ移行しました。検証のタイミング設計が変わりますSPARK — Android 17 の Gemini Spark は、アプリを直接操作して配車の予約や注文といった複合的な作業を自動化しますSCALE — Rork は a16z から $2.8M を調達し、月間訪問は74万件規模まで伸びていますNATIVE — Rork Max では AR / LiDAR スキャン、Metal を使った 3D、Dynamic Island、Siri Intents、HealthKit、NFC、App Clips、Core ML まで届きますIOS27 — iOS 27 Developer Beta 4 で Siri AI の対象が iPhone 15 Pro / 15 Pro Max・16 シリーズ・17 系へ広がり、応答が初期ベータより明確に速くなりましたDESIGN — iOS・iPadOS・macOS 27 向けの Apple 純正デザインキットが Figma と Sketch 向けに公開されました。新 OS の UI を組む段階で参照できますCANARY — Android 17(Cinnamon Bun)は従来の Developer Preview を廃し、継続更新される Canary ビルドへ移行しました。検証のタイミング設計が変わりますSPARK — Android 17 の Gemini Spark は、アプリを直接操作して配車の予約や注文といった複合的な作業を自動化しますSCALE — Rork は a16z から $2.8M を調達し、月間訪問は74万件規模まで伸びています
記事一覧/開発ツール
開発ツール/2026-06-14上級

Rork のサブスクを RevenueCat の Entitlement で組む — アクセス判定・Offering 駆動のペイウォール・復元の実装メモ

Rork(Expo)アプリの課金を RevenueCat で実装する際の設計メモです。Entitlement を唯一の真実とするアクセス判定、Offering 駆動でハードコードを避けるペイウォール、購入復元とリスナーの実装、サンドボックスで詰まりやすい点まで動くコードで整理します。

Rork525RevenueCat29サブスクリプション63Expo156課金8

プレミアム記事

Rork で形になったアプリに課金を載せようとして、最初に手が止まるのは「会員かどうかをアプリのどこで、何を根拠に判定するか」という一点ではないでしょうか。商品 ID を直接見るのか、レシートを保存するのか、購入済みフラグを端末に書くのか。ここを曖昧にしたまま実装を進めると、価格を変えた途端に判定が崩れたり、機種変更したユーザーから「課金したのに使えない」という問い合わせが届いたりします。

RevenueCat を入れる本当の利点は「数十行で課金が書ける」ことよりも、判定の根拠を商品 ID ではなく Entitlement(権利)に寄せられることにあります。Rork が生成する Expo(React Native)アプリを前提に、react-native-purchases を使った Entitlement 中心の設計と、Offering 駆動のペイウォール、購入復元、そしてサンドボックスで実際に詰まった箇所を、動くコードと一緒に整理していきます。商品設定の画面手順そのものより、後から効いてくる構造のほうを厚めに書きます。

なぜ「商品 ID で判定」が後で崩れるのか

課金実装でよくある初手は、購入した商品 ID(com.example.app.pro_monthly など)をそのまま判定に使うやり方です。動くことは動きます。ただ、運用に入ると次のような場面で必ず引っかかります。

月額と年額を両方売り始めたら、pro_monthlypro_annual の両方を if で見る必要が出ます。値上げのために新しい商品 ID を切ったら、旧 ID 加入者を救うコードを足すことになります。iOS と Android で商品 ID の命名規則を変えてしまっていたら、プラットフォーム分岐が二重に増えます。気づくと「Pro 機能を解放してよいか」を判定する関数が、商品 ID の羅列で膨らんでいきます。

RevenueCat の Entitlement は、この羅列を一段抽象化する仕組みです。ダッシュボードで pro という Entitlement を一つ作り、そこに「どの商品を買えば pro が有効になるか」を紐づけます。アプリ側は商品 ID を一切知らずに「pro が active かどうか」だけを見ます。商品を増やそうが値上げしようが、紐づけはダッシュボード側の作業になり、アプリのコードは変わりません。私はここを最初に固めるかどうかで、その後半年の保守コストが変わると考えています。

判定軸はひとつに絞ります。「Entitlement が active か」だけがアクセスの真実で、端末に書いた購入フラグや商品 ID は参考情報にすぎない、という前提でコード全体を組みます。

サービス層を Entitlement 中心に書く

まず SDK を入れます。Rork(Expo)の場合、課金はネイティブモジュールを含むため Expo Go では動かず、開発ビルド(expo-dev-client)か EAS Build が必要です。ここを知らずに Expo Go で試して「購入が呼べない」と悩むのが最初の落とし穴なので先に書いておきます。

npx expo install react-native-purchases
# 開発ビルドを作る(Expo Go では課金は動かない)
npx expo prebuild
eas build --profile development --platform ios

パッケージ名は react-native-purchases です(スコープ付きの古い表記を見かけますが、現行はこちらです)。サービス層は、アプリの他の部分が「商品」や「レシート」を意識せずに済むよう、Entitlement を返す薄い窓口として書きます。

// src/services/purchases.ts
import Purchases, {
  CustomerInfo,
  PurchasesPackage,
  LOG_LEVEL,
} from 'react-native-purchases';
import { Platform } from 'react-native';
 
// 判定に使う Entitlement は「ひとつ」に決める。商品 ID はここに出てこない
export const ENTITLEMENT_ID = 'pro';
 
const API_KEY = Platform.select({
  ios: process.env.EXPO_PUBLIC_RC_IOS_KEY ?? '',
  android: process.env.EXPO_PUBLIC_RC_ANDROID_KEY ?? '',
}) as string;
 
export async function configurePurchases(appUserId?: string) {
  if (__DEV__) Purchases.setLogLevel(LOG_LEVEL.DEBUG);
  // appUserId を渡さなければ RevenueCat が匿名 ID を自動採番する。
  // 自前の認証がある場合のみ「ログイン後に logIn() で紐づけ」が正解で、
  // configure に最初から渡すと匿名→既知の付け替えが二重に走りやすい
  await Purchases.configure({ apiKey: API_KEY });
}
 
// 唯一のアクセス判定。これ以外でプレミアム可否を判断しない
export function isPro(info: CustomerInfo): boolean {
  return info.entitlements.active[ENTITLEMENT_ID] !== undefined;
}
 
export async function getCustomerInfo(): Promise<CustomerInfo> {
  return Purchases.getCustomerInfo();
}

isProCustomerInfo を引数に取り、内部状態を持たない純粋な関数になっている点が肝心です。判定がどこか一箇所のグローバル変数に依存していると、購入直後・復元直後・起動直後で値がずれます。常に「いま手元にある最新の CustomerInfo を渡して聞く」形にしておくと、後述のリスナーと素直につながります。

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
Entitlement を唯一の判定軸にし、商品 ID 直書きを排して価格改定・プラットフォーム差に強くする実装
react-native-purchases の Offering / Package と priceString で価格を遠隔差し替えするペイウォール
restorePurchases と CustomerInfo リスナー、サンドボックスで詰まる4つの箇所と回避策
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

開発ツール2026-06-25
機内モードで開くと有料会員にペイウォールが出る — RevenueCat の権限をオフラインでも保つキャッシュ設計
電波の弱い場所でアプリを開いた有料会員に、一瞬ペイウォールが見えてしまう。RevenueCat の customerInfo がオフライン起動で揺れる仕組みと、最後の正解を信頼期限つきでキャッシュして権限を維持する設計を、Expo アプリの動くコードで整理します。
開発ツール2026-06-15
解約だと思って権限を切ったユーザーは、まだ払う気だった — 支払い猶予期間と権限維持の実装
購読の支払いが失敗しても、それは解約ではありません。猶予期間中に権限を切ると復帰可能な売上を自分で捨てます。Rork(Expo)アプリで猶予・課金リトライ・アカウントホールドを取り違えず、権限維持と復帰導線を出す実装をまとめます。
開発ツール2026-04-14
Rork で課金後のステータスが反映されない — RevenueCat・StoreKit 同期問題のデバッグ手順
Rorkアプリで課金後にサブスクリプションが反映されない問題の原因と解決策を解説。RevenueCatのcustomerInfo取得タイミング・Entitlement設定・Sandbox遅延まで実例コード付きで解説します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →