【Google】リアルタイムデベロッパー通知(RTDN)の仕組みと設定
Google Play のアプリ内課金では、購入や定期購入の状態が変わったことを、サーバーへリアルタイムに知らせる仕組みが用意されています。
それが、リアルタイムデベロッパー通知(Real-time developer notifications: RTDN)です。
このページでは、RTDN を受け取る仕組みと設定手順、通知データの構造、受信後のハンドリングの基本をまとめていきます。
アプリ内課金全体の中での位置づけは、以下のまとめページもあわせてご覧ください。
リアルタイムデベロッパー通知(RTDN)とは
RTDN は、定期購入の更新やキャンセル、商品の購入や払い戻しなど、課金に関するイベントが発生したときに、開発者のサーバーへ通知を届ける仕組みです。
通知には、イベントの種類や購入トークンなどの情報が含まれています。
ただし、RTDN が伝えるのは「状態が変わった」という事実だけで、購入の詳細までは含まれません。
そのため通知を受け取ったら、Google Play Developer API で最新の状態を取得し直すのが基本的な流れになります。
RTDN を受け取る仕組み(Cloud Pub/Sub)
RTDN は、開発者のサーバーへ直接 HTTP で届くわけではありません。
実は、Google Cloud の Cloud Pub/Sub というメッセージングサービスを経由して配信されます。
そのため、AWS やオンプレミスでバックエンドを運用している場合でも、RTDN を使うには Google Cloud のプロジェクトと Cloud Pub/Sub の設定が必要です。
設定の大きな流れは、次の 4 ステップです。
- Cloud Pub/Sub でトピックを作成する
- トピックにサブスクリプションを作成する
- トピックに Google Play の公開権限を付与する
- Google Play Console で RTDN を有効化する
1. トピックを作成する
Cloud Pub/Sub の「トピック」は、通知メッセージの送り先となる入れ物です。
Google Cloud Console で対象プロジェクトを選び、Pub/Sub からトピックを 1 つ作成します。
トピック名は、最終的に projects/{プロジェクトID}/topics/{トピックID} という形式のフルパスで扱います。
2. サブスクリプションを作成する
作成したトピックには、メッセージの受け取り方を決める「サブスクリプション」を紐づけます。
サブスクリプションには、プッシュ型とプル型の 2 種類があります。
| 配信タイプ | 通知の届き方 |
|---|---|
| プッシュ型 | Pub/Sub が、指定した HTTPS エンドポイントへ通知を送信する |
| プル型 | バックエンド側から Pub/Sub に通知を取りに行く |
公式ドキュメントでは、どちらにすべきか迷う場合は、実装しやすいプッシュ型が推奨されています。
プル型は大量メッセージのリソース最適化に向いた方式で、RTDN の用途ではあまり当てはまらない、という説明です。
3. トピックに公開権限を付与する
Google Play から Pub/Sub のトピックへ通知を書き込めるよう、トピックに公開権限を付与します。
具体的には、トピックの権限設定で、次のサービスアカウントに「Pub/Sub パブリッシャー」ロールを付与します。
google-play-developer-notifications@system.gserviceaccount.com
この権限がないと、Google Play 側からトピックへ通知を発行できません。
4. Google Play Console で RTDN を有効化する
最後に、Google Play Console 側で通知の送信先を設定します。
対象アプリの「収益化」→「収益化のセットアップ」を開き、「リアルタイムデベロッパー通知」のセクションへ進みます。
「リアルタイム通知を有効にする」にチェックを入れ、トピック名の欄に projects/{プロジェクトID}/topics/{トピックID} 形式のフルパスを入力します。
「テストメッセージを送信」を押すと、設定が正しいかどうかをその場で確認できます。
通知データの構造
RTDN の通知は、Cloud Pub/Sub のメッセージとして届きます。
メッセージの本文(data)は base64 でエンコードされており、デコードすると DeveloperNotification という JSON オブジェクトが得られます。
DeveloperNotification には、以下のフィールドが含まれます。
| 項目 | 内容 |
|---|---|
| version | 通知のバージョン |
| packageName | アプリのパッケージ名 |
| eventTimeMillis | イベント発生日時(ミリ秒) |
| subscriptionNotification | 定期購入に関する通知の場合に含まれるオブジェクト |
| oneTimeProductNotification | 1 回限りの購入に関する通知の場合に含まれるオブジェクト |
| voidedPurchaseNotification | 無効化された購入に関する通知の場合に含まれるオブジェクト |
| testNotification | テスト通知の場合に含まれるオブジェクト |
このうち subscriptionNotification・oneTimeProductNotification・voidedPurchaseNotification・testNotification は相互排他で、1 つの通知にはいずれか 1 つだけが含まれます。
つまり、どのオブジェクトが入っているかを見れば、通知の大きな種類を判別できます。
通知の種類
ここからは、通知に含まれる 4 種類のオブジェクトと、それぞれの通知タイプを紹介します。
定期購入の通知(SubscriptionNotification)
定期購入に関する通知で、version・notificationType・purchaseToken のフィールドを含みます。
notificationType には、状態変化の種類を表す整数値が入ります。
| 値 | 定数名 | 内容 |
|---|---|---|
| 1 | SUBSCRIPTION_RECOVERED | アカウント保留状態から定期購入が回復した |
| 2 | SUBSCRIPTION_RENEWED | 有効な定期購入が更新された |
| 3 | SUBSCRIPTION_CANCELED | 定期購入がキャンセルされた(ユーザー操作または決済不備による) |
| 4 | SUBSCRIPTION_PURCHASED | 新しい定期購入が購入された |
| 5 | SUBSCRIPTION_ON_HOLD | 定期購入がアカウント保留状態に入った |
| 6 | SUBSCRIPTION_IN_GRACE_PERIOD | 定期購入が猶予期間に入った |
| 7 | SUBSCRIPTION_RESTARTED | ユーザーが Google Play から定期購入を再開した |
| 8 | SUBSCRIPTION_PRICE_CHANGE_CONFIRMED | 価格変更がユーザーに確認された(非推奨) |
| 9 | SUBSCRIPTION_DEFERRED | 定期購入の更新日時が延長された |
| 10 | SUBSCRIPTION_PAUSED | 定期購入が一時停止された |
| 11 | SUBSCRIPTION_PAUSE_SCHEDULE_CHANGED | 定期購入の一時停止スケジュールが変更された |
| 12 | SUBSCRIPTION_REVOKED | 有効期限前に定期購入が取り消された |
| 13 | SUBSCRIPTION_EXPIRED | 定期購入の有効期限が切れた |
| 17 | SUBSCRIPTION_ITEMS_CHANGED | 定期購入バンドル内のアイテムが変更された |
| 18 | SUBSCRIPTION_CANCELLATION_SCHEDULED | 分割払いの定期購入のキャンセルが、コミットメント期間の終了時に有効になるよう予約された |
| 19 | SUBSCRIPTION_PRICE_CHANGE_UPDATED | 定期購入アイテムの価格変更の詳細が更新された |
| 20 | SUBSCRIPTION_PENDING_PURCHASE_CANCELED | 定期購入の保留中トランザクションがキャンセルされた |
| 22 | SUBSCRIPTION_PRICE_STEP_UP_CONSENT_UPDATED | 段階的な価格引き上げ(price step-up)の同意期間が始まった、またはユーザーが同意した(price step-up が必須の地域のみ) |
各状態が定期購入のライフサイクルの中でどう遷移するかは、定期購入のページで詳しく解説しています。
1回限りの購入の通知(OneTimeProductNotification)
1 回限りの購入(使い切り商品・非消費型商品)に関する通知です。
version・notificationType・purchaseToken・sku(商品ID)のフィールドを含みます。
| 値 | 定数名 | 内容 |
|---|---|---|
| 1 | ONE_TIME_PRODUCT_PURCHASED | 1 回限りの商品が購入された |
| 2 | ONE_TIME_PRODUCT_CANCELED | 保留中だった 1 回限りの商品の購入がキャンセルされた |
1 回限りの購入のハンドリングは、以下のページで解説しています。
無効購入の通知(VoidedPurchaseNotification)
払い戻しやチャージバックなどで無効になった購入に関する通知です。
purchaseToken・orderId・productType・refundType のフィールドを含みます。
| フィールド | 値 | 内容 |
|---|---|---|
| productType | 1 | PRODUCT_TYPE_SUBSCRIPTION(定期購入) |
| productType | 2 | PRODUCT_TYPE_ONE_TIME(1 回限りの購入) |
| refundType | 1 | REFUND_TYPE_FULL_REFUND(全額返金) |
| refundType | 2 | REFUND_TYPE_QUANTITY_BASED_PARTIAL_REFUND(数量に応じた一部返金) |
無効購入の取得と扱いについては、以下のページで解説しています。
テスト通知(TestNotification)
動作確認用の通知で、version フィールドのみを含みます。
前述の Google Play Console の「テストメッセージを送信」を押すと、この testNotification が届きます。
通知を受け取った後の処理
RTDN を受け取ったら、基本となる処理の流れは次のとおりです。
- Pub/Sub メッセージの data を base64 デコードし、
DeveloperNotificationを取り出す - 含まれているオブジェクトの種類と
notificationTypeを確認する purchaseTokenを使い、Google Play Developer API で最新の購入状態を取得する- 取得した状態をもとに、バックエンドの購入情報やアクセス権を更新する
ポイントは、通知タイプを鵜呑みにせず、必ず Developer API で最新状態を取得し直すことです。
定期購入なら purchases.subscriptionsv2.get、1 回限りの購入なら purchases.products.get で状態を確認します。
また、Pub/Sub のメッセージは、配信順序が保証されず、同じ通知が重複して届くこともあります。
そのため、通知を受け取った後の処理は冪等(何度実行しても結果が変わらない)になるよう設計しておくと安心です。
受け取った通知の内容は、ログやデータベースに履歴として残しておくと、トラブル時の調査にも役立ちます。
まとめ
Google Play のリアルタイムデベロッパー通知(RTDN)について、仕組みと設定をまとめてきました。
RTDN は Cloud Pub/Sub を経由するため設定の手間はありますが、状態変化を起点にできるので、特にサブスクリプションの運用では欠かせません。
通知はあくまで「変化のきっかけ」として扱い、最終的な判断は Developer API で取得した最新状態に委ねる、という設計を意識しておきましょう。
参考(出典)
- Real-time developer notifications reference guide(Google)
- Get ready to configure in-app products and subscriptions(Google)
