購読アプリを作ると、こういう検証をしたくなります。
- 購読する → プレミアム表示を確認
- 解約する →「解約済み」表示を確認
- もう一度購読する → プレミアム復帰を確認
- 期限切れにする → 無料への転落を確認
各状態で画面が正しく出るかを見る必要があるので当然の手順です。iOS ではこれが事実上できません。ahha の開発で数日を溶かしてから気づきました。
リセットが必要な理由 — サーバーが二つある
[Apple / Google ストアサーバー]
決済・購読の履歴を保持
↓ receipt push
[RevenueCat サーバー]
Entitlement の状態を管理・別サーバー
片方だけ消すと、もう片方のデータから復活します。アプリを起動すると SDK が残っているほうと同期して購読が生き返ります。リセットするなら両方を消す必要があります。
Android — 手順どおりで通る
Android はきれいです。
- Google Play Console → 定期購入 → 解約
- RevenueCat ダッシュボード → Customers → 該当 App User ID → Delete Customer
- アプリを強制終了 → 再起動
App User ID はアプリ画面に出ないので、こう探します。
RevenueCat ダッシュボード → Overview →「View sandbox data」をオン →「Recent sandbox transactions」の最新行 → App User ID($RCAnonymousID:xxxxxxxx 形式)
新しい anonymous ID が生成され、無料状態で始まります。この手順で「購読 → 解約 → 再購読」を何度でも繰り返せました。
iOS — 手順どおりでも通らない
同じ手順を iOS に当てるとこうなります。
- App Store Connect → ユーザーとアクセス → Sandbox → テスターを選択 →「購入履歴を消去」
- RevenueCat → Customers → Delete Customer
- アプリ削除 → 再インストール → 再起動
- ところがアプリを開くとまた「プレミアム」になっている
理由はこうです。アプリ起動時に iOS の StoreKit が receipt を自動同期しますが、Apple サーバーに以前の決済 receipt がまだ残っています。その receipt から RevenueCat に新しい Customer が生成され、Entitlement がそのまま引き継がれます。
Delete Customer は無意味です。消した場所に同じものが再生成されます。
Apple 側の壁、四つ
1. 「購入履歴を消去」の反映が遅い
App Store Connect でボタンを押しても即座には反映されません。開発者コミュニティの報告では数時間から数十日、最大 41 日という事例もあります。
2. TestFlight の購読は設定アプリから管理できない
iOS 設定 → Apple ID → 購読 から手動解約すればいいのでは、と思いますが、Apple の公式文書にTestFlight は対象外と書かれています。一覧に出ません。
3. 開発者向けのサンドボックス購読管理画面も空
iOS 設定 → デベロッパ → Sandbox Apple Account 側にも購読管理の項目がありますが、iOS 16.1 以降で購読が表示されない問題が知られています。私のところも空でした。
4. 新しいテスターアカウントでも同じことがある
「では新しいサンドボックスアカウントで」— 同じ端末に同じアプリなら「すでに購読済み」の応答が繰り返される既知の問題があります。
スポンサーリンク
スポンサーリンク
唯一確実なのは自動期限切れを待つこと
サンドボックスの購読は実際に一か月待つわけではありません。Apple が更新周期を圧縮して回しています。
- 更新周期は App Store Connect のテスターごとの「購読更新頻度」設定に従う
- 最大 12 回の更新後、13 回目の試行で自動更新が停止する
ここで一度大きく迷った
私はこの数字を最初「6 回の更新後に期限切れ」だと思い込んでいました。どこで見たか思い出せない古い情報です。
「6 回なら数日で終わるな」と待ったのに終わらない。「何かおかしいのか」とリセット手順をやり直し、また待ち、また疑い — 間違った数字ひとつのために、二つのセッションを待機判断に費やしました。12 回が正しい数字です。
更新頻度の設定は遡らない
App Store Connect でテスターの更新頻度を変えても進行中の購読には適用されません。次の決済から適用されます。「頻度を短くして早く期限切れにしよう」は通りません。
サンドボックスでできること・できないこと
| 区分 | 内容 |
|---|---|
| できる | 決済フロー自体の動作(購入 → Entitlement 反映 → 機能解放) |
| できる | 復元ボタンの動作 |
| できる | Paywall 画面の描画・価格表示 |
| できる | 無料 → 有料の切り替え時の UI 変化 |
| 難しい(iOS) | 解約 → 再購入の繰り返し |
| 難しい(iOS) | 任意の時点で期限切れ状態を作る |
| 難しい(iOS) | 支払い問題(billing issue)状態の再現 |
代替手段は、自動期限切れを待って期限切れケースを確認し(12 回更新後)、残りは審査通過後の本番実決済で検証することです。
審査には影響しない
ひとつ安心してよい点があります。審査担当者は別の Apple ID を使います。自分のサンドボックステスターの履歴や RevenueCat の Customer 状態とは無関係です。
「サンドボックスをきれいにしてから審査を出そう」と考えているなら、その必要はありません。決済フローが動くことを確認できたら提出して大丈夫です。
Android にも注意点がある
Android はリセットが効きますが、別の罠があります。
解約は即終了ではありません。Google Play で解約しても有効期限までは Entitlement が active のまま残り、will_renew だけが false になります。
そのため「解約したのにアプリがまだプレミアムだ」という症状に出会いますが、これはシステムの観点では正常です。アプリの UX 観点では「解約済み・○月○日まで利用可能」のように表示しないとユーザーが誤解します。
この記事について
自社アプリ ahha(React Native + Expo Bare Workflow・RevenueCat サブスク・AdMob)の検証中に踏んだ内容です。
「最大 12 回の更新後に自動更新停止」は Apple 公式文書に基づく記述で、実際に 13 回目まで数えたわけではなく期限切れの時点だけを確認しています。「購入履歴を消去」の反映遅延が最大 41 日というのも開発者コミュニティの報告に基づくもので、41 日を実測したわけではありません。Android はリセット手順がうまく機能しましたが、繰り返し回数の上限があるかは確認していません。
スポンサーリンク
スポンサーリンク


コメント