最新のApp Store Server APIに移行し、App Store Server通知を組み込む方法を学びます。
これらのツールを使い始めるお手伝いをし、サーバーでアプリ内購入を最大限に活用するためのベストプラクティスを提供します。
JSON Webトークンに署名し、署名されたトランザクションを検証し、verifyReceiptから移行する方法を発見してください。
♪ ♪ガブリエル・ティン:こんにちは、私たちのセッション「アプリ内購入の統合と移行を探る」へようこそ。このセッションは2つの部分に分かれています。
1つはApp Store Server APIへの移行専用、もう1つはApp Store Server Notifications Version 2への移行専用です。
私の名前はガブリエルで、App Store Server APIに移行する方法について話し合っています。
アレックス・ベイカー:私の名前はアレックスです。App Storeサーバー通知バージョン2への移行をご案内します。
ガブリエル:まず、App Store Server APIとApp Store Server通知の簡単な紹介から始めましょう。
昨年、データを取得し、サーバーから操作を実行するための強力で安全で効率的な方法として、App Store Server APIを導入しました。
受け取ったデータが改ざんされ、あなたのために意図され、App Storeによって署名されていることを確認できるように、JSON Web署名またはJWS形式で署名された、必要なデータのみを提供することを目指しています。
たとえば、App Store Server APIエンドポイントの1つであるGet Transaction Historyエンドポイントは、新しいフィルターとソート機能と組み合わせて、元のTransactionIdだけで、指定したトランザクションのセットを取得できます。
App Store Server Notifications Version 2のペインで、表現できるサブスクリプションの状態の数が増えたため、Notifications Version 2は、サブスクリプションのすべての可能な状態をリアルタイムで更新します。
私たちは、私たちに情報を求めることなく、あなたの加入者に何が起こっているかについて知る必要があるすべての情報を積極的に提供することを目指しています。
アレックスは、このセッションの彼の部分でこれをもっと説明します。
これらの機能を簡単に効果的に使用する場合、このセッションはあなたのためです。
App Store Server APIとApp Store Server Notifications Version 2の使用を開始する方法と、いくつかの移行のヒントとベストプラクティスについて説明します。
これらのそれぞれの詳細については、以下にリストされているこれらの追加セッションを参照してください。
それでは、App Store Server APIへの移行について話し合いましょう。
まず、App Store Server APIの使用を開始する方法について説明します。
次に、JSON Webトークンに署名する詳細をいくつか掘り下げます。第三に、App Storeから受け取った署名された取引が本物であることを確認する方法を実演します。
最後に、verifyReceiptからApp Store Server APIに移行する方法について説明します。
始めましょう。
まず、異なるバージョンのStoreKitでApp Store Server APIを使用する方法について話しましょう。
まず、オリジナルのStoreKitだけで、次にStoreKit 2だけで、その後、StoreKit 2をサポートするiOSバージョン、つまりiOS 15以降とそうでないクライアントの両方を同時にサポートする方法について説明します。
まず、App Store Server APIへのリクエストがどのように見えるかを見てみましょう。
ここにリストされている5つのAPIは、originalTransactionIdをパスパラメータとして利用していることがわかります。
これにより、領収書、署名されたトランザクション、署名された更新、および通知から受け取った元のTransactionIdを使用して、これらのAPIを簡単に呼び出すことができます。
次は、ルックアップオーダーIDエンドポイントです。
このエンドポイントは、代わりに、サポートクエリに顧客から提供されたorderIdを使用します。
これは、顧客には各トランザクションの顧客の領収書に注文IDが提供されますが、元のTransactionIdは提供されないため、顧客から直接の質問をよりよく支援できるようにするためです。
これにより、顧客が手元にあるデータを使用して、顧客の問い合わせに直接対応できます。
ここにリストされている最後のエンドポイントは通知関連で、アレックスはこのセッションの彼の部分で触れます。
次に、Original StoreKitでオリジナルのTransactionIdsを入手できる場所を見てみましょう
統一されたアプリレシートでverifyReceiptを呼び出すと、App Store Server APIを呼び出すときに使用する元のTransactionIdは、このユーザーが購入した各トランザクションの領収書のin_appフィールド、および最新の_receipt_infoとpending_renewal_infoに戻ります。
元のStoreKitトランザクションから元のTransactionIdを取得する方法がわかったので、顧客、App Storeサーバー、サーバー間の全体の流れを見てみましょう。
まず、サーバーでアプリのレシートを取得します。次に、アプリのレシートを受け取り、サーバーからverifyReceiptに電話をかけます。
これにより、デコードされた領収書が返されます。
デコードされた領収書から、以前に示したのとまったく同じ方法で、元のTransactionIdをすべて収集します。
次に、収集された元のTransactionIdsのいずれかを使用して、トランザクション履歴の取得エンドポイントを呼び出すことができます。
これにより、このユーザーのトランザクションの履歴が署名されたトランザクションとして返されます。
これらの取引には、非消耗品、返金された消耗品、非更新サブスクリプション、および自動更新サブスクリプションが含まれます。
次に、特定のサブスクリプションの最新の署名済みトランザクションと署名済み更新情報を取得したい場合は、対応するoriginalTransactionIdを使用してGet All Subscription Statusesエンドポイントを呼び出します。
これにより、指定されたoriginalTransactionIdに対応するサブスクリプションのすべての署名済みトランザクションと更新が返されます。
次に、StoreKit 2トランザクションの場合、元のTransactionIdがどこにあるかを見てみましょう。
これは、トランザクションから元のTransactionIdを取得するためのクライアントのコードです。
StoreKit 2をサポートするデバイス、つまりiOS 15以降のデバイスでは、検証済みでデコードされたトランザクションで元のIDプロパティを取得して、元のTransactionIdを取得できます。
さて、サーバー側を見ると、署名されたJWSトランザクションの例です。
これは、署名されたトランザクションと、App Store Server APIおよびApp Store Server通知からの署名された更新で受信するデータタイプです。
ここでは、originalTransactionIdがトップレベルのフィールドであることがわかります。
次に、顧客、App Storeサーバー、およびStoreKit 2トランザクションのサーバー間のフロー全体を見てみましょう。
まず、デバイスで署名されたトランザクションを取ります。
StoreKit 2を使用すると、デバイス上でこのトランザクションを確認できます。
オンデバイスステータスリスナー、トランザクションリスナー、または最後のトランザクションを使用すると、最新のトランザクション、キャンセル、および払い戻しが更新され、記録保持のためにサーバーに送信されます。
たとえば、これらはサブスクリプションの更新、サブスクリプションオファーの償還、有効期限などについて更新されます。
トランザクションをサーバーに送信します。Alexが次のセクションで詳しく説明するApp Store Server Notificationsと組み合わせることで、App Store Server APIを呼び出すことなく、サブスクリプションの最新のステータスと状態を最新の状態に保つことができます。
サブスクリプションの更新日を延長するなど、サブスクリプションの操作を実行する必要がある場合は、署名されたトランザクションから元のTransactionIdを使用して、対応するエンドポイントを呼び出し、必要なデータを取り戻すことができます。
オリジナルのStoreKitとStoreKit 2でApp Store Server APIを使用する方法を見たので、StoreKitとStoreKit 2の両方をサポートする方法について話しましょう。
StoreKit 2を完全に採用することなく、App Store Server APIを利用できます。
前述のように、Original StoreKitの領収書から元のTransactionIdを取得できます。
また、JWSトランザクションからStoreKit 2で元のTransactionIDを取得することもできます。
App Store Server APIは、他のAPIとは独立して使用することもできます。他のAPIの特定のバージョンの使用とは関係ありません。
App Store Server通知に関しては、バージョン1またはバージョン2の通知で使用できます。
バージョン2を使用することをお勧めします。なぜなら、サブスクリプションの変更が発生した場合に通知し、安全なJWS形式などを使用するため、アレックスはこのセッションの彼の部分でさらに掘り下げます。
ただし、バージョン1の通知付きでも、通知なしでも、App Store Server APIを個別に使用できます。
次に、以前に説明した移行手順を完了した後、新しい購入を処理する方法について話し合いましょう。
元のStoreKitを使用してデバイスでの新しい購入をサポートするには、新しい領収書を受け取り、サーバーに送信し、途中で新しいデータを収集しながら、以前に示したのとまったく同じ手順を実行できます。
新しい領収書でverifyReceiptを呼び出し、最新の領収書の新しい元のTransactionIdでデコードされた領収書を取得し、それらの元のTransactionIdsを領収書のin_appセクションの他の元のTransactionIdsと関連付けて、トランザクション情報をグループ化します。
次に、新しいoriginalTransactionIdを取得し、対応するサブスクリプションの最新のステータスを取得するためにすべてのサブスクリプションステータスエンドポイントを呼び出す必要がある場合など、必要に応じてApp Store Server APIを呼び出すことができます。
Original StoreKitとStoreKit 2の両方でApp Store Server APIを使用する方法を取り上げたので、App Store Server APIを呼び出すための要件であるJSON Webトークンに署名する詳細をいくつか掘り下げてみましょう。
開発者アカウントがApp Store Server APIの発信者であることを認証するために、JWTとも呼ばれるJSON Webトークンを使用してリクエストを認証します。
このトークンは、サーバーからの呼び出しの承認ヘッダーとして、すべてのリクエストに含める必要があります。JWTは、ヘッダー、ペイロード、および署名で構成されています。
次に、アプリケーションに固有のJWTを構築する方法について説明します。
ここでは、JSON Webトークンがどのように構成されているか、およびヘッダーとペイロードの構造を確認できます。
トークン自体は、ピリオドで区切られた3つの部分に分けることができます。
ベース64エンコードされたヘッダー、ベース64エンコードされたペイロード、および署名シークレットを使用して署名されたベース64エンコードされたヘッダーとペイロードで構成される署名です。
ヘッダーは、データに署名する方法に関するメタデータを含むこれらのフィールドで構成されています。
ここで重要なフィールドの1つは、App Store Connectの秘密鍵IDであるキーIDです。
これは、JWTに署名するために使用するキーと一致する必要があります。
ペイロードには、特定のアプリケーションに関する追加情報が含まれています。
APIキーの取得方法に関する追加情報とガイダンスについては、記事「App Store Server APIで使用するAPIキーの作成」を参照してください。
これらの各フィールドの詳細については、記事「APIリクエストのトークンの生成」を参照してください。
すべての適切な情報を含むヘッダーとペイロードを取得したら、次にkeyIdに対応する証明書を使用してJWTに署名します。
これは、言語に関係なく使用できるコア疑似コードです。
まず、先ほど見たヘッダーで提供されたキーIDに対応する秘密鍵があることを確認してください。
次に、JWTライブラリが公開する署名関数を秘密鍵、ヘッダー、およびペイロードで呼び出します。ヘッダーには署名アルゴリズムが含まれているため、JWTライブラリは提供されたアルゴリズムに従って署名します。
最後に、Get All Subscription StatusesエンドポイントへのcURL呼び出しを認証する際のこのトークンの使用例を次に示します。
${token}と${originalTransactionId}を、それぞれ生成したトークンと希望するoriginalTransactionIdの値に置き換えます。
次に、あなたが受け取る署名されたトランザクションがあなたのものであり、App Storeによって署名されていることを確認する方法について話しましょう。
署名されたトランザクションは、本質的には、JavaScript Object Notation、または暗号的に署名されたJSONオブジェクトであり、App Storeとサーバーの間で改ざんされた場合、それを検出できます。
署名されたトランザクションは、JSON Web署名、またはJWS形式で署名されます。
App Storeが送信する署名済みのトランザクションは、JWS形式で到着します。受け取ったJWSを確認することで、データがApp Storeから来たこと、およびコンテンツが改ざんされていることを確認します。
では、署名されたトランザクションを検証する方法を見てみましょう。
まず、ベース64はヘッダーをデコードします。次に、algクレームを介して使用する署名アルゴリズムを決定できます。
これは、JWSの検証の一部として使用されます。x5cクレームの証明書チェーンはAppleによって発行され、クレームの検証は、データが適切に署名され、改ざんされていないことを示しています。
JWSの検証方法の詳細については、App Storeの開発者ドキュメントを参照してください。
本質的に、x5cチェーンは証明書のチェーンです。証明書チェーンの検証に成功すると、データが信頼できること、およびデータがAppleによって署名されていることがわかります。
注文は証明書チェーンにとって重要です。最初にルート証明書が来ます。
このルート証明書の後には、これらの証明書のそれぞれが以前の証明書によって署名されている追加の証明書が続く場合があります。
チェーンの最後の証明書をリーフ証明書と呼びます。
最初の証明書はルート証明書と呼ばれ、自己署名されています。
この証明書は、Appleの認証局から取得したルート証明書と一致する必要があります。
証明書が一致しない場合、チェーンは信頼されるべきではありません。チェーンの最後の証明書であるリーフ証明書は、JWSに署名するために使用される証明書です。
以下は、App Storeが送信するJWSのヘッダーがどのように見えるかの例です。
まず、JWSに署名するために使用されるアルゴリズムです。次はx5c証明書チェーンで、証明書は順番にリストされています。
さて、x5c証明書チェーンの生成が高レベルの概要からどのように見えるかを見てみましょう。
Appleの認証局からのルート証明書から始めます。
次に、ルート証明書を使用して中間署名証明書に署名します。中間署名証明書は、リーフ証明書に署名するために使用されます。
x5c証明書チェーンの生成がどのように見えるかを取り上げたので、チェーンの検証がどのように見えるかを見てみましょう。
リーフ証明書から始めて、中間署名証明書によって署名されていることを確認します。
次に、中間署名証明書がルート証明書によって署名されていることを確認します。
さらに、ルート証明書はApple認証局の証明書と一致する必要があります。これらの手順がすべて成功すると、チェーン全体が正当なものとして検証されます。
証明書チェーンを検証する方法について話しましょう。これは、OpenSSLを使用してx5c証明書チェーンを検証するコマンドです。
これを細かく分割すると、大まかに言えば、検証コマンドを使用すると、検証のために証明書を渡すことができます。
信頼できるフラグを使用すると、信頼する証明書、つまり、次の証明書を検証するために使用される証明書を提供できます。
この場合、Apple認証局から取得したルート証明書を渡しているため、信頼できます。
これを使用して、チェーン内の次の証明書であるWWDR証明書を検証します。
信頼できないフラグを使用すると、信頼できる証明書を使用して検証したい証明書または証明書を提供できます。
ここでは、まず、ルート証明書で署名されたApple認証局からのWWDR証明書を渡します。
これは、x5cチェーンの2番目の証明書と一致する必要があります。
そして最後に、ここのリーフ証明書は、前の証明書によって署名された最後の証明書です。
検証に成功すると、成功コードが返されます。その後、デコードされた情報の使用に進むことができます。
検証に失敗した場合は、返されたエラーコードに基づいて問題を判断します。
検証できない場合、このデータは改ざんされる可能性があり、使用すべきではありません。
OpenSSLを使用したx5c証明書チェーンの検証に関する完全な手順については、App Storeの開発者ドキュメントを参照してください。
署名されたトランザクションを検証する方法に関する疑似コードは次のとおりです。
まず、確認したいJWSを入手してください。次に、JWSライブラリが検証に必要な証明書を取得します。
適切な証明書を使用して、JWSライブラリの検証機能を呼び出します。JWSに署名する証明書はリーフ証明書ですが、一部のライブラリではチェーン全体を渡す必要があります。
通話が成功した場合は、タスクを続行できます。これがApp Store Server APIへの呼び出しの結果である場合、検証されたデータの保存に進むことができます。
通知の場合、アレックスはこのセッションの彼の部分でこれにもっと入ります。
JWSを検証できない場合は、JWSを使用しないでください。
これは、App Storeによって改ざんされたか、送信されなかったことを意味する可能性があります。
アレックスは、通知を使用する際にセキュリティをより適切に確保する方法について詳しく説明します。
JWSの検証と処理に関する完全な手順については、App Storeの開発者ドキュメントを参照してください。
それでは、verifyReceiptからApp Store Server APIへの移行のユースケースをいくつか見てみましょう。
まず、特定の購読者の最新のステータスを確認したいケースを見てみましょう。
これにより、個々のサブスクリプションの変更が最新の状態に保たされます。
以前は、加入者の最新のステータスを取得するには、verifyReceiptを呼び、有効期限の意図、grace_period_expires_dateなどのフィールドに基づいてサブスクリプションのステータスを決定する必要がありました。
現在、App Store Server APIを使用すると、Get All Subscription Statusesエンドポイントを呼び出すと、現在のステータスと最新の署名済みトランザクションと更新情報を含むステータスフィールドを使用して、サブスクリプションの最新のステータスを取得できます。
これを実行する方法の流れを見てみましょう。
まず、あなたが持っているデコードされた領収書については、私が以前に示した方法で元のTransactionIdsを取得できます。
次に、その元のTransactionIdのGet All Subscription Statusesエンドポイントを呼び出すと、そのトランザクションの最新の署名済みトランザクションと更新が返されます。
次に、最新の取引を取得するケースを見てみましょう。
最新のトランザクションを取得すると、ユーザーが購入したもの、更新されたもの、ユーザーのサブスクリプションに変更があった場合などが通知されます。
以前は、ユーザーの最新のトランザクションを取得するには、verifyReceiptを呼び、in_app配列を使用し、ユーザーのすべてのトランザクションを含む最新の_receipt_infoを調べる必要がありました。
App Store Server APIを使用すると、最新のトランザクションを取得するために、トランザクション履歴の取得エンドポイントを使用すると、ユーザーの完全な購入履歴を取得できます。
さらに、WWDC22トーク「アプリ内購入の新機能」で取り上げられている新しいフィルタとソート機能と組み合わせることで、必要なデータを効率的に正確に取得できます。
これが伴うかもしれないものの流れを見てみましょう。
そのユーザーに属する元のTransactionIdを使用すると、Get Transaction Historyエンドポイントを呼び出すことができます。
これにより、このユーザーのトランザクションの履歴が署名されたトランザクションとして返され、フィルタリングされ、ソートされ、仕様にページネーションされます。
最後に、appAccountTokenを採用するケースを見てみましょう。appAccountTokenフィールドを使用すると、StoreKit 2トランザクションをユーザーに関連付けるUUIDを提供できます。
その後、署名されたトランザクション、署名された更新、およびそのトランザクションの通知に、appAccountTokenが表示されます。以前は、StoreKit2の新しい機能であったため、元のStoreKitでappAccountTokenのサポートは存在していませんでした。
これで、Original StoreKitクライアントとの互換性をサポートするために、Original StoreKitのフィールドアプリケーションユーザー名にUUIDを提供するサポートを追加しました。
この条件の下で、そのUUIDはappAccountTokenが行うすべての機能をサポートします。その後、appAccountTokenは、Original StoreKitユーザーのverifyReceiptに戻り、App Store Server APIへの呼び出しとApp Store Server通知からの通知で、Original StoreKitとStoreKit 2の両方のユーザーにも表示されます。
このセッションのApp Store Server API部分については、これでおそれです。
次に、App Storeサーバー通知バージョン2への移行をカバーするアレックスです。
アレックス:ありがとう、ガブリエル。
私の名前はアレックスで、今日ここに来てApp Storeサーバー通知バージョン2について話し合うことに興奮しています。
まず、バージョン2の通知を開始する方法について説明します。
次に、バージョン2の通知がどのように異なり、利用可能な他のモデルに基づいて構築されるか。
第三に、通知を逃した場合の回復と、このタスクを達成するために利用可能な新しいリソースのいくつかについて話します。
最後に、通知が顧客の行動に関する洞察を提供し、サブスクリプションのライフサイクルについて知らされる追加の機会を生み出す方法。
通知とは何か、誰が使用できるのかを簡単に紹介しましょう。
App Storeサーバー通知は、アプリのユーザーが特定のアクションを実行するたびに送信するメッセージです。
これらの通知は、サブスクリプションの更新と払い戻しの更新の2つのカテゴリに分類されますが、常に追加のシナリオをカバーするために取り組んでいます。
これらの通知は、アプリで利用できない可能性のあるユーザーアクションのギャップを埋めるのに役立ちます。
例として、最も一般的なユースケースの1つは、サブスクリプションの更新です。
このトランザクションが利用可能になると、ユーザーはアプリにいない可能性があります。
App Storeサーバー通知は、サブスクリプションの更新時に最新のトランザクション情報をサーバーに直接送信することで、この問題を説明するのに役立ちます。
バージョン2の通知は、Gabrielから聞いたばかりのStoreKit 2モデルとApp Store Server APIと多くの類似点を共有しています。
しかし、それらはうまく連携しますが、それらはすべて異なる時期に採用できる独立したツールです。
最も重要なことは、バージョン2のサーバー通知を利用しながら、iOS-15以前のクライアントであるStoreKit 2が利用できないクライアントを引き続きサポートできることです。
私たちは、バージョン2の通知を、サブスクリプションライフサイクル全体を通じてユーザーに関する情報を提供するための最も詳細で柔軟なツールの1つにするために取り組んできました。
これについては、プレゼンテーションの後半で詳しく説明しますが、通知は、アプリの外で行われたアクションをキャプチャすることがほとんど不可能な情報を提供します。
特に通知とバージョン2の通知の概念に興味があることを願っています。
先に進む前に、このプレゼンテーションでは、開始と通知を受け取るためのベストプラクティスについて説明しますが、全体のストーリーを伝えるものではありません。
通知の詳細と、さまざまなユースケースに対応する方法については、これらの最近のビデオを参照してください。
バージョン2の通知を設定するを見てみましょう。
最初の通知を受け取るまで、通知を設定する方法を説明します。
まず、App Store Connectのアプリのページに移動します。下にスクロールすると、App Storeサーバー通知のセクションが表示されます。
ここでは、生産とサンドボックスの両方のオプションが表示されます。
各環境には、個別のURLと個別の通知バージョンを含めることができます。
以下は、本番設定のオプションページの例です。サンドボックスの設定はまったく同じです。
特にバージョン1の通知ユーザーの場合は、まずサンドボックス環境でバージョン2の通知を試すことをお勧めします。
これは、生産設定に影響を与えることなく、通知に慣れるのに最適な場所です。
[サンドボックスの設定] ボタンを選択し、サーバーの URL を提供し、バージョン 2 通知を選択します。
通知をトリガーする前に、サーバーエンドポイントに有効なHTTPS証明書があることを確認してください。
また、AppleのパブリックIPのサーバーへのアクセスを許可したことを確認してください。
通知を設定する際の最も一般的な失敗のいくつかは、ファイアウォールと証明書に関連しています。
これらは、最初のトラブルシューティング手順として突然通知の受信を停止したかどうかを確認するのにも最適です。
これで、最初の通知を受け取る準備が整いました。
サンドボックスでは、アプリ内サブスクリプションの購入など、さまざまなアクションによって通知がトリガーされます。
ただし、テスト中に使いやすくするために、App Store Server APIの一部である新しいRequest a Test Notificationエンドポイントを使用して通知をトリガーすることをお勧めします。
このエンドポイントは、通知テストプロセスを自動化するのに役立ちます。
テスト通知のリクエストエンドポイントをトリガーした後、通知がすぐに届くことを期待する必要があります。
通知の受信に問題がある場合は、新しいGet Test Notification Statusエンドポイントを参照してください。
これは、通知が配信されなかった理由に関する簡単なステータスを提供できます。
たとえば、SSL_ISSUEのようなステータスは、HTTPS証明書を再確認するための手がかりになります。設定変更を実行するたびに、テスト通知をトリガーすることをお勧めします。
これは、変更後も通知を受信できることを確認するのに最適な方法です。では、受け取ったばかりの通知の理解に移りましょう。
ガブリエルから以前に見た取引と同様に、通知もJWS形式です。通知ペイロードをデコードして検証する方法を見てみましょう。
まず、通知を受け取ったら、JSONボディのsignedPayloadフィールドを抽出する必要があります。
次に、署名されたトランザクションを検証するために、ガブリエルが先ほど説明したのとまったく同じ手順を実行します。
通知からの署名された通知ペイロードであるか、App Store Server APIからの署名されたトランザクションであるかにかかわらず、署名されたデータを確認するために同じ手順に従います
次に、通知がどのアプリ用かを確認することが重要です。同じエンドポイントを共有する複数のアプリがある場合、これはターゲットアプリを決定するのに適した場所です。
また、通知がターゲットとするアプリがあなたのアプリであり、通知が別の開発者を対象としていないことを確認することも重要です。
最後に、もう1つの便利なチェックは、通知の環境が本番環境またはサンドボックスのいずれかの予想される環境と一致していることを確認することです。
App Store Connectは環境ごとに個別のURLを許可するため、この要件を強制したり、URLが共有されている場合は、環境に基づいて通知を個別に保存および処理することを保証します。
この時点で、JWSは完全に検証され、さらなる処理のために保存することができます。
いくつかの基本的なチェックに加えて、サーバーが通知を非同期に処理することをお勧めします。通知の処理に時間がかかりすぎる場合、当社のサーバーはタイムアウトを記録し、通知が正常に配信されなかったと仮定します。
その後、通知を再送信します。したがって、時間のかかる処理をこの機能の外に移動すると、App Storeサーバーが正常に送信された通知を記録し、サーバーが再試行時に通知を再処理する必要がなくなります。
では、確認後、通知の本文を確認しましょう。
最初のフィールドは、通知タイプとオプションのサブタイプです。
これらを組み合わせると、通知のシナリオがわかります。これらのフィールドは、前回の通知から何が変更されたかを表示し、これらの変更が発生した理由に関する情報を提供するのにも役立ちます。
notificationUUIDは、通知ごとの一意の識別子です。
サーバーが通知を再試行すると、再試行された通知には同じnotificationUUIDが含まれます。
これは、サーバーが通知を処理したが、成功したHTTP応答コードでタイムリーに応答しなかったケースを検出するのに役立ちます。
このフィールドに基づいて、再試行による通知検出の重複を追加することをお勧めします。
signedDateフィールドは、通知がいつ作成されたかを示します。
これは、再試行された通知を検出するのに特に便利です。
次に、appAppleIdとbundleIdです。
これらは、ターゲットアプリケーションを検出するために重要です。先に説明したように、これらのフィールドをチェックし、リプレイ攻撃を防ぐために期待値と一致することを確認することが重要です。
さらに、通知の環境が期待される環境と一致していること、サンドボックス通知が本番データとして記録されていないこと、またはその逆であることを確認してください。
最後に、実際のsignedTransactionInfoとオプションのsignedRenewalInfo。
これらは、署名時の基礎となる購入の最新のステータスになります。
この時点で、通知を解析すると、最新のトランザクションと更新情報、およびステータスの変更の最新の理由が残ります。
特定の通知の設定と受信について説明したので、バージョン2の通知モデル、通知がサブスクリプションのライフサイクルを追跡するためにどのように適合するか、バージョン1の通知との比較を通じてバージョン2の通知の背後にある設計決定を調べてみましょう。
バージョン2は、購入状況に関する情報を送信する際に異なる哲学を採用しています。
通知ごとに最近の履歴全体を送信する代わりに、バージョン2の通知は、最新の取引情報、およびサブスクリプションの場合は保留中の更新情報のみの送信のみに焦点を当てています。
通知では、サブスクリプションライフサイクルのすべてのステップに関する情報を提供するために取り組んでいます。
したがって、通知には、購入またはサブスクリプションに関する最新情報のみが含まれます。
これらの通知は、サブスクリプションのステータスの完全なタイムラインを作成します。
トランザクション履歴全体を表示する必要があり、通知履歴にアクセスできない場合、これはトランザクション履歴の取得エンドポイントとよくペアになり、ページネーションされたフィルタリング可能なコンテキストでユーザーのトランザクション履歴全体を照会できます。
第二に、バージョン1の通知では、クライアントがStoreKit 2を使用する必要はありません。
そして、そうです、バージョン2もそうではありません。実際、クライアント側でどのようなフレームワークが使用されても、今日からバージョン2の通知の利点を享受し始めることができます。
最後に、バージョン2の通知は、提供される詳細のレベルを高め、追加のタイプを追加し、新しいサブタイプフィールドを追加することでカバーされるケースを拡大するために機能します。
これにより、より多くのシナリオをカバーし、サブスクリプションライフサイクルのすべての段階で通知を提供することができます。
追加した注目すべきシナリオには、有効期限、自動更新ステータスの変更に関するより詳細な情報、および払い戻しプロセスに関するより多くのシナリオが含まれます。
さて、カバーされるシナリオの複雑さを説明し、より具体的な例を提供するために、通知がサブスクリプションが最初から最後まで取る各ステップを通知する方法を見てみましょう。
サブスクリプションの前にユーザーを想像してみましょう。購読すると、ユーザーは更新サブスクリプション状態に移行し、サブタイプINITIAL_BUY通知付きのSUBSCRIBED、またはオファーが使用された場合はサブタイプINITIAL_BUYのOFFER_REDEEMEDが送信されます。
通知には、最初に署名されたトランザクションと署名された更新情報が含まれます。時間が経過し、サブスクリプションが更新され、更新状態のままになります。
更新のたびに、次の署名された取引情報を含むDID_RENEW通知を送信します。
ユーザーが自動更新を無効にすると、有効期限が切れるサブスクリプション状態に移行し、サブタイプAUTO_RENEW_DISABLED通知を含むDID_CHANGE_RENEWAL_STATUSが届きます。
自動更新を再度有効にしない場合は、期間の終了時に期限切れの状態に移行し、サブタイプのVOLUNTARY通知でEXPIREDを受け取ります。
さて、あなたは疑問に思うかもしれません、他のすべての通知タイプはどこにありますか?
通知からわかるように、サブスクリプションのライフサイクルは次のとおりです。
たくさんのことが起こっています。
そして、この図は全体の話さえ伝えていません。例えば、払い戻し/取り消しのライフサイクルはここには含まれていません。
この図は、バージョン2の通知がカバーし、サブスクリプションライフサイクルの各ステップを通知するために機能するシナリオの膨大な配列を示しています。
私が言いたいもう一つのポイントは、私たちはすべての可能な移行状態をカバーするために働くということです。
これは、サブスクリプションを追跡するための単一のソースになることで通知の有用性を高め、加入者の旅のすべてのステップを見ているという自信を高めるのに役立ちます。
ただし、このデータはすべてここにありますが、利用可能なすべてのタイプで作業する必要はありません。
たとえば、更新設定の変更に関連する通知を処理するだけでも、価値を提供できます。
特に始めたばかりの場合は、状況に最も有用な通知タイプから始めてください。
さて、サーバーをセットアップした後に何が起こるかをカバーしましょう。
すべてがスムーズに実行されていますが、残念ながら、サーバーがダウンします。
数日でも数分でも、1つだけ見逃したかもしれないと思うかどうか、この問題を解決するためのいくつかの手順について説明しましょう。
あなたのサーバーをイメージしてみましょう。
設定が正常に完了し、通知を受信しています。ある時点で、サーバーに問題があり、通知を受信できません。
私たちはまだあなたのサーバーにメッセージを送信しようとしていますが、今、それらの要求は失敗し始めます。このシナリオに対処する方法はいくつかあります。
1つ目はただ待つことです。サーバーからステータスコードが正常に届かない場合、またはまったく接続できなかった場合は、文書化された再試行ポリシーに従って通知を再試行します。
バージョン2の通知については、各試行後に、まず1時間の遅延、次に12時間の遅延、24時間、48、そして最後に72時間の遅延の後に再試行します。
通知は最初の失敗の1時間後に再試行されるため、1時間未満の停止の場合、待機はうまく機能します。
ある時点でサーバーが回復し、再び通知を受信し始めます。
まず、見逃した通知とは関係のない新しい通知を受け取ります。通知は遅れて再試行されるため、サーバーがオンラインになるとすぐに、見逃したすべての通知をすぐに受け取ることはありません。
時間が経ち、見逃した通知を受け取り始め、新しい通知が散在します。
これは、通知が元の通知か再試行された通知かをどのように検出できるかという質問を提起します。
通知を調べてみましょう。
この通知では、いくつかのフィールドを表示しているだけです。
通知にはsignedDateフィールドが含まれています。このフィールドは、署名日と通知の受信時間を比較することで、再試行を検出するのに便利です。通知を受け取った日付よりかなり早い署名日の通知が表示された場合は、停止を経験した可能性があることを示しています。
このシナリオでは、6と3というラベルの付いた通知が同じサブスクリプションのものだったと想像してみてください。
これは、元のTransactionIdsを比較することで決定できます。
この場合、通知6の後に通知3が受信されたからといって、通知6よりも新しい情報が含まれているわけではありません。
また、サーバーが通知を受信した可能性がありますが、成功したHTTP 200ステータスコードで応答できませんでした。
これにより、通知がサーバーに再配信される可能性があります。
先に説明したように、これらの要求を重複排除するためにnotificationUUIDフィールドを確認してください。
通知を正常に記録したにもかかわらず、かなりの数の再試行された通知が表示される場合があります。
この場合、通知を受け取るたびにHTTP 200応答で応答していることを確認してください。
さらに、タイムアウトを記録して通知を再送信するのを防ぐために、タイムリーにそうしており、正常に応答する前に広範な処理を行っていないことを確認してください。
時には、特に長い停止では、次の再試行は数時間または数日かかるかもしれませんし、長時間の停止のために、再試行が枯渇しているかもしれません。
見逃した通知から回復するための次のオプションは、通知履歴の取得エンドポイントです。
サーバーに送信した通知の6か月の履歴を提供する新しい通知履歴エンドポイントを発表しました。
このエンドポイントの概要と、私たちが発表する他の優れた機能については、「アプリ内購入の新機能」ビデオを参照してください。
ここでは、このエンドポイントを使用する際のベストプラクティスと、それが支援できるシナリオに焦点を当てます。
停止が解決した後、停止の開始と終了のタイムスタンプに注意してください。
通知履歴の取得エンドポイントでは、特定の期間にわたってクエリを行うことができます。
停止の開始時間と終了時間を指定することで、履歴全体のページングを要求するのではなく、見逃した可能性が高い通知のみを処理できます。
これは、回復の速度を向上させ、すでに記録された通知を再処理する作業を減らすのに役立ちます。
次に、通知履歴の取得エンドポイントでは、通知の種類でフィルタリングできます。
延長された停止を経験し、かなりの数の通知を期待している場合は、タイプ別にフィルタリングし、DID_RENEWやEXPIREDなど、すぐに影響を与える可能性のあるタイプから始めることを検討してください。
これらは、最も関連性の高いケースに対して最初に行動を起こすのに役立ちます。
通知タイプを渡すときの1つのヒントは、notificationSubtypeフィールドが省略されている場合、これはサブタイプのない通知のみを返します。
したがって、DID_RENEW notificationTypeに示されている例では、これはBILLING_RECOVERYのサブタイプでDID_RENEW通知を返しません。
最後に、通知履歴の取得エンドポイントでは、元のTransactionIdを使用して特定のユーザーにフィルタリングできます。
サブスクリプションのライフサイクルを振り返って、ユーザーの旅のすべてのステップが通知でカバーされていることを確認しました。
したがって、サブスクリプションの更新から直接有効期限が切れるまでなど、予期せぬ方法で飛び回っていることに気付いた場合、そのユーザーの通知を見逃したことを示す可能性があります。
これは、ユーザーのアカウントが予想とは異なる状態にある場合、カスタマーサポートのコンテキストでも役立ちます。このような場合、そのユーザーの通知履歴のクエリを送信できます。
通知履歴の取得エンドポイントからの応答を見てみましょう。シンプルにするために、応答には特定の値のみが表示されます。
応答で返される値は、notificationHistory配列にあります。
配列内の各エントリは、単一の通知を表します。
署名されたペイロードフィールドには、あなたに送信された正確な通知が含まれています。
次に、最初のSendAttemptResultフィールドがあります。
このフィールドには、サーバーによって記録された最初の通知試行の結果に基づいて、いくつかの値のいずれかが含まれています。
成功した場合、これは価値SUCCESSになります。
しかし、先ほど議論したように、通知がサーバーに届かないことがあります。
これらのメッセージは、問題の方向を指し示し、解決プロセスを簡素化するための一般的なガイドとなることを目的としています。
たとえば、ここにSSL_ISSUEが表示されます。
これは、サーバー上のSSL証明書またはプロセスに問題があることを示しています。このフィールドは、通知が届かなかったことを超えて、サーバーの診断の問題に対する可視性を向上させます。
また、テスト通知を使用するときにこの機能を提供するために、テスト通知ステータスの取得エンドポイントでこの同じフィールドを提供します。
これらは、オンボーディング中やトラブルシューティング中、または停止の根本原因を特定する際に遡及的に役立ちます。
通知は、ユーザーの履歴のすべてのケースをカバーしない場合があります。
通知を採用したばかりで、既存のユーザーがカバーされていない可能性があります。
また、通知履歴の取得エンドポイントで通知の保存期間よりも長い履歴を調べることもできます。
トランザクション履歴の取得エンドポイントが画像を入力する場所です。
このエンドポイントは、ガブリエルからのプレゼンテーションで先に見たように、通知の使用を開始する前にケースをカバーする履歴を顧客に提供することで、これらの問題を解決します。
それでは、通知が購入履歴を超えて洞察と機会を提供する方法について説明します。
バージョン2の通知の新しい追加機能の1つは、サブタイプフィールドで、notificationTypeフィールドに追加のコンテキストを追加します。
このフィールドは、EXPIREDやDID_CHANGE_RENEWAL_STATUSなど、特定のシナリオで詳細を提供することを目的としています。
たとえば、EXPIREDの場合、実行するアクションは通常同じで、サブスクリプションを非アクティブとしてマークし、製品へのアクセスを取り消します。
しかし、ユーザーが期限切れになった理由を理解することはしばしば役に立ちます。
それは請求の問題、自発的な選択、または決して受け入れられなかった値上げによるものですか?
別の通知であるDID_CHANGE_RENEWAL_STATUSは、通知を使用する際に追加情報や機会を得る素晴らしい例です。
表面的には、優先順位が低いようです。
すぐに行動を起こす必要はありません。
製品へのアクセスを取り消すための重要な通知は、期限切れの通知です。
だまされてはいけません。
ここにはたくさんの機会があります。
1つは、この通知は、サブスクリプションの有効期限が切れる前に顧客を取り戻すことを試みる絶好の機会です。
特に、自動更新の無効化はアプリケーション外で発生する可能性があるため、これは有効期限前に更新ステータスのこの変更で通知される唯一のトリガーになる可能性があります。
この通知は、顧客の行動に関する洞察も提供します。
この通知は、更新期間の購読者がいつキャンセルするかを判断するために使用できます。
更新の前日ですか?新規加入者は、サービスにサインアップした直後に自動更新を無効にしますか?
この種の情報は、キャンセルの原因を理解し、製品を改善するために重要です。
最後に、特定のシナリオは、通知なしにユーザーの履歴に反映されない場合があります。
たとえば、ユーザーは、サブスクリプション期間が終了する前に、自動更新を無効にしてから再アクティブ化することができます。
これはすべてサブスクリプション期間内に発生するため、サブスクリプションの長期ステータスには影響しません。
これらの決定は、顧客を理解するために重要であり、通知はこれらのタイプのシナリオを検出して記録するための情報を提供します。
全体として、通知は、カスタマージャーニーのあらゆる段階で情報を提供し、これまで以上に多くのシナリオをカバーすることで、顧客の行動を理解する機会を強化し、創出するために機能します。
結論として、今日はApp Store Server APIとApp Store Server Notificationsの両方を取り上げました。
これらは、購入の管理と追跡を取り巻く機能を改善するために利用できます。
彼らは更新されたメッセージタイプを使用し、これまで以上に多くのケースをカバーしています。
これらのシステムは、すべてのクライアントで利用でき、オリジナルのStoreKitとStoreKit 2の両方と相互互換性があり、サブスクリプションのライフサイクルを監視する能力を向上させることができます。
最後に、これらのツールはすでにサンドボックスとプロダクションの両方で利用でき、あらゆるシステムに最適です。
ご参加いただきありがとうございます。素晴らしいWWDCをお過ごしください。
WWDC
コメント