【Google】アプリ内課金のサブスクリプションのライフサイクル
下記で Google のアプリ内課金について紹介しました。

ここでは、Google(Android)のアプリ内課金における、定期購入のライフサイクルと様々な状態変化について紹介していきたいと思います。
購読の開始から終了、猶予期間、保留状態、再開、一時停止など、各状態における処理方法や注意点を、運用経験から得たノウハウで補足していきます。
- 定期購入のライフサイクル
- 定期購入の状態別の処理方法
- 新規購入(SUBSCRIPTION_PURCHASED)
- 更新(SUBSCRIPTION_RENEWED)
- 猶予期間(SUBSCRIPTION_IN_GRACE_PERIOD)
- アカウントの保留(SUBSCRIPTION_ON_HOLD)
- アカウントの保留からの回復(SUBSCRIPTION_RECOVERED)
- 期限切れ(SUBSCRIPTION_EXPIRED)
- キャンセル (SUBSCRIPTION_CANCELED)
- 取り消し(SUBSCRIPTION_REVOKED)
- 延期(SUBSCRIPTION_DEFERRED)
- 一時停止(SUBSCRIPTION_PAUSED, SUBSCRIPTION_PAUSE_SCHEDULE_CHANGED)
- アップグレード、ダウングレード、再購読
- まとめ
定期購入のライフサイクル
Google の定期購入は、ユーザーの行動や支払い状況、開発者の管理操作など、様々な要因によって状態が変化します。
定期購入の状態を管理するための最適な方法は、purchases.subscriptionsv2.get API
を使用して最新の購読リソースを取得することです。
この API は、購入トークン(purchaseToken)に基づいて最新の購読状態を提供し、定期購入管理の信頼できる情報となります。
定期購入の状態別の処理方法
ここから、Google の API から返ってきた状態(status)ごとに、どのようにハンドリングをしていくのがベターなのか紹介していきます。
新規購入(SUBSCRIPTION_PURCHASED)
ユーザーが定期購入を購入すると、このイベントが発生します。
開発者は、purchases.subscriptionsv2.get API で状態を確認し、購入を検証した後、ユーザにコンテンツへのアクセス権を付与する必要があります。
よって、リアルタイムデベロッパー通知でも購入の通知は届くのですが、コンテンツ側のユーザとの紐付けを考えると、Android アプリ経由でバックエンド側に購入レシート情報を送って処理するのがいいですね。
また、3 日以内に購入が承認されないと、自動的に払い戻しが行われ購入は取り消されます。
更新(SUBSCRIPTION_RENEWED)
自動更新型の定期購入が更新されると、このイベントが発生します。
ユーザーが引き続き購読資格を有することを確認し、更新されている expiryTime をコンテンツ側に反映します。
猶予期間(SUBSCRIPTION_IN_GRACE_PERIOD)
支払いに問題が発生した場合、猶予期間が設けられます。
この期間中、引き続きユーザーをコンテンツにアクセスできるようにし、決済不備の修正を促すのが望ましいです。
サイレント猶予は、猶予期間に入るサブスクリプション(猶予予備群)が 24 時間は ACTIVE のまま保留されるようなイメージです。
24 時間以内に決済不備が解消されたり、そのままキャンセルされたり、状態遷移はいくつかあります。
猶予設定が 0 日の場合、そのまま 24 時間経過すると AccountHold になるイメージですね。
- SUBSCRIPTION_ON_HOLD
- SUBSCRIPTION_CANCELED
- SUBSCRIPTION_EXPIRED
- SUBSCRIPTION_RENEWED
アカウントの保留(SUBSCRIPTION_ON_HOLD)
猶予期間中に支払い問題が解決されない場合、アカウントが保留状態になります。
ユーザーのコンテンツへのアクセスをブロックし、指定した日数(デフォルトは 30 日)は、 Google 側の決済不備解消を待つことになります。
アカウントの保留からの回復(SUBSCRIPTION_RECOVERED)
保留状態のアカウントで支払い問題が解決されると、このイベントが発生します。
コンテンツへのアクセスを復元します。
期限切れ(SUBSCRIPTION_EXPIRED)
定期購入の有効期限が切れると、このイベントが発生します。
ユーザーのアクセス権を削除し、購入ステータスを無効に設定します。
キャンセル (SUBSCRIPTION_CANCELED)
ユーザーが定期購入をキャンセルするか、アカウントの保留状態から回復しない場合、このイベントが発生します。
現在の請求サイクルの終了まで、ユーザーはコンテンツにアクセスできます。
サイクル終了後、期限切れ状態になるので、そのタイミングでアクセス権を削除します。
分割払いの場合は、キャンセルは現在のコミットメント期間の終了時に有効になります。
取り消し(SUBSCRIPTION_REVOKED)
開発者による取り消しやチャージバックなどにより、定期購入が取り消されると、このイベントが発生します。
直ちにユーザーのアクセス権を取り消します。
延期(SUBSCRIPTION_DEFERRED)
開発者が GooglePlay Developer API を使用して次回の請求日を延期した場合、このイベントが発生します。
延期期間中、ユーザーは無料でコンテンツにアクセスできます。
一時停止(SUBSCRIPTION_PAUSED, SUBSCRIPTION_PAUSE_SCHEDULE_CHANGED)
ユーザーが定期購入を一時停止すると、これらのイベントが発生します。
一時停止中はコンテンツにアクセスできず、料金も発生しません。
一時停止期間の終了後、定期購入は再開されます。
再開できない場合は、アカウントが保留状態になります。
アップグレード、ダウングレード、再購読
ユーザーがアップグレード、ダウングレード、またはキャンセル後に再購読した場合、古い定期購入は無効になり、新しい購入トークンを持つ新しい定期購入が作成されます。
新しい購読リソースには、linkedPurchaseToken フィールドが含まれ、以前の購入を示します。
これにより、新しい購入を同じアカウントに関連付けることができます。
まとめ
Android アプリにおける定期購入のライフサイクル管理について紹介してきました。
他にも、プリペイドプランやプラン変更予約(ReplacementMode.DEFERRED)などサブスクリプションのサービスの幅が広がる機能が用意されています。
しかし、以外にも新しい機能について公式ドキュメントで詳細に説明されてなく、挙動を確認してみないと実態がわからないものも少なくありません。
また、これまでの経験上、ドキュメントの内容が薄い機能を試して、何度かバグに遭遇したので、新機能を導入する際には調査や検証に時間をかけた方が良さそうです。