mcpField
R
rc-subscriptions

rc-subscriptions

github.com/revenuecat開発76659 回インストール1 日前に更新
リポジトリ

rc-subscriptions について

Android 開発者向けの RevenueCat サブスクリプション連携スキルです。Google Play の階層を RevenueCat のオブジェクトに対応づけ、購入対象の選び方を説明します。

主な機能

  1. 01Google Play と RevenueCat のオブジェクト対応
  2. 02Offering と購入可能な Package の取得
  3. 03タグまたは ID によるオファー選択
  4. 04トライアルと初回価格の表示
  5. 05エンタイトルメントによるアクセス確認

活用シーン

  1. 01固定または動的なサブスクリプション paywall の構築
  2. 02対象ユーザーへのウィンバックオファー表示
  3. 03トライアル期間と価格フェーズの表示
  4. 04購入後のユーザーアクセス確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/revenuecat/ai-toolkit --skill rc-subscriptions

インストール後、Claude Code で/rc-subscriptionsを入力して読み込まれたか確認します。

詳細

RevenueCat を使用した Android のサブスクリプション

Google Play では、サブスクリプションは「サブスクリプション」「ベースプラン」「オファー」の 3 層構造で提供されます。RevenueCat では、この階層をダッシュボードで設定する、よりフラットなモデルである「オファリング」「パッケージ」「SubscriptionOption」にまとめています。Offering を取得して Package を選び、ほとんどのフローでは SDK に適切な SubscriptionOption を選択させます。

フェーズ 1:理解する

Google Play と RevenueCat の対応関係は次のとおりです。

Google PlayRevenueCat
サブスクリプション(product ID)StoreProduct
ベースプランSubscriptionOption(ベースプラン)
オファーSubscriptionOption(オファー)
ダッシュボードでまとめたベースプランのグループOffering 内の Package

使用する主な型は次のとおりです。

  • Offering:ダッシュボードで設定する Package オブジェクトのグループです。offerings.current は、デフォルトで表示する Offering です。
  • Package:購入可能な枠(月次、年次、週次、カスタム)です。product: StoreProduct を公開します。
  • StoreProduct:Google Play のサブスクリプション商品です。subscriptionOptions: List<SubscriptionOption>? と defaultOption を持ちます。
  • SubscriptionOption:ベースプランまたはオファーです。pricingPhases、tags、id を持ちます。
  • PricingPhase:1 つの課金区分(初回トライアル、初回価格、または継続課金)です。billingPeriod、price、offerPaymentMode、recurrenceMode を持ちます。

完全な Offering 階層と、エンタイトルメントの確認に使用する CustomerInfo 階層を並べたオブジェクトモデル図については、revenuecat.com のサブスクリプションに関する章をご覧ください。

フェーズ 2:計画する

コードを書く前に、ペイウォールをオブジェクトモデルに対応付けます。次の 3 つの質問に答えてください。

2.1 ペイウォールで使用する Offering はどれですか?
  • デフォルトのペイウォール:offerings.current を使用します。これはダッシュボードで current に設定された Offering であり、標準的な選択肢です。
  • 実験またはセグメント固有のペイウォール:offerings.all["experiment-a"] を取得します。どの商品を表示するかはダッシュボードで管理できるため、カタログを変更してもアプリのアップデートは不要です。
2.2 どの Package を表示しますか?

アクセス方法は 2 つあります。レイアウトに合った方法を選んでください。

パターンAPI使用する場面
名前付きスロットoffering.monthly、offering.annual、offering.weekly期間が決まっている固定ペイウォール
反復処理offering.availablePackages動的なレイアウト、期間が不明な場合、またはカスタムのパッケージタイプ

標準の PackageType 値は MONTHLY、ANNUAL、WEEKLY、TWO_MONTH、THREE_MONTH、SIX_MONTH、LIFETIME です。それ以外は PackageType.CUSTOM です。

2.3 ペイウォールでは特定のオファーが必要ですか?それともデフォルトで問題ありませんか?
状況PurchaseParams に渡すもの
標準的なペイウォールで、ユーザーが適用可能な最適なオファーを自動的に受け取るPackage
特定のオファーが必要(引き戻し、プロモーション、選択されたタグ)SubscriptionOption

SDK の defaultOption のロジックは次のとおりです。

  1. "rc-ignore-offer" または "rc-customer-center" のタグが付いたオプションを除外します。
  2. 無料トライアル期間が最も長いオプション、または最初の課金区分の価格が最も安いオプションを選びます。
  3. 該当するオファーがない場合は、ベースプランにフォールバックします。

SDK はトライアルの適用可否を絞り込みません。Google Play はユーザーが適用対象となるオファーのみを返すため、すでに無料トライアルを利用したユーザーの場合、そのオプションは subscriptionOptions に表示されず、ベースプランがデフォルトになります。

フェーズ 3:実行する

3.1 Offerings を取得して Package を選ぶ
val offerings = Purchases.sharedInstance.awaitOfferings()
val offering = offerings.current ?: return
val monthly = offering.monthly ?: return
val product = monthly.product
val price = product.price.formatted
val period = product.period?.iso8601 // "P1M", "P1Y", null for one time

動的なリストの場合:

for (pkg in offering.availablePackages) {
    render(pkg.product.title, pkg.product.price.formatted, pkg.packageType)
}
3.2 デフォルトのオプションで購入する

ペイウォールに Package を表示し、SDK に最適なオファーを選ばせる場合は、Package を直接渡します。

val params = PurchaseParams.Builder(activity, monthly).build()
val result = Purchases.sharedInstance.awaitPurchase(params)
3.3 特定のオファーについて subscriptionOptions を詳しく確認する

タグまたはオファー ID でオファーを指定するペイウォール(引き戻しオファーなど)で使用します。

val product = offering.monthly?.product ?: return
val winBack = product.subscriptionOptions
    ?.firstOrNull { it.tags.contains("win-back") }
val option = winBack ?: product.defaultOption ?: return
val params = PurchaseParams.Builder(activity, option).build()

対象のオファーがない場合(たとえば、ユーザーが適用対象でない場合)でもペイウォールが機能するよう、必ず defaultOption にフォールバックしてください。

3.4 pricingPhases からトライアルと初回限定価格を表示する

最初の PricingPhase がある場合は、トライアル価格または初回限定価格です。トライアルを判定するには offerPaymentMode を使用します。

val option = pkg.product.defaultOption ?: return
val first = option.pricingPhases.first()
val isTrial = first.offerPaymentMode == OfferPaymentMode.FREE_TRIAL

billingPeriod.value は期間の単位における数であり、日数ではありません。期間が P1W の場合、value = 1、unit = WEEK となります。両方のフィールドを使ってラベルを作成してください。

val p = first.billingPeriod
val label = when (p.unit) {
    Period.Unit.DAY -> "${p.value} day"
    Period.Unit.WEEK -> "${p.value} week"
    Period.Unit.MONTH -> "${p.value} month"
    Period.Unit.YEAR -> "${p.value} year"
    else -> p.iso8601
}
3.5 プリペイドプラン

プリペイドのベースプランには、同じ SubscriptionOption API を使用します。pricingPhases では RecurrenceMode.NON_RECURRING が返されます。プリペイドプランで保留中の購入を受け付けるには、設定時にフラグを有効にしてください。

PurchasesConfiguration.Builder(context, apiKey)
    .pendingTransactionsForPrepaidPlansEnabled(true)
    .build()
3.6 購入後にアクセス権を確認する

エンタイトルメントを使用することをおすすめします。猶予期間、アカウント保留、残りの利用期間がある状態でのキャンセルなどを含む、サーバーで計算されたアクセス状態が反映されます。

val info = result.customerInfo
val isPro = info.entitlements["pro"]?.isActive == true

生のプロダクト ID が必要な場合は、customerInfo.activeSubscriptions を使用してください。"subscriptionId:basePlanId" 形式のエントリを含む Set<String> が返されます。

判断のまとめ

質問回答
プロダクトを取得するにはどうすればよいですか?Purchases.sharedInstance.awaitOfferings() を呼び出し、その後 offerings.current を使用します。
期間を表示するにはどうすればよいですか?offering.monthly/annual/weekly を使用するか、availablePackages を反復処理します。
購入するにはどうすればよいですか?Package を PurchaseParams に渡し、defaultOption を適用します。
特定のオファーを指定するにはどうすればよいですか?product.subscriptionOptions をタグまたは ID で絞り込み、SubscriptionOption を渡します。
無料トライアルを判定するにはどうすればよいですか?pricingPhases.first().offerPaymentMode == OfferPaymentMode.FREE_TRIAL を確認します。
アクセス権を確認するにはどうすればよいですか?customerInfo.entitlements["<id>"]?.isActive を確認します。

参考資料

コメント