LASSIC Media らしくメディア
アプリ内課金のサーバー通知実装を外注で進める
LASSIC IT事業部|元請(プライムベンダー)としてシステム保守・運用を受託
この記事のポイント
- アプリ内課金の購読状態をクライアント任せにすると、解約・返金・課金停止の反映漏れが起きる理由を整理します。
- Apple「App Store Server Notifications V2」とGoogle「Real-time Developer Notifications(RTDN)」の仕組みの違いを公式ドキュメントに基づき比較します。
- 署名検証・冪等性・再送設計の実装論点と、外注する場合の委託範囲・発注前チェックポイントを解説します。
目次
サーバー通知とは — 購読状態をサーバーで正確に把握する仕組み
アプリ内課金のサーバー通知とは、Apple・Googleの決済サーバーが購読・購入状態の変化(更新・解約・返金・支払い失敗等)をリアルタイムでアプリの開発者サーバーへ送信する仕組みを指します。iOSでは「App Store Server Notifications V2」、Androidでは「Real-time Developer Notifications(RTDN)」という名称でそれぞれ提供されています。
両OSともクライアント(アプリ本体)を経由せず、決済サーバーからアプリの開発者が用意したエンドポイントへ直接(またはPub/Sub経由で)通知が送られます*1*2。この経路を使うことで、ユーザーがアプリを起動していない状態でも、解約や返金の情報をサーバー側の購読状態に反映できます。
クライアント任せの検証が抱えるリスク
アプリ内課金の実装では、クライアント側でレシート(購入情報)を取得し、それをサーバーに送って検証する方式が広く使われます。しかし、この方式だけでは購読状態の変化を捉えられない場面があります。
ユーザーが解約・返金・支払い方法の失効などを行った場合、その情報はApple・Googleの決済サーバー側で発生します。アプリを再度起動しない限り、クライアントからの再検証は走りません。その間、サーバー側のデータベースには「有料会員」の状態が残り続けます。
サブスクリプション型のアプリでは、猶予期間(grace period)中の支払い失敗や、アカウント保留といった中間状態も存在します*2。これらの状態をクライアントからの都度リクエストだけで追跡するのは難しく、サーバー通知を受信して購読テーブルを更新する仕組みが実務上必要になります。
App Store Server Notifications V2の仕組み
Apple「App Store Server Notifications V2」とは、App Store Connectで設定したエンドポイントに対し、購入・更新・解約・返金などのイベントをJWS(JSON Web Signature、署名付きJSON形式)で送信する仕組みです*1。
通知本体はsignedPayloadという1つの文字列で届き、これをApple公開鍵で検証してデコードすると、notificationType(通知種別)とsubtype(詳細区分)、そしてトランザクション情報が得られます*1。主なnotificationTypeには、購読開始を示す「SUBSCRIBED」、更新成功の「DID_RENEW」、更新失敗の「DID_FAIL_TO_RENEW」、期限切れの「EXPIRED」、猶予期間終了の「GRACE_PERIOD_EXPIRED」、返金の「REFUND」などがあります*1。
開発者はrequestTestNotificationというApp Store Server APIのエンドポイント(POST https://api.storekit.itunes.apple.com/inApps/v1/notifications/test)を呼び出すことで、本番前にテスト通知(TESTタイプ)を送信し、自社サーバーが正しく受信できるかを確認できます*3。
旧方式のV1は非推奨となっており、新規アプリはApp Store ConnectでV1を選択できません*4。既存アプリがV1からV2へ切り替えた場合も、切り替え後最長3日程度はV1形式の再送が届く可能性があるため、切り替え直後は両形式を扱える設計にしておく必要があります*4。
Google Play Real-time Developer Notificationsの仕組み
Google「Real-time Developer Notifications(RTDN)」とは、購入・購読の状態変化をGoogle Cloud Pub/Sub(Googleのメッセージ配信サービス)経由で開発者サーバーに通知する仕組みです*2。App Store Server Notificationsのように直接HTTPS POSTを受けるのではなく、開発者が用意したPub/Subトピックにメッセージが配信され、そこからPush配信または自社サーバーでのポーリングで取得する構成になります*2。
受信したメッセージのdataフィールドをBase64デコードすると、DeveloperNotificationというJSONが得られます。この中にpackageName・eventTimeMillisと、通知の種別に応じてsubscriptionNotification・oneTimeProductNotification・voidedPurchaseNotification・testNotificationのいずれかが格納されます*2。
subscriptionNotification内のnotificationTypeは整数値で、たとえば「4」が新規購入(SUBSCRIPTION_PURCHASED)、「2」が更新(SUBSCRIPTION_RENEWED)、「3」が解約(SUBSCRIPTION_CANCELED)、「13」が期限切れ(SUBSCRIPTION_EXPIRED)、「12」が失効前取り消し(SUBSCRIPTION_REVOKED)を示します*2。通知にはイベント種別と購入トークン(purchaseToken)のみが含まれ、購読の詳細情報は別途Google Play Developer APIを呼び出して取得する設計です*2。
Google Playにはもう一点、実装上重要な仕様があります。購入を検知したサーバーが3日以内に確認応答(acknowledgePurchase)を行わないと、Googleは自動的にユーザーへ返金し購入を取り消します*5。RTDNの受信処理とは別に、購入確認応答の実装漏れがないかを確認しておく必要があります。
iOSとAndroidの実装差 — 通知経路・署名・再送の違い
両OSのサーバー通知は目的が同じでも、経路・データ形式・検証方法が異なります。実装時に混同しやすい点を表に整理します。
| 項目 | iOS(App Store Server Notifications V2) | Android(RTDN) |
|---|---|---|
| 配送経路 | App Store Connectで設定したURLへHTTPS POSTで直接送信*1 | Cloud Pub/Subトピックへメッセージを発行し、Push配信またはポーリングで取得*2 |
| データ形式 | JWS(署名付きJSON)1文字列のsignedPayload*1 |
Base64エンコードされたJSON文字列*2 |
| 署名・認証の確認方法 | Apple公開鍵でJWSの署名を検証*1 | Pub/Subのpush認証設定(OIDCトークン等)で送信元を確認*2 |
| 詳細情報の取得 | 通知本体にトランザクション情報を含む*1 | 通知には購入トークンのみ。詳細はPlay Developer APIを別途呼び出す*2 |
| テスト方法 | App Store Server APIのrequestTestNotificationでTEST通知を送信可能*3 |
Play Consoleからテスト通知を送信できる仕組みが用意されている*2 |
iOSは通知そのものに情報がまとまっている一方、Androidは通知をきっかけに別APIで詳細を取りに行く設計です。この違いを理解せずに実装すると、Android側で「通知は届くが購読状態の詳細が取れない」という実装漏れが起きやすくなります。
冪等性・署名検証・レシート検証の実装論点
サーバー通知を運用するには、通知を受信するだけでなく、以下の3点を設計に組み込む必要があります。
第一に、署名検証です。iOSのJWSはApple公開鍵で署名を検証しないと、なりすまし通知を受け入れるリスクがあります*1。Androidも、Pub/SubのPush配信先を認証なしで公開設定にすると第三者からの偽装リクエストを受け付けてしまうため、Push認証の設定が必須です*2。
第二に、冪等性(同じ通知を複数回処理しても結果が変わらないようにする設計)です。両OSとも通知の重複送信・再送が発生する前提で設計されています。Google Play側はメッセージに付与されるmessageIdを使って重複を判定するよう案内されています*2。処理済みの通知IDを記録し、二重処理を防ぐテーブル設計が必要です。
第三に、レシート検証・購入確認応答との関係です。サーバー通知はあくまで「状態が変化したことを知らせる仕組み」であり、購入そのものの正当性を保証するものではありません。iOSでは通知内のトランザクション情報を、Androidでは通知後にPlay Developer APIで取得した情報を、それぞれ既存の購入検証フローと突き合わせる設計が求められます*1*2。Android側は前述の3日以内の確認応答(acknowledgePurchase)と合わせて処理順序を整理しておく必要があります*5。
内製に必要なスキル・工数と外注の委託範囲
サーバー通知の実装を内製する場合、以下の知識が必要になります。JWS署名検証とApple公開鍵の扱い(iOS)、Cloud Pub/SubのサブスクリプションとPush認証設定(Android)、両OSの通知種別と自社の購読テーブル設計をマッピングする業務知識、そして重複処理・再送を前提にしたべき等性のあるバックエンド設計です。
これらは決済基盤特有の知識であり、通常のアプリ開発(画面実装・API実装)とは別のスキルセットになります。実装を誤ると、解約したユーザーに課金が続いたり、返金されたユーザーの有料機能が止まらないといった、収益・信頼の両面に影響する不具合につながります。
外注を検討する場合、委託範囲は大きく3つに分けられます。1つ目はエンドポイント実装(署名検証・冪等性処理を含むサーバー側の受信処理)、2つ目は既存の購読テーブル・決済ロジックとの統合、3つ目は本番切り替え前のテスト通知による動作確認です。3つすべてを一括で委託するか、自社の既存システムとの統合部分だけを内製に残すかは、自社の決済基盤の複雑さによって判断が変わります。
外注時の発注準備 — 確認すべき項目
外注先に依頼する前に、自社側で以下を整理しておくと、要件のすり合わせがスムーズになります。
- 現在の購読状態をどのテーブル・カラムで管理しているか(既存の決済基盤の構成)
- iOS・Androidそれぞれの現行のレシート検証方式(クライアント検証のみか、サーバー検証を実装済みか)
- 通知受信後にどのシステム(会員基盤・CRM・分析基盤等)へ状態を反映する必要があるか
- 本番切り替え前にテスト通知で確認する体制(開発環境・サンドボックス環境の有無)
特に1と2が未整理のまま外注すると、見積もり段階で想定より作業範囲が膨らみやすくなります。既存の決済実装のドキュメントやコードを事前に共有できる状態にしておくことが、発注後の手戻りを避ける実務上のポイントです。
まとめ:サーバー通知実装の3つの判断軸
アプリ内課金のサーバー通知は、購読状態をクライアントに依存せず正確に把握するための仕組みです。要点を3つに集約すると、第一に、iOSはJWS署名付き通知を直接受信し検証する方式、Androidは Cloud Pub/Sub経由で通知を受け取り詳細を別APIで取得する方式という設計思想の違いがあります。第二に、署名検証・冪等性・既存の購入検証フローとの整合という3つの実装論点を外すと不具合の温床になります。第三に、外注する場合はエンドポイント実装・既存システムとの統合・テスト確認という委託範囲を切り分けて発注準備を進めることが重要です。
よくある質問
App Store Server NotificationsのV1とV2はどちらを使うべきですか。
新規アプリはApp Store ConnectでV1を選択できないため、V2を使う前提になります*4。既存アプリでV1を使っている場合も、Appleが検証・機能更新の対象をV2に移していることから、V2への切り替えを検討する時期といえます*4。
RTDNの通知だけで購読の詳細情報は取得できますか。
RTDNの通知本体には購入トークンと通知種別など最小限の情報しか含まれません*2。購読の詳細(有効期限・自動更新設定等)を取得するには、通知をきっかけにGoogle Play Developer APIを別途呼び出す実装が必要です*2。
サーバー通知を受信する処理はどのくらいの規模で実装しますか。
通知エンドポイントの実装自体はAPI1本ですが、署名検証・冪等性処理・既存の購読テーブルとの統合を含めると、既存の決済基盤の複雑さに応じて工数が変わります*1*2。事前に自社の購読テーブル構成とレシート検証方式を整理しておくと、外注先との要件すり合わせがしやすくなります。
Google Playの確認応答(acknowledgePurchase)を忘れるとどうなりますか。
購入から3日以内に確認応答を行わない場合、Googleはユーザーへ自動的に返金し購入を取り消します*5。RTDNの受信処理を実装しても、確認応答の呼び出し漏れがあると意図しない返金が発生するため、両者は別の実装ポイントとして確認が必要です。
サーバー通知の実装を外注する場合、既存の決済ロジックへの影響はありますか。
通知の受信処理自体は新規のエンドポイント追加ですが、受信後に既存の購読テーブルやレシート検証フローを更新する部分は既存ロジックとの統合作業になります。既存システムのどの部分に手を入れるかを外注先と事前にすり合わせることで、影響範囲を限定できます。
著者:テレリモ総研編集部 鈴木 亮佑
ご不明な点はお問い合わせフォームからもご連絡いただけます。
- *1 出典:Apple Inc.「App Store Server Notifications V2」App Store Server Notifications Documentation(developer.apple.com)
- *2 出典:Google LLC「Real-time developer notifications reference guide」Play Billing Documentation(developer.android.com)
- *3 出典:Apple Inc.「Request a Test Notification」App Store Server API Documentation(developer.apple.com)
- *4 出典:Apple Inc.「TN3180: Reverting to App Store Server Notifications V1」Technical Notes(developer.apple.com)
- *5 出典:Google LLC「Subscription lifecycle and RTDNs」Play Billing Documentation(developer.android.com)