ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
App内課金の統合と移行の検討
最新のApp Store Server APIに移行したり、App Storeサーバ通知を組み込んだりする方法をご覧ください。これらのツールを使用して、ご利用のサーバ上でApp内課金を最大限に活用するベストプラクティスを紹介します。さらに、JSON Web Tokenに署名したり、署名済みトランザクションを確認したり、verifyReceiptから移行したりする方法もご覧ください。
リソース
- App Store Server API
- Apple PKI
- Creating API keys to authorize API requests
- Generating JSON Web Tokens for API requests
- Responding to App Store Server Notifications
関連ビデオ
WWDC23
WWDC22
WWDC21
Tech Talks
-
ダウンロード
♪ ♪
こんにちは 「App内課金の統合と 移行の検討」へようこそ App Store Server API への移行に特化したパートと App Storeサーバ通知V 2への 移行に特化したパートの 2部構成でお届けします App Store Server API への移行方法について お話します Gabrielです Alexです App Storeサーバ通知 V2 への移行について 説明します App Store Server APIと App Storeサーバ通知の 簡単な紹介から はじめましょう 昨年 App Store Server APIを みなさんのサーバからデータを取得し 操作する 強力で安全 効率的方法として出しました JSON Web Signatureや JWS形式で署名された 必要なデータのみの 提供を目指しています 受信データが未改ざんなこと みなさんに向けたものであること App Storeで署名されたもの であることを確認できます 例えば App Store Server API エンドポイントの1つの Get Transaction Historyでは 新しいフィルタとソート機能で originalTransactionIdだけで 指定したトランザクションセットを 取得できるようになりました App Storeサーバ通知 V2の ペインでは 表示可能なサブスクリプション 状態の数が増えたため V2通知はサブスクリプション状態の 全ての可能性を リアルタイムで更新します お客様が私達に 情報を求めなくとも 購入者の状況について 知る必要のある 全ての情報を積極的に 提供することを目指します Alexのパートで より詳しく説明します これらの機能を簡単に 効果的に使いたい方は このセッションが ぴったりです App Store Server APIと App Storeサーバ通知 V2を 使い始める方法と 移行のヒントや 最善の方法を紹介します それぞれの詳細については 以下追加セッションを 参照ください
では早速App Store Server APIの 移行について説明します まずはApp Store Server APIの 開始方法を説明します 次に JSON Web Tokenへの 署名について説明します そして App Storeからの 署名入りトランザクションが 本物であることを 確認する方法を紹介します 最後に verifyReceiptから App Store Server APIへの 移行方法 について説明します では始めましょう まず App Store Server APIを StoreKitの 異なるバージョンで使用する方法を オリジナルStoreKitのみ StoreKit 2のみ 対応したiOS 15以上の顧客と そうでない顧客の 両方に対して同時に 対応する方法 について説明します App Store Server APIへの リクエストがどのようなものか 見てみましょう ここで挙げた5つのAPIでは pathパラメータとして originalTransactionId を利用しています これにより レシート 署名付きトランザクションや 署名付き更新と通知から受け取った originalTransactionIdsを使い これらのAPIを 簡単に呼び出せます 次に Look Up Order ID エンドポイントです このエンドポイントは サポートクエリの為提供された orderIdを使用します 各トランザクションの顧客レシートに orderIdは提供されますが originalTransactionId は提供されないため 顧客からの質問に 直接対応しやすくなります これにより お客様の手元に あるデータで 問い合わせに 直接対応できる ようになります 最後のエンドポイントは 通知に関するもので Alexがこのセッションで それに触れます
originalTransactionIds をどこから取得するか オリジナルのStoreKitで 見てみましょう ユニファイドAppレシートで verifyReceiptを呼び出すと サーバAPI を呼ぶ際に使う originalTransactionIdが このユーザーが 購入したトランザクションごとに レシートの in_appフィールド latest_receipt_infoと pending_renewal_info に戻されます オリジナルのStoreKitの トランザクションから originalTransactionIdを 取得する方法がわかったので 顧客 App Storeサーバ みなさんのサーバへの流れを見ます
まず サーバでAppの レシートを取得します サーバからレシートを取り出し verifyReceiptを呼びます
これにより デコードされた レシートが返されます デコードされたレシートから 先ほどお伝えしたのと同じ方法で originalTransactionIdsを 全て集めます 次に 収集した何かの originalTransactionIdsを指定し Get Transaction Historyエンドポイントを 呼び出すと ユーザのトランザクション履歴が 署名付きトランザクション として返されます このトランザクションには 非消耗型 返金された消耗型 非自動更新 および 自動更新の サブスクリプションが含まれます 次に 特定のトランザクションの 最新の署名付きトランザクション 署名付き更新情報を取得したい場合 originalTransactionId を指定し Get All Subscription Statuses エンドポイントを呼びます これで 与えられた originalTransactionId に対応するトランザクションの全署名済み トランザクションと更新を返します StoreKit 2のトランザクションの場合 originalTransactionIdは どこにあるのかを 見てみましょう これは トランザクションから originalTransactionIdを取得する クライアント側のコードです StoreKit 2を サポートするデバイス つまりiOS 15 以降のデバイスでは 検証済みデコードされたトランザクション のoriginalIDプロパティを取得し originalTransactionIdを 取得できます サーバ側に目を向け 署名付きJWSトランザクションの例です App Store Server APIと App Storeサーバ通知から 署名付きトランザクションと更新で 受け取るデータ型です originalTransactionIdが トップレベルのフィールドです
次にStoreKit 2のトランザクションについて 顧客とApp Storeサーバ そしてみなさんのサーバの 間の流れを見てみましょう 署名されたトランザクションを デバイスから取り出します StoreKit 2では これをデバイスで確認できます デバイス上のステータスリスナー トランザクションリスナー 最終トランザクションを使用すると 最新のトランザクション キャンセル 返金の情報が更新され サーバに送信し保管できます 例えば サブスクリプションの更新 サブスクリプションオファーの利用 有効期限切れなどで 更新されます
トランザクションを サーバに送信します 後で詳しく説明する App Storeサーバ通知 と組み合わせると App Store Server API を 呼び出すことなく トランザクションの最新の状態や ステータスを 把握することができます トランザクションの更新日を 延長するなど 操作を行う必要がある場合 署名済みトランザクションから originalTransactionIdを 使い 対応する エンドポイントを呼び 必要なデータを取得できます オリジナルのStoreKitと StoreKit 2で App Store Server APIを 使用する方法を 確認しましたが 両方への 対応方法について説明します StoreKit 2を完全に 採用せずに App Store Server API を活用できます オリジナルのStoreKitでは レシートから originalTransactionIdを 取得することができます StoreKit 2ではJWSのトランザクションから originalTransactionIDを取得できます
App Store Server APIは 他のAPIに依存せずに使用できます 他のAPIの特定のバージョンに 縛られることはありません App Storeサーバ通知は バージョン1 またはバージョン2の通知で 使用することができます バージョン2の使用をお勧めします なぜなら トランザクションの 変更発生時に通知され 安全なJWS形式を 使用するからです Alexは次のパートに詳しく説明します App Store Server APIは 別途バージョン1での通知 または全く通知なしで 使用することができます 次に 説明した 移行手順が完了した後 新規購入の処理方法を 説明します オリジナルStoreKitを使用してる デバイスでの新規購入対応のため 新しいレシートを受け取り サーバに送信し 紹介したのと全く同じ手順で 新しいデータを 収集することが可能です 新しいレシートで verifyReceipt を呼び latest_receiptの新しい originalTransactionIdで デコードされたレシートを取得 originalTransactionIdを in_appセクションの originalTransactionId と関連付け トランザクション情報を グループ化してください それから 新しい originalTransactionIdを取り App Store Server APIを 必要に応じて呼べます Get All Subscription Statuses エンドポイントを呼び出して 対応トランザクションの最新状態を 取得する必要がある場合などです オリジナルのStoreKitと StoreKit 2の両方で App Store Server APIの 使用方法を説明しましたが App Store Server APIを 呼び出すために必要な JSON Web Tokenの 署名について説明します App Store Server APIの 呼び出し元がみなさんの 開発者アカウントである事を 認証するために JWTを 使用してリクエストを 認証します このトークンはサーバからの 呼び出しに認可ヘッダとして すべてのリクエストに 含める必要があります JWTは ヘッダ ペイロード 署名から構成されます 次に Appに固有のJWTを 構築する方法についてです
ここでは JSON Web Tokenの構成と ヘッダとペイロードの 構造を確認できます トークンは ピリオドで区切られ 3つの部分に分けられます Base 64エンコードのヘッダ Base 64エンコードのペイロード その両方でエンコードされた 署名です みなさんの署名シークレットを 使って署名されています ヘッダはフィールドで構成し データへの署名方法に 関するメタデータが 含まれています ここで重要な項目の1つが App Store Connectでの プライベート鍵のIDである キーIDです JWTに署名するキーと 一致する必要があります
ペイロードには みなさんの特定のAppに 関する追加情報が 含まれています その他の情報および API Keyの取得方法は 「App Store Server API API Keyの作成」 を参照してください 各項目の詳細については 「APIリクエストのトークン生成」 をご参照ください
サーバとペイロードに 適切な情報をすべて入力したら 次にkeyIdに対応する 証明書を使用して JWTに署名します 言語に関係なく使える コアとなる擬似コードです 先ほど見たヘッダで 提供されたキーIDに対応する プライベート鍵があることを 確認します 次に プライベート鍵 ヘッダ ペイロードを使用して JWTライブラリが公開する 署名関数を呼び出します ヘッダには署名アルゴリズムが 含まれているため JWTライブラリは それに従って署名します
最後に Get All Subscription Statuses エンドポイントを cURLコールで 認証する際の トークンの使用例を示します ${token}と ${originalTransactionId}を それぞれ生成した トークンと希望する originalTransactionId の値で置き換えます 次に 受け取った署名付き トランザクションが自分用であり App Storeでの署名を 確認する方法を説明します 署名付きトランザクションとは 要するに JavaScriptオブジェクト表記や JSONオブジェクトで 暗号的に署名されています App Storeとみなさんのサーバ間で 改ざんされた場合 検出できます 署名されたトランザクションは JWS形式で署名されます App Storeからの署名トランザクションは JWS形式で届きます 受け取ったJWSを検証し そのデータがApp Storeからで 内容の改ざんがないことを 確認できます 署名付きトランザクションを 検証する方法について説明します まず ヘッダをbase64で デコードします どの署名アルゴリズムを使うかは alg規制により決めます JWSの検証の一部として 使用されます x5c規制の証明書チェーンは Appleが発行しており 規制の検証は データが適切に署名され 改ざんがないことを 示すものです JWSの検証方法の 詳細についてはApp Storeの 開発者向けドキュメントを 参照してください x5cチェーンは 証明書のチェーンです 証明書チェーンの検証に 成功すると データが信頼でき Appleが署名したことが 分かります 証明書チェーンは順番が重要で まず ルート証明書が来ます このルート証明書の後に さらに証明書を追加でき これらは それぞれ前の 証明書によって署名されます チェーン内の最後の証明書を リーフ証明書と呼びます
最初の証明書は ルート証明書と呼ばれ 自己署名されています これは Apple証明書認証局から 取得したルート証明書とと 一致する必要があります 証明書が一致しない場合 そのチェーンは信頼されません リーフ証明書は チェーン内の最後の証明書で JWSに署名するために 使用される証明書です 以下は App Storeが送信する JWSのヘッダの例です 1つ目は JWSの署名に 使われるアルゴリズムです x5cの証明書チェーンですが 証明書は順番に並んでいます x5cの証明書チェーンを 作るとはどういうことか 上位の概要から 見てみましょう まずは Appleの証明書認証局から ルート証明書を取得します そして ルート証明書を用いて 中間署名証明書に署名します 中間署名証明書は リーフ証明の署名に使われます
x5c証明書チェーン生成が どの様なものか見ましたが 次はチェーンの検証を 見てみましょう リーフ証明書から順に 中間署名証明書によって 署名されていることを 確認します そして 中間署名証明書が ルート証明書によって 署名されていることを 確認します さらに ルート証明書は Apple証明書認証局のものと 一致させる必要があります これらの手順が すべて成功すれば チェーン全体の正当性が 検証されます 証明書チェーンを 検証する方法を説明します 以下は OpenSSLを使った x5cチェーンの検証コマンドです 噛み砕くと verifyという コマンドは 大雑把に言うと 証明書を渡して 検証してもらうものです trustedフラグは 信頼する証明書 または 次の証明書を検証するため 使う証明書を提供できます この場合 Apple証明書認証局から取得した ルート証明書を渡しているため 信頼できます これを利用して 次の 証明書のWWDR証明書を 検証することにします
untrustedフラグを使用すると 信頼する証明書を使用して 検証したい 1つまたは複数の 証明書を提供できます まず Apple証明書認証局から ルート証明書に 署名された WWDR証明書を渡します x5cチェーンの2 番目の 証明書と一致するはずです そして最後に ここにあるリーフ証明書は 前の証明書によって 署名された最後の証明書です 検証に成功した場合は 成功コードが返されます その後 復号化された情報を 利用することができます 検証に失敗した場合 返されたエラーコードに 基づいて 問題を判断します 確認不可の場合 改ざんの 可能性から使用はできません OpenSSLでの x5c証明書 チェーンの検証手順は App Storeの開発者向け ドキュメントをご確認ください 以下は 署名付きトランザクション 検証の擬似コードです まず 検証したい JWSを入手します JWSライブラリが求める 証明書を取り検証を行います 適切な証明書を使用して JWSライブラリの verify関数を 呼び出します JWSに署名する証明書は リーフ証明書ですが ライブラリによって チェーン全体を要求されます
成功した場合は そのまま作業を続行できます これがApp Store Server API を呼び出した結果の場合 検証済みデータの保存に 進むことができます 通知のケースについては Alexがこの後 詳しく説明します JWSが検証できない場合 使用はしないでください 改ざん済みか App Store からではない可能性があります Alexが 通知使用時の安全 を確実にする方法を説明します JWSの検証や取り扱いに 関する手順については App Storeの開発者向け 書類をご覧ください verifyReceiptからApp Store Server APIに移行する際の ユースケースを 確認してみましょう まず あるサブスクリプション登録者が 最新の状態がどうかを 確認したい場合を 見てみましょう 個々のサブスクリプションに関する 変更点を常に把握することができます 以前は サブスクリプション登録者の 最新の状態を取得するために verifyReceiptを呼び出し 有効期限や grace_period_expires_date などのフィールドに基づいて サブスクリプションの状態を 判断する必要がありました 現在 App Store Server APIで Get All Subscription Statuses エンドポイントを呼び出すと 最新のステータス 最新の署名済みトランザクションと 更新情報を含む ステータスフィールドで トランザクションの最新の状態を 取得することができます これをどのように実行するか フローを見てみましょう デコードされたレシート があれば 前述の方法で originalTransactionIdsを 取得ができます 次に originalTransactionId に対して Get All Subscription Statuses エンドポイントを呼び出すと そのトランザクションに対する最新の 署名済みトランザクションと更新が 返されます 最新のトランザクションを取得する 場合について見てみましょう 最新のトランザクションを取得することで ユーザが何を購入 更新したか サブスクリプション内容に変更があったか などを知ることができます 今までは ユーザの最新トランザクション を取得するため verifyReceipt を呼び出し in_app 配列を使用して そのユーザの全トランザクションを含む latest_receipt_info を検査していました App Store Server APIでは 最新のトランザクションを取得するため Get Transaction History エンドポイントを使用すると ユーザの完全な購入履歴を 取得することができます WWDC22のセッション 「App内課金の最新情報」 で紹介された 新しいフィルタや ソート機能とページ分割の組み合わせ 必要なデータを効率的に 取得することができます
どのような流れになるのか 見ていきましょう そのユーザに属する任意の originalTransactionId で Get Transaction History エンドポイントを呼ぶと このユーザのトランザクション履歴が 署名済みトランザクションとして返され フィルタリング ソート ページ分割が指定通り行われます
最後に appAccountTokenを 採用した場合についてです appAccountToken フィールドではStoreKit 2の トランザクションとユーザを 関連付けるUUIDを指定できます 署名済みトランザクションと更新 およびそれに関する通知に appAccountTokenが 表示されるようになります appAccountTokenは StoreKit 2の新機能で オリジナルのStoreKitでは サポートがありませんでした オリジナルのStoreKitの顧客との 互換性をサポートするため StoreKitのフィールド applicationUsernameに UUIDを供給する サポートを追加しました この条件下では そのUUIDは appAccountTokenが 行う全機能をサポートします その後 appAccountTokenは オリジナルのStoreKitユーザの場合 verifyReceiptで返され オリジナルStoreKitとStoreKit 2ユーザは App Store Server API への呼び出しや App Storeサーバ通知 からの通知にも現れます 今回のApp Store Server API の部分は以上です 次に App Storeサーバ通知 V2 への移行について説明します ありがとう Gabriel Alexです App Storeサーバ通知 V2について お話しできることを 光栄に思います まずV2通知の 始め方を説明します 次に V2通知が他のモデルと どう異なり構築されるか説明します 3つ目は 通知漏れ時の リカバリについて そのための新しい リソースをご紹介します 最後に 通知によって 顧客の行動を把握し サブスクリプションの ライフサイクルの情報を得るための 新たな機会を創出する方法 について説明します ここでは 通知とは何か 誰が使えるのかを 簡単に紹介します App Storeサーバ通知は みなさんのAppのユーザが 特定の行動を起こした時に 当社が送るメッセージです これらの通知は 大きく分けて サブスクリプションの更新と 返金の更新の2つに分類されますが その他のシナリオへの 対応も常に努力しています Appで利用できない 可能性のあるユーザ行動への ギャップを埋めるために これらの通知を提供します 例えば よく使う ユースケースのひとつに サブスクリプションの 更新があります このトランザクションが利用可能になった時 ユーザはAppにいないかもしれません App Storeサーバ通知は サブスクリプション更新時に 最新のトランザクション情報を直接 サーバにプロアクティブに 送信することで この問題を解決します V2通知はStoreKit 2モデルや 先程Gabrielから聞いた App Store Server APIと 多くの類似点があります しかし 相性が良い反面 それぞれ独立したツールで 異なるタイミングで 採用することが可能です 最も重要なことは StoreKit 2が利用できない iOS 15以前の顧客に対しても V2のサーバ通知を使いながら サポートを 継続できることです V2通知は サブスクリプションの ライフサイクル全体を通して ユーザ情報を提供する 最も詳細で柔軟な ツールの1つになるよう 取り組んできました 後ほど詳しく説明しますが 通知によって App外で行われた 把握する事がほぼ不可能な アクションの 情報を得ることができます 通知という概念 特にV2通知について 興味を持って いただけたでしょうか その前に このプレゼンテーションでは 通知受信の開始方法と 最善策を説明していますが すべてを説明している わけではありません 通知についてや様々な ケースに対応する方法は 最近のビデオを ご参照ください V2通知を設定する方法を 見てみましょう 通知の設定方法から 最初の通知を受け取るまでの 流れをご紹介します まず App Store Connectで Appページにアクセスします 下には「App Storeサーバ通知」 の項目が表示されます 本番とサンドボックス 両方の選択肢が表示されます 各環境には 個別のURLと 個別の通知バージョンを 含めることができます 以下は 本番設定のための オプションページの例です サンドボックスの設定も 全く同じです 特にVersion 1の 通知機能をご利用の方は サンドボックス環境でV2の 通知機能を試すことを勧めます プロダクションの設定に 影響を与えることなく 通知を使いこなすのに 最適な場所です サンドボックス設定を選択し サーバURLを入力 V2通知を選択します
通知を開始する前に サーバエンドポイントに有効な HTTPS 証明書がある事を 確認してください AppleのパブリックIPの サーバアクセス許可を確認します 通知を設定する際に 最も多い失敗は ファイアウォールと 証明書に関するものです 突然通知が届かない場合の 初期不具合対策として これらを確認するのも よいでしょう これで 最初の通知を 受け取る準備が整いました サンドボックスでは App内課金の購入など 様々な行動をトリガに 通知を行うことができます しかし テスト中の 使いやすさを考慮し App Store Server APIの 一部である新しい Request a Test Notificationエンドポイント での通知トリガをお勧めします このエンドポイントは テストプロセスの自動化に役立ちます Request a Test Notification エンドポイントをトリガした後 すぐに通知が届くと思います 通知の受信に 問題がある場合は 新しいGet Test Notification Status エンドポイントを参照してください 通知失敗の理由についての 簡単な状況を提供しています 例えば SSL_ISSUE のようなステータスは HTTPS証明書を 再確認する手がかりとなります 設定変更を行う際には 必ずテスト通知の トリガをお勧めします 変更後も通知を 受け取れるかどうかを 確認することができます では 今届いた通知を 理解することに移りましょう
先ほどGabrielと 見たトランザクションと同じように 通知もJWSの フォーマットになっています 通知ペイロードをデコードし 検証する方法を説明します まず 通知を受け取る際に JSON本体のsignedPayload フィールドを抽出します 次に Gabrielが説明した 署名付きトランザクションの 検証と全く同じ手順を 実行します 通知からの署名付き 通知ペイロードであっても App Store Server APIからの 署名付きトランザクションであっても 同じ手順で署名付きデータを 検証します 次に その通知がどのAppの ものかの確認が重要です 複数のAppが同じ エンドポイントを共有する場合 ここで対象Appを 決定するのがよいでしょう 通知の対象となった Appが自分のAppであり 他の開発者向けの通知 でないことの確認も重要です 最後に もう1つ有用な確認 は通知の環境が みなさんの期待する環境 本番かサンドボックス と一致することを 確認することです App Store Connectでは 環境毎 URLを指定できるため この要件を強制することも 可能ですし URLを共有している場合は 環境に応じて別々に通知の保存 処理を保証することも可能です この時点で JWSは検証され 更なる処理の為 保存可能です いくつかの 基本的なチェックの他に サーバが通知を非同期で 処理することをお勧めします 通知処理に時間がかかる場合 サーバはタイムアウトを記録 通知が正常に配信 されていないと判断します その後 通知を再送します 時間のかかる処理を この機能の外に移すことで App Storeサーバが通知を 正常に送信した記録をし リトライ時にみなさんのサーバが 通知を再処理する 必要をなくすことが できます では 検証後の通知本文を 確認しましょう 最初のフィールドは 通知タイプとオプションのサブタイプです 組み合わせ 通知の対象 シナリオを知れます これらフィールドは 前回 以降に何が変更されたか示し 変更が発生した理由について 情報提供に役立ちます notificationUUIDは 通知ごと一意の識別子です サーバが通知を リトライする場合 リトライされた通知は同じ notificationUUIDを含みます サーバが通知を処理したものの HTTPレスポンスコードの 正常な応答が得られなかった ケースの検出に役立ちます このフィールドを元に リトライによる重複通知検知を 追加することを お勧めします signedDateフィールドは 通知の作成時間を示します 特にリトライされた通知を 検出するのに有効です 次に appleIdと bundleIdです 対象となるAppを 検出するのに重要です リプレイ攻撃を防ぐためには これらのフィールドを確認し 期待値と一致することを 確認することが重要です 通知の環境が 想定環境と一致していること サンドボックス通知が 本番環境の データで記録されていない事 またその逆も 確認してください
最後にsignedTransactionInfoと オプションの signedRenewalInfoです これらは サブスクリプション時の最新の 購入状況となります この時点で 通知を解析した結果 最新のトランザクション 更新情報 最新のステータス変更理由が 残されています 特定の通知設定と 受信をカバーしたところで V2通知モデル サブスクリプションライフサイクル追跡に どのように通知を 組み合わせることができるか V1通知との比較を通して V2通知の背後にある 設計上の決定を 検証してみましょう V2では 購入時の状態に 関する情報を送る際に 異なる考え方を 採用しています V2では 通知毎に最近の履歴を すべて送信するのではなく 最新情報のみの送信に 重点を置いています 最新のトランザクション情報 サブスクリプションの場合は 更新待ち情報も表示されます
通知機能で サブスクリプション ライフサイクルの各ステップに関する 情報を提供するよう 努めます よって 通知には 購入 または サブスクリプションに関する 最新情報のみが含まれます この通知により トランザクション状態を完全な タイムラインとして 把握することができます トランザクション履歴全体表示の必要があり 通知履歴にアクセス不可の場合 Get Transaction History エンドポイントと組み合わせ ページ分割やフィルタリング 可能なコンテキストで ユーザのトランザクション履歴全体を 照会することができます V1通知ではStoreKit 2を 使用する必要はありません その通り V2もそうです クライアントサイドでどのような フレームワークを行っても 今日からV2通知の メリットを享受できます 最後に V2通知では 種類の追加やサブタイプの フィールド追加により 詳細度の向上と対象ケースの 拡大が図られています これにより 多くのシナリオをカバーし サブスクリプションライフサイクルの 各ステップで通知の提供が 可能になりました 今回追加された シナリオには 有効期限 自動更新の状態変更に関する より詳細な情報 返金処理に関する シナリオが含まれます さて 今回取り上げた シナリオの複雑さを説明し より具体的な例を示すために サブスクリプションの開始から終了までの 各ステップを 通知する方法について 見てみましょう サブスクリプション前のユーザを 想像してみましょう サブスクリプションすると ユーザは サブスクリプションの更新ステートに移行し サブタイプINITIAL_BUYの SUBSCRIBED通知が送られ オファーが使用された場合は OFFER_REDEEMEDが送信 通知には 最初に 署名されたトランザクションと 署名された 更新情報が含まれます 時間が経過すると サブスクリプションは 更新状態のままとなります 更新のたびに 次の署名付き トランザクション情報を含む DID_RENEW通知 を送信します ユーザーが自動更新を 解除するたびに サブスクリプションの 期限切れ状態に移行し サブタイプ AUTO_RENEW_DISABLEDを持つ DID_CHANGE_RENEWAL_STATUS 通知を受信します
自動更新を再有効化 しない場合 期間終了時に 期限切れ状態に移行し EXPIREDサブタイプ VOLUNTARY の通知が届きます さて 他の通知タイプは どこだと疑問に 思うかもしれません
通知で見るサブスクリプションの ライフサイクルを示します 沢山ありますね この図では 全体像がわかりません 例えば 返金や 取り消しは含まれていません この図は V2通知がカバーする 膨大なシナリオと サブスクリプションライフサイクルの 各ステップを通知するため 機能することを 説明しています
もう一点は あらゆる 遷移状態をカバーするよう 取り組んでいる ということです サブスクリプションを追跡するための 単一ソースで通知の実用性を高め サブスクリプション登録者のジャーニーの すべてのステップを見ているという 信頼性の向上に 役立ちます しかし データが全て ここにあるからと言って 利用可能な全タイプで 作業する必要はないのです 例えば 更新の設定変更の 通知を処理するだけでも 価値を提供することが できます 特にこれから始める方は 状況に応じて 最も便利な通知タイプから 始めるとよいでしょう サーバを立ち上げ 全て順調に進んでいたのに 残念ながらダウンしてしまった 場合の説明をしましょう 数日間 数分間 又は1回だけの失敗でも 問題を解決するため いくつか手順を説明します サーバを イメージしましょう 正常にセットアップされ 通知を受信しています ある時 サーバに問題が発生し 通知を受け取れません 現在もサーバへの メッセージを試みていますが そのリクエストに 失敗するようになりました このシナリオに対処する 方法はいくつかあります 1つ目は ただ待つことです みなさんのサーバから成功した ステータスコードを受信できない場合 またはサーバに全く 接続できない場合 当社のリトライポリシーに 従って通知をリトライします V2通知では まず1時間遅れ 12時間遅れ 24時間遅れ 48時間遅れ そして 72時間遅れで リトライします 待機は 最初の障害から 1時間後にリトライされるため 1時間以内の 障害に最適です
ある時点でサーバが回復し 再び通知を受け取ることが できるようになります まず 見逃した通知とは 無関係の 新しい通知が届きます 通知は遅延してリトライされる為 サーバがオンラインになると すぐに全ての見逃した通知を 受け取れる訳ではありません
しばらくすると 見逃した通知と新しい通知が 混在して 届くようになります
通知が元の通知なのか リトライされた通知なのかを どのように検出するか という疑問が出てきます 通知を 検証してみましょう
この通知では 一部の フィールドを表示しています
通知はsignedDate フィールドを含みます このフィールドは 署名日と通知受け取り時刻を 比較することにより リトライの検出に有用です 通知受け取り日より かなり前の署名日付の通知が 表示されている場合 障害が発生した 可能性があります
このシナリオでは 6と3のラベル付き通知が 同じサブスクリプションの ものであるとします これはoriginalTransactionIdsを 比較することで判断できます この場合 通知3の受信が 6の後だからといって 通知6より新しい情報が 含まれることにはなりません サーバが通知を受けたものの HTTP200 ステータスコードで 正常に応答できなかった 場合もあります これにより サーバに通知が 再送されることがあります 前述したように このリクエストを重複排除する為 notificationUUIDフィールドを チェックしましょう 通知の記録に 成功したにもかかわらず かなりの数の通知が リトライされることがあります この場合 通知を受けるたびに HTTP 200レスポンスで 応答している事を確認します タイムアウトを記録して 通知の再送信を防ぐため 正常に応答する前に 大規模な処理を行っていないか 適時に行っていることを 確認してください 特に長時間の停止では 次のリトライが数時間から 数日後なこともあり リトライを使い切場合も 通知漏れから 回復するための次の選択肢は 通知履歴を取得する エンドポイントです
顧客のサーバに送信した 通知6ヶ月間の履歴を 提供し Get Notification History エンドポイントを発表しました このエンドポイントの概要と その他素晴らしい機能については ビデオ 「App内課金の最新情報」 を参照ください このエンドポイント 使用時のベストプラクティスと 支援するシナリオに 焦点を当てます 障害が解消されたら 障害の開始と終了タイムスタンプを 注意してください Get Notification History エンドポイント では 特定の時間帯にクエリを 実行することができます 障害の開始時刻と 終了時刻を指定することで 履歴をすべて 表示する必要がなく 見逃しそうな通知だけを 処理することができます これにより 復旧スピードの 向上や作業再処理 すでに記録された通知 の削減に貢献します 次に Get Notification History エンドポイントでは 通知の種類で フィルタリングができます 長時間の障害が発生し 大量の通知が予想される場合 タイプ別にフィルタリングし DID_RENEWやEXPIREDなど すぐに影響が出るタイプから 始めることを検討してください 最も関連性の高いケースから 順に対処するのに役立ちます 通知タイプを 渡すときのヒントとして notificationSubtype フィールドが省略された場合 これはサブタイプを 持たない通知のみを返します DID_RENEW通知タイプ について示された例では サブタイプ BILLING_RECOVERYを持つ DID_RENEW通知は 返されません
最後に Get Notification History エンドポイントでは originalTransactionIdを使い 特定ユーザをフィルタできます サブスクリプションの ライフサイクルを振り返ると 私たちはユーザのジャーニーの すべてのステップを通知で カバーするように 取り組んできました 例えば 更新中のサブスクリプションが すぐに期限切れになるなど 予期しないことで 翻弄されることがあれば そのユーザに対する通知を 見落としているかもしれません ユーザアカウントが 予想と異なる状態にある場合 カスタマーサポート環境 が役に立ちます この場合 ユーザの通知履歴 クエリを送信ができます
Get Notification History エンドポイント からの応答を見てみましょう 簡略化のため 特定の値 のみを表示しています
返された値は notificationHistory 配列に格納されます
配列の各エントリは 1つの通知を表します
署名済ペイロードフィールドには みなさんに送信された 正確な通知が含まれます
次に firstSendAttemptResult フィールドです このフィールドには 当社サーバに記録された 最初の通知試行結果に基づく 値のうちの1つが含まれます 成功した場合は SUCCESS値となります しかし 先ほど説明したように 通知がサーバに 届かないことがあります これらのメッセージは 問題解決を簡略化するため 問題の方向性を示す ガイドとして意図しています 例えば ここにはSSL_ISSUE が表示されています これは SSL証明書または サーバ上のプロセスに 問題があることを 示しています このフィールドは 通知未到達の確認だけでなく サーバ問題を診断するための 可視性を向上させます テスト通知を使用する際 この機能を提供するために Get Test Notification Status に同フィールドを用意しています この情報は オンボーディング時 やトラブルシューティング時 障害の根本的原因の特定時の 振り返りに利用できます 通知は ユーザ履歴全てを カバーする訳ではありません 通知を導入したばかりで 対象外の履歴を持つ 既存ユーザーが いる場合があります Get Notification Historyエンドポイント で通知の保持期間よりも 長い履歴を 調べたい場合もあります そこで Get Transaction History エンドポイントが登場します このエンドポイントでは Gabrielが説明したように 通知を使い始める前の ケースをカバーする履歴を 顧客に提供することで これら問題を解決しています 通知によって 購入履歴 以上のインサイトや機会を 提供する方法について 説明します V2通知で追加されたものに subtypeフィールドがあり notificationTypeフィールドに コンテキストを追加しています このフィールドはEXPIREDや DID_CHANGE_RENEWAL_STATUS の様に 特定シナリオでより 詳細な情報を提供するものです 例えば EXPIREDの場合 みなさんの行動は通常同じで サブスクリプションを非アクティブでマークし 製品へのアクセスを失効させます しかし なぜ期限切れになったかを 理解することは有益です 課金の問題なのか 自主的な選択なのか 受け入れられなかった 値上げによるものなのか? もう一つの通知である DID_CHANGE_RENEWAL_STATUSは 通知を使用する際に 追加の情報と機会を 得ることができる 素晴らしい例です 表面的には 優先順位が低いように見えます 直ちに行動を起こす 必要はありません 製品へのアクセスを 無効にする重要な通知は EXPIRED通知です 騙されないでください 多くのチャンスがあります 1つは この通知は サブスクリプション期間が満了する前に 顧客を取り戻すための 絶好の機会だという事です 特に 自動更新の停止は Appの外部で 発生する可能性があるため 有効期限前にRenewal状態の 変化を通知する唯一のものです また この通知により 顧客行動を把握もできます この通知により サブスクリプション登録が 更新期間のどの時期に 解約するのかを 判断することができます 更新の前日? 新規登録者が サービスに申し込んだ後 すぐに自動更新を 解除していませんか? このような情報は 解約原因究明や製品改良のため 重要な情報となります 最後に 特定のシナリオは 通知されないと ユーザーの履歴に 反映されないことがあります 例えば ユーザは サブスクリプション 期間が終了する前に 自動更新を一旦停止した後 再度有効にできます これはすべて サブスクリプション 期間内に行われるため サブスクリプション期間の 長期化には影響しません このような判断は 顧客を理解する上で重要で 通知はこのような シナリオを検知し 記録するための 情報を提供します 通知は これまで以上に 多くのシナリオをカバーし 顧客体験の各ステップ において情報を提供する事で 顧客の行動を理解する機会を 強化 創造するものです 本日はApp Store Server APIと App Store サーバ通知 の両方について 説明しました 購入した商品の 管理 追跡機能を 向上させるためにも 利用できます メッセージタイプを更新し 従来以上に多くカバーできます これらのシステムは すべてのクラアンとで利用でき オリジナルのStoreKitとStoreKit 2 両方に互換性があり サブスクリプションライフサイクルの 監視能力を向上できます このツールは既にサンドボックスと 本番の両方で利用可能で どんなシステムにも 追加することができます ありがとうございました 素晴らしいWWDCを
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。