ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
App内課金の最新情報
iPhone、iPad、Mac、Apple Watchで、App内課金エクスペリエンスをさらに向上させる方法をご確認ください。StoreKit 2やApp Store Server APIの強化をはじめ、App Storeサーバ通知の改善点について解説します。さらに、App Transaction APIでApp課金を検証する方法、プロパティをStoreKitモデルに追加する方法、SwiftUI対応のAPIやStoreKitメッセージを組み込む方法、トランザクションでapplicationUsernameを保持する方法をご確認ください。また、稼働しているサーバサイドにおいてもApp Storeサーバ通知を最大限に活用する方法、ユーザトランザクション履歴を取得する新たな方法、サーバが停止した場合の復旧手順を紹介します。
リソース
- environment
- Get Notification History
- Get Test Notification Status
- Get Transaction History
- recentSubscriptionStartDate
- Request a Test Notification
関連ビデオ
WWDC23
WWDC22
WWDC21
-
ダウンロード
♪ 穏やかな音楽 ヒップホップミュージック ♪ ♪ こんにちは ようこそ 「App内課金の最新情報」 について話します Daniです StoreKitチームの エンジニアをしています 本日は同僚のIanと一緒に 今年 App内課金に導入した 新しい改善点について 紹介します 昨年は StoreKit 2を導入しました App内課金を 簡単に実現するために 一から設計された 新しいAPIのセットです StoreKit 2は async/await パターンを使用した Swiftの並行処理を含む モデン言語機能を採用しています サーバサイドでは App Storeサーバの エンドポイントを全て新しくし これらのStoreKitの 新機能を補完しました これらのサーバエンドポイント を使用することで サーバ上で トランザクション情報を取得し サブスクリプション状態を 確認することが容易になります また App Storeサーバ通知の バージョン2をリリースし みなさんサーバ上で サブスクリプションのライフサイクルを これまで以上に簡単に 追跡できるようになりました 本日は これらの 新しいAPIと 新しいStoreKitの モデルにもたらす 機能の拡張について 説明します その後 IanはApp Store Server APIの拡張や App Storeサーバ通知の 新しくなったAPIを含む 興味深い新しいサーバ関連の アップデートを紹介していきます まず最初に Appの購入 を検証するための 新しいApp Transaction API について説明します その後 StoreKitの モデルに追加された 新しいプロパティ について掘り下げていきます サブスクリプションの オファーコードを使用し 顧客にAppの レビューを依頼するための 新しいSwiftUIフレンドリーな APIを紹介します そして 顧客に App Storeのメッセージを 表示するために活用する APIであるStoreKit Messagesを紹介します そして オリジナルから最新の StoreKit APIに移行する際に applicationUsernameを 保持するために 追加している 拡張機能について説明します 今回のプレゼンテーションでは 私のお気に入りのApp Food Truckを使って 説明します Food Truck Appでは ドーナツの ポップアップストアを運営し さまざまな都市を訪れて ドーナツを提供しています では 始めましょう まずはApp Transactionに ついてです App Transactionは 顧客のAppの購入を 確認するための 新しいAPIです App Transactionは Appが実行されているデバイスに 購入するための 署名された情報を示します JWSを使用して 署名されます オリジナルのStoreKit APIの レシートのAppの詳細部分 を置き換えます トランザクションの 検証と同様に StoreKitはAppの トランザクションの検証を 自動で行います ただし 希望する場合 自身で検証を 行うことも可能です JWS署名の検証は 十分にドキュメント化された標準です 公開ドキュメントを参考に 独自の検証を 実装することができます StoreKitは 必要に応じて App Transactionを 自動的に更新します レアなケースですが ユーザーが何かおかしいと 思った場合は リフレッシュすることができます 顧客がAppのトランザクションを 更新できるように AppにUIを提供する 必要があります これはApp Transactionを 更新すると ユーザー認証が求められるため ユーザーアクションの 結果として対応する場合にのみ 使用する必要があります App Transactionの利点は 不正行為を防止することだけではありません 有料Appから App内課金のある無料Appに ビジネスモデルを 変更したい場合や どの顧客がAppを 事前予約したか知りたい場合 Appがいつ購入されたのか 調べたいだけの場合などにおいて App Transactionはこれらの状況に 対応することができます Appのレシートに レシートペイロードは Appに関する購入データと 発生したすべてのApp内課金と 関連します これらは StoreKitで 2つの独立した コンポーネントに 分割されました 一つ目は トランザクション履歴です StoreKitの トランザクションAPIは ユーザーのApp内課金の すべての履歴を デバイス上で確認できます これらのAPIは ユーザーの 最新トランザクション 未完了のトランザクション 現在の権利など 必要な情報を正確に 見つけることができます サーバ上でこれらの処理を 行いたい場合は App Store Server APIから ユーザーの購入履歴を 取得することも可能です このセッションの後半で Ianがこの件に関する興味深い アップデート内容について話します 2つ目のコンポーネントは App Transactionであり これにはAppが 実行されるデバイスに対して 有効であることを確認する 必要なデータが含まれています App Transactionを使えば Appの購入を簡単に 検証することができるため 簡潔にその使い方の 例を紹介します その前に 私のお気に入りの Appについて 背景をいくつか 紹介したいと思います Food Truckでは ドーナツの配達 基本的なソーシャルフィードでの チェックイン 販売履歴の可視化など ができるようになります データベースでこれらの 情報を保持することは Appにとって継続的な コストとなります そのコストを カバーするために 年間販売履歴チャートを 1回限りの購入として提供します さらに ソーシャルフィードを 強化させたいと考えています ポップストアについて 他の人の意見を 見るだけでなく 顧客との関わりができる ツールを提供したいと思っています これはサブスクリプションの サービスとして 月額プランと年額プランを 用意する予定です Food Truckは有料App として始まりましたが 今後はApp内課金がある 無料Appに切り替えていく予定です しかし すでにFood Truckを 購入された既存の顧客には 取り残されたような 気持ちになってほしくありません そこで Food Truckを 購入した顧客が 有料のプレミアムコンテンツに 引き続きアクセスできるように App Transactionを 活用します ここにFood Truckの タイムラインがあります 初期リリースでは Food Truckは $4.99の有料Appとして開始しました バージョン1.0では ドーナツの配達 基本的なソーシャルフィード 販売履歴チャートなどが提供されました バージョン8.0のリリースで ビジネスモデルが 変更されました Food Truckは 現在は無料ですが プレミアム機能をアンロックする 様々なApp内課金も含まれます 現在では年間販売 履歴チャートが 1回限りの 非消耗型になり 高度なエンゲージメント ツールが使える プレミアムソーシャルフィードの 新しいサブスクリプションサービスがあります その影響を受ける 可能性のある 2つのタイプの異なる 顧客を紹介します Aliceはバージョン2.5で Food Truck Appの存在を知り デジタルワールドで ドーナツへの情熱を 共有したいと思ったそうです 彼女は私のAppを$4.99で購入し ドーナツ配達の道のりを 歩み始めたのです 2人目の顧客であるBobは 友人の紹介でFood Truck Appを知り App Storeで バージョン8.2のAppを 無料でダウンロードしました このシナリオでは 無料になる前に 私のAppを購入したAliceは すでに購入したすべての プレミアムコンテンツに アクセスすることができます。 彼女にはまだソーシャル フィードプレミアムの サブスクリプション購入をする オプションがありますが 私は当初含まれていた 年間の 販売履歴チャートを否認したくありません BobはAppを 無料で手に入れました App内課金を完了するまで 機能やコンテンツを アンロックしないように することも知っています App Transactionで どのように実現するか コードで見てみましょう AppTransaction.sharedを 呼び出して Appのトランザクションを 取得するところから始めます この呼び出しにより Appの トランザクションを含む VerificationResultを 取得します その結果により AppTransaction typeには JWSペイロードがあります 次に 結果を切り替えます 結果が未検証の場合 Appの購入が App Storeで確認できなかったことを ユーザーに警告し Appのトランザクションを 更新するのに 適切なタイミングとなります この時に Appでは 最低限の体験を提供します その結果が検証された場合 ユーザーがAppを購入したかを これを機会に 確認することにします Appを購入した顧客には 購入したサービスを 付与する必要があります これには originalAppVersion プロパティを使います このプロパティでは 顧客が初めてAppを ダウンロードしたときの Appのバージョンを 知ることができます バージョン8.0がApp内課金で 無料になったバージョンです 私はユーザーがAppを バージョン8.0より以前に 購入したかどうかを 確認する関数に 顧客のoriginalAppVersion を渡します それにより ユーザーに対して どのようにプレミアムコンテンツを 提供する必要があるのか 十分な情報を 得た上で判断することができます Aliceのように Appを以前に購入した顧客には 購入時に付与済みの ユーザーの権利がある コンテンツを提供します 私の場合 彼女の配達のために 年間販売履歴チャートを 解除します また 実施する可能性のある 他のApp内課金を確認して 提供したいと思います そうでなければ Bobのように ビジネスモデルを切り替えた後に ユーザーが私のAppを ダウンロードしたと確信できます これは ユーザーの現在の権利を 確認する良い機会であり 私は彼ら彼女らが購入した機能や コンテンツのロックを 解除することができます 数行のコードで Appの購入を検証し ユーザーがAppの 有料バージョンを ダウンロードしたかどうか を確認し 顧客がAppを購入したか どうかにかかわらず すぐにプレミアムコンテンツの 提供を開始できます App Transactionでは 初期のサポーターも 最近Appを ダウンロードしたばかりの 顧客も簡単に サポートすることができます StoreKitの モデルに追加する 新しいプロパティの話を したいと思います これらの中の一つ目のプロパティは 価格ロケールです 価格ロケールは StoreKitプロダクトに含まれます オリジナルの購入APIと 連動しているため 価格ロケールについては すでにご存知かもしれません 次に サーバ環境プロパティ について掘り下げていきます トランザクションや更新情報が 発生したサーバ環境を 判断ことができるように なりました そして 最近のサブスクリプションの 開始日のプロパティ について話します 顧客のサブスクリプションパターンに応じて 顧客の情報に基づいた 意思決定をするための ツールとして活用できます Xcodeの StoreKit Testingで これらのプロパティを 使用する際の 特別な考慮事項 について説明します これらのプロパティは 古いOSでは センチネル値を返し これがどういうことなのか 簡潔に説明します StoreKitのAPIは柔軟性を 念頭に置いて設計されており オリジナルで搭載されていなくても 昨年のOSデバイスでも これらの新しいプロパティを 利用できることを ここで発表でき 嬉しく思っています これを実現するために 必要なのは Xcode 14を使って Appをビルドするだけです これで以前のOSでこれらのプロパティに アクセスできるようになります これにより これらのプロパティの実装が Appに 組み込まれているためであり 顧客が新しいバージョンに Appをアップデートする際 OSをアップデート する必要なく これらの強化された機能を 利用することができます ただし これらのプロパティを 使用する際には 1つだけ注意点があります これらのプロパティは これらの古いOSで Xcodeの StoreKitテストを使用している場合 センチネル値を返します センチネル値とは これは実際値でないことを知らせる プレースホルダ値 のことであり なぜこのようなことが 起こるのか説明します サンドボックスと 本番環境では App Storeサーバの レスポンスから値を抽出し これらのプロパティを 利用します XcodeでのStoreKit のテストは App Storeのサーバ とは独立して 動作するローカルな テスト環境です つまり これらの プロパティの値を 以前のOSに バックポートすることはできません この制限は テストデバイスを 新しいOSに アップデートすることで 簡単に回避でき ローカル環境での これらの値のテストは すべて準備完了となります それでは これらの 新しいプロパティを どのように使い始めることが できるかを示す いくつかの状況について説明します まずは価格ロケールです StoreKitプロダクトには 購入価格を表示するための 表示価格プロパティが すでにありますが 価格ロケールを使用すると 製品の小数点以下の価格に 由来する数値をフォーマット することができます 年間のサブスクリプションを している場合 これを機会に 顧客に月々いくらかかるか を示します この例では 年間契約では 月々$4.17になる ことがわかります 月額よりも年額の方が お得であることを 伝えたいと思うかと思います これらの情報があれば 顧客が購入の選択肢を 検討する際に 十分な情報を得た上で 判断することができます ここからはEnvironmentプロパティ について話しましょう Environmentプロパティは トランザクション及び 更新情報にて確認できます このプロパティは トランザクションまたは 更新情報が発生した Xcode サンドボックス 本番環境などのサーバ環境をお知らせします Appはトランザクション管理 および分析のために 顧客が購入した後 サーバに トランザクション情報を送信します Appがこれらの トランザクションを生成するとき これらのサーバ環境のいずれかから 生成される可能性があります 皆さんと同様に 私も無関係なテストデータで 分析にノイズを 加えたくありません 環境を知ることで 不要な情報がサーバに 転送しないように フィルタリングすることができます そして最後に 最近のサブスクリプション 開始日について見てみましょう 最近のサブスクリプション開始日は プロダクトのサブスクリプション 情報内で確認でき 最近の継続サブスクリプション期間 を表しています 2つのサブスクリプション間隔は 60日以上の空白期間がない場合 サブスクリプションは継続的 であるとみなされます この期間には顧客がプロダクトを サブスクリプションしていない 期間が含まれるため これを顧客が サブスクリプション日数の指標として 使用しないように 注意してください 最近のサブスクリプション開始日は みなさんと顧客の間の ロイヤルティのパターンを 決定するのに役立ちます 常連顧客には プロダクトとの関係を 維持する方法として 報酬を提供する こともできます あるいは 顧客がサービスから 退会したことに気づいた場合 再びプロダクトを使い始めるための インセンティブを提供することで 退会した顧客を取り戻す機会 として利用することもできます この前これらのプロパティの センチネル値について 詳しく見ていこうと言いました 注意点として センチネル値というのは 存在しない実際値を指す プレースホルダ値の ことです これらのプロパティの センチネル値を簡単に識別できます 価格ロケールを処理する場合 センチネル値は識別子 xx_XXのロケールとなります Emvironmentプロパティには 空の文字列が指定されます そして 最近のサブスクリプション 開始日においては この値は Date.distantPastとなります 幸いなことに これらのセンチネル値の 発生は予測可能です 古いOSでXcodeの StoreKitテストを 使用している場合にのみ発生し テストデバイスを 更新することで 回避することができます ここまでStoreKitの モデルに対する 追加強化機能を ご覧いただきました そのモデルがリリースされた 当時のOSまで 後方互換性があるので Appを アップデートするだけで 顧客がすぐに効果を 実感できるのも 私の好きな部分です 価格の値で演算を行う場合 価格ロケールはApp Storeの ロケールと一致するように 正常にフォーマットするのに 役立ちます トランザクションや サブスクリプション情報については どの環境が 生成されたかわかることができ これらのデータを サーバに保存しておくと 環境に応じて 適宜対応することができます 最近のサブスクリプション開始日は 顧客のロイヤリティを 理解するのに役立つため 長い間ご利用いただいている 顧客に特別な提供をしたり サブスクリプションを解除した顧客に インセンティブを提供したりできるかもしれません 念のためお伝えしますが 環境と 最近のサブスクリプション開始日は Ianが説明する App Store Server APIと App Storeサーバ通知を 通じても確認できます 今はオファーコードの交換や レビューリクエストのために 提供している新しいSwiftUI API について話したいと思います オファーコードは サブスクリプションの価格を割引または 期間限定で 無料提供することで 購読者の獲得 維持 取り戻しに役立ちます App Store Connectで 固有名のカスタムコードを 作成することができます そこでは 交換の上限を 設定したり 有効期限を設定するのか 選択できます SwiftUIはどのように 直接Appからオファーコード 引き換えシートを実装することを 見てみましょう ここで オファーコード 引き換えシートを トリガするボタンがある SwiftUIビューを用意しました オファーコード 引き換えシートには SwiftUIで独自の ビューモディファイアがあります ビューモディファイアは 簡単に使うことができ 連携するBooleanを指定するだけで 処理が開始されます オファーコードシートが 終了すると シートが正常に 提示されたかどうかを表す 結果が表示されます 顧客がAppの オファーコードを利用すると その結果の トランザクションが トランザクションリスナーに 送信されます Appを起動したらすぐに トランザクションリスナーを 設定して Appの実行中に新規および 更新されたトランザクションを 受信してください オファーコードモディファイアは iOS 16から使用可能です 次に リクエストレビューの更新 について話していきたいと思います 顧客からフィードバックを 頂くことは重要です 潜在的新規顧客は Appをダウンロードする際の 決定要因として レビューを使用する場合があります また フィードバックや 提案を提供するために レビューを残したいという方 もいるかもしれません いずれの場合においても 顧客から簡単に 評価をリクエストできる ツールを提供することで 顧客の声を 確認していることを伝え 顧客との関わりを継続できる ようにしたいと考えています コードを見ていきましょう ここにある非常に 単純なビューを使い Request Review APIを 説明します SwiftUIでは requestReviewという 環境値があります この値を使って RequestReviewActionの インスタンスを取得します 評価リクエストをする 準備が整った際に 機能としてインスタンスを 呼び出すだけで レビュープロンプトの表示を リクエストできます 適切な時間を決めて Appに対するレビュー リクエストを行います しかし 注意して頂きたいのは そのプロンプトは 365日間で 最大3回だけしか 顧客に表示することが 出来ないと言うことです 顧客にAppの同じ バージョンのレビューを 複数回リクエストを するべきではありません レビュープロンプトにより顧客を 不快な気持ちにさせることを避けるためです レビューリクエストをする 適切なタイミングとしては EコマースAppでの購入を終了や ゲームでレベルクリアした際など ポジティブなインタラクションがあった後 ではないかと思われます 顧客はデバイス上に リクエストの表示を 無効にできるため ユーザーアクションの 結果としてレビューを 再リクエストできなくなります これらのAPIは SwiftUI Appに対し 本当に便利になっていきます StoreKitメッセージの 新しいAPIについて 紹介していきたいと思います StoreKitメッセージは Appに表示される シートのことで 重要な情報を ユーザーに提示します メッセージはApp Storeで 配信されます メッセージには それぞれ理由があり メッセージメタデータに 含まれています StoreKitメッセージは Appがフォアグラウンドに 動作した際に取得されます 例として メッセージの 理由の一つである 値上げに関する承諾 について見ていきます サブスクリプションの価格を 上げ ユーザーの承諾が 必要な際 App Storeは対象となる購入者に 電子メール プッシュ通知 App内価格同意シートを 通じて通知します この場合 App Storeは 値上げをする前に サブスクリプションの新しい 価格に対する ユーザーからの承諾が 必要となります サブスクリプションにおいて 価格を上げる場合は まだ値上げに対しての 回答をしていない場合は ユーザーがAppを 開いた際に 値上げに対する同意シートが 表示されます デフォルトでは ユーザーがAppを フォアグラウンドにした際に StoreKitメッセージが App上に表示され ユーザーに Appに関連する 何らかのアクションを リクエストする場合があります これについて 見ていきましょう 全体の処理はAppから 始まります Appがフォアグラウンドに 入った際 StoreKitでは 表示が保留中の メッセージがあるかどうか 確認ができます もしある場合 StoreKitは App Storeに確認します App Storeは メッセージに関する情報を StoreKitに返します この時 StoreKitはAppが メッセージを受け取る設定が できているのかを確認します Appでメッセージリスナーを 設定してこれを実行できます これについて 簡潔に説明します Appにメッセージリスナーが 設定されている場合 StoreKitはAppに メッセージ情報を送ります Appがメッセージを 表示するのに 適したタイミングなのか または後で表示をするのか を今が決める機会です メッセージリスナーを 設定しない場合 StoreKitは Appの上に メッセージシートを表示することで メッセージを すぐに表示します コードではどう実現するのか 見ていきます その前に App Storeのメッセージの 表示を制御するために 便利な方法について 説明します Food Truck Appでは さまざまな都市に配達する ドーナッツをカスタマイズ することができます この間にAppに メッセージが届いた場合 突然メッセージシートで 中断されると ユーザーが混乱するので メッセージAPIを実装して 受信メッセージを表示する タイミングを管理し 混乱を防ぎます では コードについて 話していきます ここでは 簡単なドーナッツエディタ のビューを紹介します 前に述べたように Appがフォアグラウンドに 入る度に保留中の メッセージが表示されます メッセージの表示を 延期したい各ビューに メッセージリスナーを 設定したいと思います エディタのビューにいる間にAppに 配信されたすべてのメッセージを 収集するために バインディング配列を追加します メッセージリスナーを 設定していない場合 StoreKitはAppが フォアグラウンドに入ってすぐに メッセージシートを表示するため これはとても重要です ビューが表示されるとすぐに メッセージリスナーを設定します メッセージタイプのスタティック プロパティをイテレートする タスクを設定することで これを実行します このプロパティは asycシーケンスであり メッセージが来た時に 受信できます 私の場合 保留中のメッセージ配列に メッセージを保存します 保留中のメッセージが Appがフォアグラウンドに入る度に 配信されるのであれば Appに同じメッセージが 何度も届く場合があるため この条件は 配列に重複したメッセージを 追加するのを防ぎます ビューが廃棄された場合 親ビューにメッセージを 表示させます これは ドーナッツ エディタへの ナビゲーションリンクを 保持している親ビューです ここに この保留中の メッセージ配列に表示されるべき すべての保留中の メッセージを収集しています ではどのようにしてこれらの 保留中のメッセージを表示するのでしょう ここには環境値 displayStoreKitMessageが あります これによりDisplayMessageActionの インスタンスが取得でき 指定されたメッセージを 表示するために使用できます ビューが表示される際に 保留中のメッセージを 繰り返しアクセスし 表示したい メッセージを提出して displayStoreKitMessageを 呼び出します StoreKitがメッセージシートの 表示を行います 前にも述べたように 同じメッセージが 何度もAppに配信される 場合があります それは メッセージが ユーザーに提示されるまで 既読として マークされないからです StoreKitはそれぞれの 固有のメッセージが 一度だけ表示される ようにします そして それが Messages APIの 簡単な実装です StoreKitメッセージは Appがフォアグラウンドに 入る度に送信されるので 各ビューでメッセージが表示される タイミングを管理したい場合 メッセージリスナーを設定すること を忘れないでください 予期せぬタイミングで メッセージシートを表示しないことで 顧客に素晴らしい最高の体験を していただくことができます あるいは 特定の メッセージタイプに対して ロジックを調整する こともできます 値上げに関する メッセージがある場合 値上げの同意シートが 提示される前に 提供する付加価値について 顧客に説明した方が いいかもしれません ユーザーが購入した後に StoreKitが applicationUsernameを appAccountTokenとして 保持する方法を 確認しましょう サーバにユーザーアカウント システムがある場合 すでにapplicationUsername プロパティを 使用していることが 良い機会となります applicationUsernameは トランザクションを サービスのユーザーアカウントと 関連付けるために作成する文字列です App内課金のオリジナルAPIでは ペイメントキューに ペイメントを追加する際に applicationUsernameの値を 設定します applicationUsernameはどんな 文字列でも可能ですが UUIDの文字列形式を 使用することをお勧めします UUID文字列にした際 StoreKitは その値を保持し キューが更新するトランザクションに 表示されます applicationUsernameに UUID文字列を使用しない場合 StoreKitはそれを 保持しない場合があります ペイメントトランザクションを キューに追加し キューがトランザクションを 更新するまでの間 値が保持する 保証はありません UUIDの文字列形式を 使用する場合 Appのどのユーザー アカウントが トランザクションを開始し 完了したのか識別することができます 最近のStoreKit APIでは この概念を appAccountTokenという 購入オプションとして実装し UUID形式が必要となります 支払い時に applicationUsernameを UUID文字列に 設定すると App Storeサーバはそれを appAccountTokenとして保存します App Store Server APIから返される 署名付き トランザクション情報や V2 App Storeサーバ通知に そのUUIDが表示されます UUIDでは 最新のStoreKit トランザクションAPIにおける appAccountTokenとの 互換性があります コードベースを最新の StoreKit APIに更新した際に applicationUsernameに 使用した UUIDがStoreKit トランザクションで appAccountTokenとして 保持されることを 確認できます 本日私たちは たくさんのことに触れました サーバのアップデートに移る前に 今年度のStoreKitの更新 について見ていきます App Transactionによる App内課金の検証したり オファーコードを 引き換えたり SwiftUIでレビューを依頼したり StoreKitメッセージの 表示を制御したり 新価格のロケール 環境 最近のサブスクリプション開始日の プロパティについて 話しました applicationUsernameに UUIDの文字列形式を使用して Appのアカウント トークンとして 保持することの重要性を 説明しました 他のセッション 「StoreKitテストの最新情報 」 も確認してください StoreKit 2 APIについて 再度確認したい方は 昨年のセッション 「StoreKit 2について」を確認してください それでは Ianへ代わり App Storeサーバの アップデートについて 説明していきます ありがとう Dani こんにちは Ianと申します App Store Serverチームで エンジニアをしています StoreKitによる App内課金についての 最新情報を 確認したところで 話を切り替えて サーバの話をしたいと思います まず最初に この1年間の 最近の動きを振り返り 次にApp Store Server APIと App Storeサーバ通知 バージョン2の 興味深い新しいアップデート について紹介します では始めましょう 昨年は大きな年でした App Store Server API と App Storeサーバ通知 V2 で これらすべての 新しい機能における フルサンドボックスの テストサポートを含む まったく新しい エンドポイントをリリースしました Get Transaction History エンドポイントを使用して ユーザーのApp内課金の 全履歴を取得する方法 または Get All Subscription Statuses エンドポイントを使用して ユーザーのサブスクリプションの 現在の状態を 常に把握する方法について 説明しました これらのエンドポイントは どれも ユーザーのoriginalTransactionIdを キーにしているので このシンプルな値だけを 保存しておくことで この複数のデータに アクセスできます App Storeサーバ通知の バージョン2が サーバでのイベント処理を 簡素化し App Store Server APIを 補完する 方法についても 話していきました V2通知では App Storeのサーバが みなさんのサーバを直接呼び出し App内課金の更新情報を 随時提供します 通知の種類とサブタイプの 合理化により 状態を理解しやすく なりました App内サブスクリプションや 他のイベントに関連する 変更を追跡するために 使用できます これらのデータソースを 使用して そのデータをできるだけ簡単に 解析できるようにしたいと思いました これらの新しいサービスでは App内データを 署名付きJSON形式で提供するため 簡単に解析でき それがApp Storeサーバのもの であると信頼できることで レシートは今では 過去のものとなりました 昨年は App Storeサーバに とって大きな年でした これらの新しい機能を 活用するために サーバコードを更新する 作業を行った場合 それはあなたにとっても 大きな意味になります App Store Server APIと App Storeサーバ通知 V2には 新しい強化と機能が 追加されており この努力の結果は今後も 継続されるのでご安心ください これが今年の 振り返りになりますが 今年のアップデート を聞いて もっと確認したい場合は WWDC21の 「サーバにおける App内課金の管理」 「StoreKit 2について」 「顧客サポートと 返金処理」 というセッションを 確認してください WWDC22のApp Storeサーバ に関連する 全く新しいアップデート について話していきます まず初めに トランザクションと 更新情報フィールドの アップデートについて紹介します App Store Server APIの 新しい強化機能について 話します 最後に App Storeサーバ通知 V2の 興味深い新機能 について話します では 最初の新しいトピック トランザクションと 更新情報の新しいフィールド について話します 先ほど App内課金の トランザクション および更新情報に 新しいフィールドが 追加されることを Daniから聞きました これらのフィールド environmentと recentSubscriptionStartDateは App Store Server APIや V2のApp Storeサーバ通知から 受け取る トランザクションや更新情報の ペイロードに関連します これらの新しいフィールドを含む App Storeサーバから 受け取ることが期待されるデータを 改めて見ていきましょう まず初めに トランザクション情報のペイロードについて これはデコード後に ここで確認することができます 下部にあるのが 新しいフィールド である environmentです これを使えば トランザクションが 本番環境で行われたのか サンドボックス環境で 行われたのか 一目で確認できます 次に 更新情報ペイロードについて こちらもデコード後に 確認できます ご覧いただけているように environmentフィールドは 参照として ここでも確認できます さらに recentSubscriptionStartDateは すべての更新情報ペイロードに 今では表示されるようになりました 60日以下の空白 期間は無視し 直近の一連の更新の中で ユーザーが最初に サブスクリプションした日を 開始日とします recentSubscriptionStartDateは 顧客のロイヤリティを 一目で把握できる 簡単な方法です タイミングや サービスの間隔の長さなど もっと詳細が 確認したい場合 Get Transaction History エンドポイントを呼び出し ユーザーのサブスクリプション 更新購入の 全履歴を調べる ことができます さらに詳細を確認するには App Storeサーバ通知 V2を使用し App Storeサーバは 自動的にユーザーの サブスクリプションに関する 更新情報をみなさんのサーバに送信します これらの通知により 更新日の変更 オファーの利用 課金障害などの イベントの発生時について 最大限に把握する ことができます ご覧のように recentSubscriptionStartDateは 顧客のロイヤリティを 決めるための 一連のオプションを改善しました これらのツールを使って オファーをカスタマイズした 最もロイヤルティがある顧客に報酬を提供します Get Transaction History エンドポイントを強化する 便利で新しい機能 について話します Get Transaction History エンドポイントを使用して App内のユーザーの 購入履歴を全て 取得することができます エンドポイント応答を ページ分割しているため このデータを適度な大きさに 分割して処理できます 各レスポンスは 次のページを取得するために 次のリクエストで提供する リビジョントークンを含みます ページは更新日順で表示され 以降のページには より新しく更新された トランザクションが 含まれることになります これがどのように 機能するか見ていきましょう Get Transaction History エンドポイントを呼び出して originalTransactionIdを提供します App Storeサーバは そのユーザーの署名済み トランザクションを 最大20件まで返します このユーザーに対する 次のページリクエストで 提供する更新された リビジョン値も返します レスポンスのhasMore フィールドがtrueの場合 より多くのデータが利用可能 であることが分かります この場合 もう1ページ分の データが用意されている とします エンドポイントに 再度リクエストをして 初期レスポンスから そのリビジョン値を含めます 更新された リビジョン値を含む 次のページの データを受け取ります hasMoreが falseになったため 最新のトランザクションデータ であることがわかります 今回を除いて レスポンスの最後の トランザクションについて 以前にも見たことがあることに 気づくかと思います 最初のリクエストに 応えていただいた 20件のうちの1件です トランザクションが 変更されたため ソート順の先頭に 戻りました トランザクション データを検証し 変更した点について 確認します この例では revocationDateと revocationReasonフィールドが 入力されており トランザクションが キャンセルされたことがわかります 購入に関連する コンテンツを取り消すことで 対処することができます この最終レスポンスの リビジョン値を ユーザーを識別するために 使用した originalTransactionId と 保存することは 良い考えです 次にこのユーザーの エンドポイント を呼び出すときは そのリビジョンを提供し 前回のリクエスト 以降に更新された 真新しいトランザクションデータのみを 取得することができます これまで見てきたように Get Transaction History エンドポイントでは App内課金データの 包括的なセットを取得するための 簡単な方法を提供します 時々それは包括的すぎる 場合があります 一部のユーザーは 数年前からの 長い購入履歴があります これらのユーザーにとって このエンドポイントは さまざまなタイプの何百件もの 購入を返すことができます ページでも これを 管理するのは大変です そのため 今年はこのエンドポイントに さまざまな新しいソートや フィルタオプションを 追加しているのです 開始データを指定し サーバの処理時間を短縮し 利用可能なすべての ページを取得するために 必要なネットワーク 呼び出しの回数を 減らすことができます 最近更新された 購入したものを 結果の最初のページに 表示したい場合 更新日の降順で ソートすることができます また プロダクトタイプ プロダクトID ファミリー共有の状況など 便利なフィールドでフィルタ することもできます これらの新しいソートおよび フィルタオプションを適用するには Get Transaction History エンドポイントへのリクエストに クエリパラメータとして 追加するだけです どのように機能するか 詳しく見ていきましょう すべての新しいパラメータオプションを ここで見ることができます これらのほとんどは トランザクション情報のペイロードから 直接取得したものであるため ご存知かもしれません 非常に詳細な結果を 取得するために これらのパラメータを合わせ 適合させることができます 例えば あるユーザーが 今年の初めから 非消耗型の購入だけを 取り出したいとします また 購入が取り消されたものも 除外したいとします productTypeを NON_CONSUMABLEに設定し ミリ秒単位で表した 年始をstartDateと指定し カスタムリクエストを 構築します 最後に excludeRevokedを trueに設定します それが私たちの リクエストです ソート順を指定していないため デフォルトで更新日の昇順で ソートされます このように具体的な リクエストであっても 検索する購入品のページが 複数ある可能性があります フォローアップの リクエストでは 前回のレスポンスからのリビジョンに加え まったく同じクエリパラメータを 含める必要があります 柔軟性を高めるために 3つのフィルタフィールドが 複数の値をサポートしており 提供された値の少なくとも 1つに一致する購入品だけを フィルタリングする ことができます これらのフィールドは productType productId およびsubscriptionGroupIdentifierです これらのパラメータにおいて 複数の値を提供するためには それらを複数回 定義することです 次に App Storeサーバ通知の アップデートについて話します App Storeサーバ通知 V2を使用して 次のレベルにあなたのサーバを 引き上げることができます V2通知は 他では取得できない App内課金 イベントに関する 詳細なインサイトを 提供します これらは Appで提供される 自動更新サブスクリプションの ライフサイクルを 追跡するために特に役立ちます これらのインサイトを 活用して 顧客を維持する 離反顧客を取り戻す カスタマーサポートのリクエスト を解決するなどに役立ちます これらのこれだけメリットを どのように見ていくか悩むかと思います どんな新機能でもそうですが サンドボックスのテスト環境は 最適な開始地点です そのため 昨年では サンドボックスでApp Store サーバ通知を受信するために App Store Connectで 別のサーバURLを設定する 機能を追加しました サーバURLの登録後 サーバがApp Storeの サーバからの通知を 受信していることを確認します ユーザーアクションによって 通知をトリガーするためだけに サンドボックスアカウントを 設定することも可能です 例えば そのサンドボックス アカウントを使って 初めてサブスクリプション 購入をするとします SUBSCRIBEDタイプと INITIAL_BUYサブタイプの V2通知を受け取ります 通知が来ない場合は どうすべきでしょうか サーバに問題があったのか 通知設定のための手順に 問題がなかったか 疑問に思うかもしれません このような状況は 始めたばかりの時には 不安になります この経験を簡素化し App Storeサーバ通知が サーバに到達することを 簡単に確認する方法を 提供したいと考えています そのため 今年は新たに Request a Test Notificationという エンドポイントを 導入しました このシンプルなエンドポイントを 呼び出すことで App Store ConnectでAppに 登録されたサーバURLに TESTタイプのV2通知を 送信するように依頼できます 新しいTEST通知タイプを このエンドポイントに 使用します サンドボックスまたは本番環境で エンドポイントを呼び出して 保存したURLをどちらの環境でも テストすることができます この新しいエンドポイントを使用して 新しいサーバのURLや 設定を素早くテストする ことができます この簡素化で どのように 初期設定をするのか確認できます 最初の通知を トリガーするだけなら サンドボックス アカウントを設定したり 購入を実行したりする 必要はありません テストしたい環境で 新しいエンドポイントを 呼び出すだけで リクエストを承認する HTTP 200レスポンスが 返されます このレスポンスには サーバが受け取る テスト通知を識別する 新しいフィールド testNotificationTokenが 含まれます このフィールドについては 後ほど説明します その後まもなく App Store Connectに 保存されたURLに TESTタイプのV2通知が サーバに届きます このエンドポイントの呼び出し 方法について見ていきます POSTリクエストを App Storeサーバの この新しパスに 送信するだけです HTTP 200レスポンスを受け取り リクエストが送信されたこと を確認します レスポンスには 新しいフィールド testNotificationTokenが 含まれます 後ほど使用するため 覚えていてください すぐに署名付き TEST通知を受け取ります その通知がデコードされると このようになります それには 新しい notificationTypeや TESTなどの V2通知の 通常のトップレベル フィールドがすべて含まれます データオブジェクトの コンテンツは 標準の通知よりも 少し短めです これはテストのため トランザクション関連の データはないため トランザクション固有のフィールド 特にsignedTransactionInfoを省略します 新しいRequest a Test Notification エンドポイントを呼び出すときは App Storeサーバ通知が 非同期で送信されることを 留意してください エンドポイントへの 呼び出しに成功すると HTTP 200が返されますが 実際のテスト通知は 後ほど別に届きます このエンドポイントは サーバ設定をテストする ためのものであり テストが失敗した場合どうすれば よいのか気になると思います つまり テスト通知が来ない場合は どうしたらいいのでしょうか テストの性能を さらに強化するために Request a Test Notification エンドポイントと 組み合わせて使用する Get Test Notification Statusを リリースしています この新しいエンドポイントでは 以前リクエストした TEST通知の ステータスを確認できます エンドポイントのレスポンスは App Storeサーバが サーバに到達し TEST通知を正常に 送信できたかどうか をお知らせします 送信に失敗した場合 その原因をお知らせするため サーバ設定のトラブルシューティングを より適切に行うことができます どのように このエンドポイントを 使用するのか見ていきましょう App Storeサーバ上で このパスに GETリクエストを送信します そのパスには testNotificationTokenが含まれており Request a Test Notification エンドポイントから受け取ります これはステータスを 確認したい テスト通知について お知らせします ここからはレスポンス についてです signedPayloadフィールドには App Storeサーバが サーバに送信しようとした TEST通知ペイロードが 含まれています firstSendAttemptResult フィールドは その送信試行の 結果を示します SUCCESSは送信が 成功したことを示しており みなさんのサーバから App Storeサーバが HTTP 200レスポンスを 受信したことを意味します 送信が成功しなかった場合 さまざまな異なるエラー値の いずれかが表示されます これらの値は App Store サーバがテスト通知で みなさんのサーバに到達しようとした際に 経験したエラーを示します この情報を使用して サーバの 問題をトラブルシューティングし 必要に応じて新しいテスト 通知をリクエストし サーバを確実に 稼働させます これらのテスト通知 エンドポイントをまとめて使用し V2 App Storeサーバ通知を 受信するために サーバ設定や 再設定を行う際に 多くの作業を 省くことができます これらのエンドポイントの サポートを活用し サーバを設定し 問題なく 実行できるよう確保します サーバは完璧ではなく 想定外のことも生じます サーバがダウンし App Storeのサーバ通知が 届かない場合 どのように復元しますか これに対する現在の解決策は リトライシステムです App Storeサーバがみなさんの サーバに到着できなかった場合 リトライ処理を初期化します 各試行間の間隔を 長くし 同じ通知を最大 5回まで送信をリトライします これらのリトライは本番環境 でのみ実行されます リトライは予想外のことから 復元することに役立ちますが すべての状況に完璧に対応する というわけではありません 例えば 予想外のことには 大きい規模のものもあります サーバが長時間 ダウンして App Storeサーバから 最後のリトライを見逃した場合 その通知は失われます またはよくあることですが サーバに一瞬の 問題が発生し その間にほんの数回だけ 通知を見逃すことがあります たった一つでも 通知を見逃すと 少なくとも1時間は 顧客記録の一部が 最新ではなくなります そうなった場合でも それがどれかも分かりません サーバの想定外のことが生じると 明らかにストレスとなり その復元は複雑な 作業になります そのため 見逃したApp Storeサーバ通知を できるだけ簡単に 復元できるよう 早めにサーバも修復できるようにしたい と考えています そのため今年は 新しい Get Notification History エンドポイントを導入します このエンドポイントでは Appに生成された V2 App Storeサーバ通知の 履歴を取得できます サーバが通知を正常に 受信したかどうかにかかわらず その通知はこのエンドポイントの レスポンスに表示されます このエンドポイントを 呼び出す際に 取得する通知日の 範囲を指定します WWDCと共に このデータの記録を開始し 上限となる直近6カ月間の ローリングヒストリーを 構築します オプションとしてタイプや サブタイプでリクエストを フィルタしたり originalTransactionIdを指定して 単一ユーザーの通知だけを 取得したりできます 既存のリトライシステムは そのまま利用でき この新しいエンドポイントと 併用することができます このエンドポイントを呼び出す 方法について見ていきましょう App Storeサーバ上で POSTリクエストを この新しいパスに送信します リクエストボディに startDate およびendDateを含みます レスポンスには このウィンドウで最初に 送信を試みた通知 のみが含まれます 最も早く通知可能なのは リクエストの6ヶ月前に 送られたものです オプションとして notificationType notificationSubtypeを 特定できます この場合 履歴はこれらの 値の両方に一致する 通知にのみ フィルタされます いくつかの通知にはサブタイプが ないということに留意してください ユーザーの originalTransactionIdを 指定することで そのユーザーだけの通知履歴を 取得することも可能です 最後に 次のページを 取得するために すべてのフォローアップリクエストの クエリパラメータとして paginationTokenを提供する 必要があります フォローアップリクエストには 同じリクエストボディを使用し このpaginationTokenのみを 変更するように してください ここで レスポンスを みていきましょう notificationHistory配列には 最大20件の通知が含まれ 最も古い通知が 最初に表示されます この配列の各エントリは 通知を表し signedPayloadが含まれるため 通常通りデコードすると トランザクションデータを 見ることができます 含まれているデータは App Storeサーバが オリジナルの通知で送信した ペイロードと同じです このエンドポイント レスポンスに 新しいfirstSendAttemptResult フィールドも入れたことが分かります このフィールドを使用して タイムアウトやその他 エラーのシーケンスを検索し サーバが過去に通知を 逃した理由をより良く 理解することができます レスポンスに 取得すべき ページがもっとある場合は paginationTokenも 含まれます 次のページの通知を取得するために 次のリクエストでこれを 提供する必要があります hasMoreフィールドが trueである限り 取得するページが もっとあることが分かります これが この便利な新しい エンドポイントについて 知っておくべきこと のすべてです これで本日のApp Storeサーバの アップデートを終了します 本日発表したサーバ機能は すべてサンドボックスと 本番環境の両方で 現在利用可能です これらの新機能の 利点を活用し サーバを最適の状態に していただければと思います レガシークライアントを サポートしながら 最新機能を 利用する方法など App内課金で サーバを利用する際の 素晴らしいコンテンツは WWDC22の他のセッション 「App内課金の統合と移行の検討」 をご確認ください WWDC22にご参加いただき ありがとうございました ♪
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。