本文へスキップ
App Store & Play Store Development

開発者向け:Apple の CONSUMPTION_REQUEST 通知への対応方法

サブスクリプションアプリの Apple 返金リクエストに対し、開発者が CONSUMPTION_REQUEST 通知を処理し、正確な顧客の消費データを提供する方法を解説します。

5 min read
開発者向け:Apple の CONSUMPTION_REQUEST 通知への対応方法

CONSUMPTION_REQUEST とは何かを理解するのに必要なのは、せいぜい一段落分の説明です。しかし、それを確実に処理する仕組みを構築するにはそれ以上の手間がかかり、つまずきやすいポイントは意外なところにあります。

署名検証がその一つです。同意もまた別の一つで、通知が届く前に取得済みでなければなりません。さらに、再送スケジュールと回答期限の関係は、初めて詳しく確認したほとんどのチームを驚かせます。

この記事では、リクエストがエンドポイントに届いた瞬間から、処理を締めくくるエンタイトルメントの更新まで、ハンドラーの流れを順に解説します。

重要なポイント

• CONSUMPTION_REQUEST は、返金審査の過程で情報提供を求めるものです。決定を下すのはあくまで Apple です。

• 署名付きペイロードを検証してから処理してください。未検証の通知を信用してはいけません。

• 同意は、アプリ内であらかじめ取得しておく必要があります。リクエストが届いてから取得することはできません。

• Apple は通知から 12 時間以内の回答を求めています。

• Apple は配信に失敗した通知を固定スケジュールで再送しますが、2 回目の再送は回答期限が過ぎた後に届きます。

• 結果を追跡し、その後にエンタイトルメントを更新してください。回答して終わりではありません。

Apple の CONSUMPTION_REQUEST 通知とは?

Apple の CONSUMPTION_REQUEST 通知とは、顧客が返金をリクエストし、その購入に関する消費情報の送信を Apple が求めていることをサーバーに伝える App Store Server Notification です。設定済みの通知 URL に届き、該当するトランザクション情報を含んでおり、回答できる時間は限られています。

これは返金でも決定でもありません。Apple は審査の途中で、判断材料を集めている段階です。あなたの役割は購入について何が起きたかを正確に伝えることであり、決定を下すのは Apple の役割です。

Apple が CONSUMPTION_REQUEST を送る理由

Apple にはアプリの内部が見えないからです。トランザクション、アカウント、購入履歴は把握していますが、コンテンツが配信されたか、正常に動作したか、顧客がどの程度利用したかは分かりません。

消費情報はそのギャップを埋めるものです。Apple が考慮する複数の要素の一つであって決定打ではなく、消費率が高いからといって返金が拒否されるわけでもありません。主張を戦わせる場ではなく、判断材料を提供する場だと考えてください。

CONSUMPTION_REQUEST を受け取ったら何をすべきか?

通知を検証し、トランザクションと顧客を特定し、同意を確認し、正確な消費データを組み立て、Apple の期限内に送信し、結果を記録します。

実際の 10 ステップ:

1. 設定済みのサーバーエンドポイントで通知を受信し、直ちに永続化します。

2. いずれかのフィールドを信頼する前に、署名付きペイロードを検証します。

3. 通知タイプを読み取り、適切に振り分けます。消費リクエストは返金結果ではありません。

4. デコードしたペイロードから関連するトランザクションを特定します。

5. そのトランザクションを自社システム内の顧客アカウントに紐付けます。

6. その顧客の同意状況が回答を許可しているかを確認します。

7. 推定値ではなく、自社の記録から配信データと利用データを収集します。

8. 回答を準備し、フィールドのバリデーションルールに照らして確認します。

9. Apple の consumption エンドポイントに送信し、結果を取得します。

10. その後の返金結果を追跡し、エンタイトルメントと記録を更新します。

CONSUMPTION_REQUEST はどのように検証すべきか?

内容を信頼する前に署名を検証してください。通知は署名付き JWS ペイロードとして届き、その仕様は Apple の App Store Server Notifications ドキュメントに記載されています。ハンドラーでは Apple の証明書チェーンに照らして検証し、bundle ID が自分のアプリと一致することを確認する必要があります。

理由は単純です。通知 URL は公開エンドポイントです。届いたものを何でも解析して処理する実装は、URL を見つけた誰もが操作できる実装ということになります。

署名と同じくらい重要なハンドラーの詳細が 3 つあります。

正しいステータスコードを返す。 Apple は HTTP 200 から 206 を成功として扱います。40x や 50x を返すと App Store は再送します。成功を返すのは通知を保存した時点であり、処理を完了した時点ではありません。この 2 つは別のタイミングであり、結び付けてしまうと、下流の処理が遅いだけで不要な再送を招くことになります。

重複を処理する。 再送があるため、同じ通知が複数回届くことがあります。各通知には重複排除に使える notification UUID が含まれています。重複にはエラーではなく受領応答を返してください。失敗応答は再送サイクルを再開させるだけです。

Sandbox の挙動は異なることを忘れない。 再送は本番環境で適用されます。Sandbox では App Store は配信を 1 回しか試みないため、テストで問題なさそうに見えるハンドラーが本番ではイベントを取りこぼしていることもあり、その逆もあり得ます。

回答前に確認すべきことは?

4 つあり、この順序で確認します。

まず同意です。これがすべてを止め得る要素だからです。Apple は顧客データを共有する前に有効な顧客の同意を必須としており、その取得は Apple ではなくあなたの責任です。通知自体に同意フラグは含まれていません。また Apple は、App Tracking Transparency のプロンプトはここでいう同意の仕組みではないと明言しています。同意がなければ、回答しないというのがガイダンスです。

次にトランザクションの特定です。どの購入で、どのアカウントが背後にいるのかを把握する必要があります。この紐付けこそが appAccountToken と Apple 返金対策のテーマです。トランザクションからアカウントへの安定したリンクがなければ、期限に追われながら推測することになります。

3 つ目は商品タイプです。利用できる選択肢に影響するためです。最後に、実際に使えるデータを保持しているかどうかです。コンテンツが配信されたかどうかをシステムが答えられないなら、回答を組み立て始める前にそれを把握しておく価値があります。

Apple に送信できる消費情報は?

Apple の現行の Send Consumption Information ドキュメントでは 5 つのフィールドが定義されています。3 つが必須、2 つが任意です。

フィールド

必須

平たく言うと

customerConsented

はい

顧客はこれに同意していますか?true でなければリクエストは拒否されます。

deliveryStatus

はい

アプリは実際に正常な購入内容を配信しましたか?していない場合、その理由は?

sampleContentProvided

はい

顧客は購入前に試すことができましたか?

consumptionPercentage

いいえ

どの程度利用しましたか?単位はミリ単位で、半分は 50 ではなく 50000 です。

refundPreference

いいえ

あなたの希望:全額返金、拒否、または按分。

つまずきやすいルールが 2 つあります。配信ステータスが「配信済み」以外の場合、消費率はゼロでなければなりません。また、返金の希望はあくまで希望であって指示ではありません。Apple は異なる判断を下すことができ、実際にそうします。

どちらのエンドポイントを使っているかを確認する価値があります。Apple は Apple の ConsumptionRequestV1 ドキュメントも公開しており、こちらは 12 フィールドのボディを持つ旧バージョンで、多くのサードパーティ記事が今も説明しているものです。Apple の注記では、標準の In-App Purchase は現行エンドポイントへ誘導され、V1 は Advanced Commerce API の購入に範囲が限定されています。統合がこの変更より前に構築されたものなら、まずここを確認してください。

CONSUMPTION_REQUEST への回答期限は?

Apple の現行ドキュメントでは、通知から 12 時間以内の回答が求められています。

ここが注目すべき点です。Apple は配信に失敗した通知を、前回の試行から 1、12、24、48、72 時間後の計 5 回再送します。これを 12 時間の期限と照らし合わせると、計算は厳しいものになります。エンドポイントが初回配信を取りこぼしても、1 時間後に最初の再送が届くので問題ありません。しかしそれも取りこぼすと、次の試行は約 13 時間後、つまり期限がすでに過ぎた後に届きます。

したがって、ここでのエンドポイントの信頼性は一般的な運用上の心がけの話ではありません。消費リクエストに限って言えば、およそ 1 時間のダウンタイムなら回復できますが、半日では回復できません。

Apple は、期限を逃すと返金が自動的に承認されるとは述べておらず、そう主張するのは誤りです。意味するところは単純で、あなたが提供できたはずの情報なしに Apple が判断を下すということです。

回答後には何が起きるか?

Apple はあなたの情報を審査に取り込み、他のすべての要素と合わせて検討し、決定を下します。結果は別の通知として届きます。承認、拒否、あるいは Apple が一度承認した返金を後に取り消した場合の取り消しです。

ここでは 3 つの別々のことが起きており、区別しておくと役立ちます。あなたの回答は情報です。Apple の決定は決定です。あなたのシステム更新は状態の変更です。Apple に属するのは真ん中の 1 つだけであり、3 つ目はあなたが構築しない限り起きません。

回答後の Apple 返金への対応方法

結果が届いたら、作業は再びあなたの側に戻ります。

結果をトランザクションと顧客に対して記録します。サブスクリプションのステータスを更新します。返金された期間は通常、サブスクリプションを継続させるのではなく終了させるためです。返金が承認された場合はエンタイトルメントを取り消し、取り消しの場合は復元し、トランザクションの一部だけが取り消される按分のケースにも対応します。

その後、金額を正しいレポート期間に照合し、返金をクエリ可能な履歴として保持します。この履歴があるからこそ、後になって特定の商品や価格帯が不釣り合いに多くの返金を生んでいないかが分かりますし、顧客からアクセス権に何が起きたのかと問い合わせがあったときにサポートが必要とするのもこの履歴です。

CONSUMPTION_REQUEST 処理でよくあるミスは?

繰り返し見られるものは次のとおりです。

• 通知を返金とみなし、直ちにアクセスを取り消す。まだ何も決定されていません。

• テストでペイロードが問題なく見えるからと署名検証を省略する。

• 回答期限が迫った瞬間に、同意フローが存在しないことに気づく。

• 実際の値ではなく推定の消費率を送る。

• リクエストを送信したきり、成功したかどうかを確認しない。失敗した送信は、後から見ると成功したものと見分けがつきません。

• キャンセルと返金を混同する。これらは異なるイベントで、アクセス権への影響も異なります。

• 承認と拒否の結果は処理するが、取り消しのケースを忘れる。これは有料顧客を締め出してしまいます。

• 12 時間のタイマーが動く中で、誰かが通知に手動で気づくことに頼る。

CONSUMPTION_REQUEST 処理は自動化できるか?

できます。そして、ほぼすべてのステップが決定論的であるため、ほぼ全部を自動化すべきです。

自動化の対象は、通知の監視と検証、トランザクションの検索、同意の確認、消費データの準備、送信、応答のログ記録、結果の追跡、社内アラート、レポートです。いずれもその場での判断を必要としません。

人が担うのは上流の部分です。アプリ内の同意フローの設計と、返金希望のポリシーを決めることです。そして、一部のツールが何を匂わせようと、自動化は Apple の決定に影響を与えません。

RefundSensor が Apple 返金ワークフローの処理をどう支援するか

App Store の返金管理というカテゴリにおいて、RefundSensor は開発者側の領域をカバーします。Apple 返金ワークフローの監視、消費リクエストに対するサポートされた回答経路の処理、返金イベントと結果の追跡、そして反復作業を人の手から切り離すことです。

実際には、誰かが午前 3 時にダッシュボードを見張ることなく期限内に回答が送信され、ボリュームが増えても返金記録は正確に保たれます。返金を防ぐものではなく、Apple の決定に影響を与えることもできません。手動の監視と、抜け落ちるステップをなくすものです。

これらのルールが記載されている場所

Send Consumption Information — 現行のエンドポイント。同意要件、12 時間の期限、5 つのリクエストフィールド。標準の In-App Purchase はこれに基づいて構築してください。

Send Consumption Information V1 — 12 フィールドのボディを持つ旧エンドポイント。統合がどのバージョンを呼び出しているかの特定や、Advanced Commerce API の購入に役立ちます。

App Store Server Notifications — 通知の配信、署名付きペイロードの形式、期待される応答コード、再送スケジュール。

まだ手作業で処理しているなら

12 時間の期限、それを超え得る再送スケジュール、夜間に届く通知。これらは手動監視には向いていません。 RefundSensorは、通知の検証、期限内の回答の準備と送信、エンタイトルメント記録までの結果追跡といった、これらのワークフローの開発者側を担います。

よくある質問

顧客が返金をリクエストし、その購入に関する消費情報の送信を Apple が求めていることをサーバーに伝える App Store Server Notification です。返金通知でも決定でもありません。Apple は別途判断を下し、あなたの回答は複数の要素の一つとして扱われます。

Apple にはアプリ内で何が起きたかが見えないからです。トランザクションとアカウント履歴は把握していますが、コンテンツが配信されたか、正常に動作したか、顧客がどの程度利用したかは分かりません。その情報はあなたのシステムにあるため、Apple は審査中にそれを求めます。

署名付き通知を検証し、トランザクションとその背後の顧客を特定し、同意があることを確認し、自社の記録から実際の配信データと利用データを収集した上で、期限内に Apple の consumption エンドポイントに送信します。呼び出しが成功したと決めつけず、応答結果を記録してください。

現行エンドポイントでは 5 つのフィールドです。必須は 3 つで、顧客の同意、配信ステータス、サンプルコンテンツを提供したかどうか。任意は 2 つで、消費率と返金の希望です。旧 V1 エンドポイントは 12 フィールドを求めていたため、古い解説ではより長いリストが記載されています。

Apple の現行ドキュメントでは、この通知はすべての商品タイプの返金リクエストに関連して説明されており、旧ドキュメントが示していたよりも範囲が広くなっています。Apple はすべてのケースで送信を保証しているわけではないため、必ず届く前提のロジックではなく、リクエストが届いたときに回答するハンドラーを構築してください。

Apple は通知から 12 時間以内の回答を求めています。注意すべき点として、配信失敗時の Apple の再送スケジュールは 1、12、24、48、72 時間後であるため、最初の再送を過ぎてもダウンしているエンドポイントは、期限が過ぎた後にしか通知を受け取れない可能性があります。

Apple はそれを他の要素と合わせて検討し、決定を下します。結果は、返金が承認、拒否、または後に取り消されたことを示す別の通知として届きます。その後は、新しいトランザクションの状態に合わせてエンタイトルメント、サブスクリプションのステータス、売上記録を更新するのがあなたの仕事です。

できます。検証、トランザクションの検索、同意の確認、データの準備、送信、ログ記録、結果の追跡はすべて決定論的です。人が担うのは、同意フローの設計と返金希望ポリシーの設定です。自動化は Apple の返金決定に影響を与えません。

#Apple refunds#Subscription apps#App Store#iOS development#CONSUMPTION_REQUEST#Apple StoreKit
Refund SensorRefund Sensor TeamRefund defense for App Store and Google Play developers