rc-cancellations-pauses-winback について
Android 開発向けの RevenueCat スキルで、サブスクリプションの解約、一時停止、再獲得の扱い方を説明します。CustomerInfo の判定、Google Play の管理画面への遷移、REST API による再開日の取得を扱います。
主な機能
- 01アクセス期間中の解約検出
- 02請求問題と一時停止の識別
- 03Google Play 管理画面を開く
- 04REST API による再開日の取得
- 05再登録と再獲得イベントの処理
活用シーン
- 01解約後のアクセス終了日を表示
- 02サブスクリプション管理画面への導線
- 03バックエンド情報に基づく再開日の表示
- 04更新 webhook 後のアクセス付与
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ revenuecat/ ai-toolkit --skill rc-cancellations-pauses-winbackインストール後、Claude Code で/rc-cancellations-pauses-winbackを入力して読み込まれたか確認します。
詳細
解約、一時停止、復帰
CustomerInfo を読み取ることで、Android で解約、一時停止、復帰の状態を検出します。これらのイベントのほとんどは受動的なものです。アプリが開始するのではなく、状態を監視します。managementURL を使って Google Play の管理画面を開きます。一時停止からの再開日を REST API から取得します。
フェーズ 1:範囲を決める
ユーザーに表示する必要がある状態を決めます。
| 状態 | CustomerInfo のシグナル | 備考 |
|---|---|---|
| 解約済み、アクセス権は有効 | entitlement.unsubscribeDetectedAt != null and isActive == true | 「[expirationDate] に終了」と表示します |
| 請求に関する問題(猶予期間または保留) | entitlement.billingIssuesDetectedAt != null | 支払いに失敗し、復旧処理中です |
| 一時停止中 | 商品を引き続き所有しているが、entitlement.isActive == false | 再開日は REST API で取得する必要があります |
| 有効で自動更新中 | entitlement.willRenew == true | 通常の状態です |
バックエンドでの復帰キャンペーンのセグメント分けには、CANCELLATION webhook の cancel_reason フィールド(UNSUBSCRIBE、BILLING_ERROR、DEVELOPER_INITIATED、PRICE_INCREASE)を使用します。
フェーズ 2:準備する
Purchases.sharedInstance.getCustomerInfo(...) またはリスナーから、取得済みの CustomerInfo があることを確認します。setIncludeSuspendedSubscriptions(true) を指定して BillingClient.queryPurchasesAsync を呼び出す必要はありません。RevenueCat はサーバー側のサブスクリプション状態から一時停止状態を解決します。
ルール:
managementURLはすでにUri?です。そのまま Intent に渡してください。Uri.parse(url.toString())は呼び出さないでください。expirationDateからアクセス権を手動で計算しないでください。isActiveとwillRenewを読み取ってください。- 一時停止からの再開日は SDK にありません。バックエンドで
/v1/subscribers/{app_user_id}から取得してください。
フェーズ 3:実行する
アクセス権が残っている解約を検出する
val entitlement = customerInfo.entitlements["pro_access"]
if (entitlement?.unsubscribeDetectedAt != null && entitlement.isActive) {
entitlement.expirationDate?.let { expiry ->
showCancellationBanner(expiry)
}
}
RevenueCat が SUBSCRIPTION_CANCELED RTDN を受け取ると、unsubscribeDetectedAt が設定されます。請求期間が終了するまでは、isActive は true のままです。
一時停止を検出する
val entitlement = customerInfo.entitlements["pro_access"]
val hasAccess = entitlement?.isActive == true
// When paused, isActive == false. Pause resume date is not in the SDK.
サブスクリプションの管理画面を開く
customerInfo.managementURL?.let { url ->
startActivity(Intent(Intent.ACTION_VIEW, url))
}
managementURL の型は Uri? です。そのまま使用してください。Uri.parse(url.toString()) でラップするのは冗長であり、エラーの原因になります。
REST を使って一時停止からの再開日を取得する
バックエンドから subscribers エンドポイントを呼び出し、サブスクリプションの paused_expiration_time_ms を読み取ります。
curl -H "Authorization: Bearer $RC_SECRET_API_KEY" \
https://api.revenuecat.com/v1/subscribers/$APP_USER_ID
一時停止中は、サブスクリプションオブジェクトに paused_expiration_time_ms が含まれます。独自のエンドポイントを通じて、この情報をクライアントに公開してください。
有効期限前に再登録する
Google の有効期限前再登録フローでは SUBSCRIPTION_RESTARTED が発生します。RevenueCat は unsubscribeDetectedAt をクリアし、willRenew = true に設定します。追加のコードは不要です。customerInfo を再読み込みするだけです。
有効期限後に再登録する
有効期限後の再登録では、INITIAL_PURCHASE ではなく RENEWAL webhook が発生します。バックエンドのハンドラーでは、どちらのイベントでもエンタイトルメントへのアクセス権を付与してください。
フェーズ 4:確認する
| 確認項目 | 方法 |
|---|---|
| 解約バナーが表示される | Play ストアで解約し、新しい CustomerInfo を取得して、unsubscribeDetectedAt != null および isActive == true を確認します |
| 管理画面へのディープリンクが開く | リンクをタップし、正しい商品に対応する Play のサブスクリプション画面が開くことを確認します |
| 一時停止が反映される | Play ストアのサンドボックスで一時停止し、entitlement.isActive == false を確認します |
| 一時停止からの再開日 | /v1/subscribers/{id} を呼び出し、paused_expiration_time_ms が存在することを確認します |
| 復帰が受け付けられる | Play で設定した復帰オファーを受け入れ、購入が CustomerInfo に通常のサブスクリプションとして表示されることを確認します |
メモ
- 延長と取り消しは、バックエンドから Google Play Developer API(
purchases.subscriptionsv2.defer、purchases.subscriptionsv2.revoke)を通じて行います。RevenueCat は、その結果として発生する RTDN を処理し、CustomerInfoを自動的に更新します。 - 復帰キャンペーンに SDK コードは必要ありません。Play Console または RevenueCat ダッシュボードで設定します。
- RevenueCat は現在、一時停止専用の webhook を送信しません。Google Play RTDN の処理後、一時停止状態が
CustomerInfoに反映されます。