アプリはアプリ内で返金リクエストシートを表示できます。顧客が送信をタップした後にAppleが何をするかを解説します
Appleのアプリ内返金リクエストは、顧客がアプリを離れることなく、Appleが構築して審査するシート上で返金を申請できる仕組みです。beginRefundRequestが何を返すか、サーバー上で開始するCONSUMPTION_REQUESTと48時間のタイマー、そしてこのボタンを出荷する価値があるかを解説します。

要点
- AppleのbeginRefundRequestは、アプリ内でApple自身の返金シートを表示するStoreKit 2のメソッドです。顧客は自分の購入内容と理由コードの一覧を見て一つを選び、リクエストがAppleに送られます。フォームを作るのも結果を決めるのもあなたではありません。
- この呼び出しはsuccessまたはuserCancelledのステータスを返すか、duplicateRequestまたはfailedをスローします。successのステータスは、App Storeがリクエストを受け取ったことを意味するだけで、承認したことは意味しません。successの時にUIで返金確定を表示しないでください。
- 顧客が送信した後、Appleは承認または却下に最大48時間かけます。消耗型の購入については、まずサーバーにCONSUMPTION_REQUESTを送り、顧客が同意していれば通常どおり12時間以内に利用データで応答できます。
- 結果はApp Store Server Notificationとしてサーバーに届きます。これはすでに受信しているのと同じフィードです。承認はREFUND通知、却下はREFUND_DECLINEDです。アプリ内リクエストは、Appleのreportaproblemページで開始された返金とまったく同じようにこのフィードへ流れ込みます。
- このボタンはiOS 15とiPadOS 15、Mac Catalyst 15、visionOS 1から利用でき、それらのバージョンを対象とするアプリなら今日から表示できます。
- 財務的な論点は、あなたが争える返金は、争えないチャージバックに勝るということです。顧客をAppleのフローの中にとどめれば、応答できるCONSUMPTION_REQUESTが起動し、最終的で手数料もかかる銀行のチャージバックにはなりません。
- Appleの配置ガイダンスは、購入画面ではなくアカウント設定やヘルプメニューから呼び出すことです。そうすれば不満を抱えた顧客がそれを見つけられ、かつ他の全員に返金を宣伝せずに済みます。
Appleは、顧客がアプリを一度も離れることなく返金を申請できるようにしています。StoreKitの呼び出し一つ、beginRefundRequestで、あなたのインターフェースの中にApple自身の返金シートが表示され、顧客が理由を選ぶと、リクエストが審査のためAppleへ送られます。フォームを作ることもなく、お金に触れることもなく、結果を決めることもありません。得られるのは、不満を抱えた顧客がすでにいる場所に返金経路を置く手段であり、彼らを銀行に流出させずに済みます。これがアプリ内返金リクエストであり、このボタンを出荷するかどうかを決める前に理解しておく価値があります。
ここからが売上に関わる部分です。このボタンはそれ自体では何も返金しません。リクエストを開くだけで、Appleは承認または却下に最大48時間かけ、消耗型の購入については、まずサーバーへCONSUMPTION_REQUESTを送ります。ですからこのシートは無償の譲渡ではありません。あなたがすでに影響を及ぼせる返金審査へ導く漏斗であり、争いがあなたに争えないチャージバックへ変わる前に、それをカードネットワークから引き戻すことができます。
アプリ内返金リクエストシートとは実際に何か
beginRefundRequestは、window scene内で特定のトランザクションに対して返金リクエストシートを表示するStoreKit 2のメソッドです。シグネチャは短く、func beginRefundRequest(in scene: UIWindowScene) async throws -> Transaction.RefundRequestStatusです。呼び出すと、システムは顧客の購入内容と、選ばせるための理由コードの一覧を載せたシートを表示します。そのUIを構築し制御するのはAppleです。あなたが渡すのはsceneとトランザクションだけで、それ以外はありません。
配置場所についてのAppleのガイダンスは明確です。この関数はアカウント設定やヘルプメニューから呼び出してください。そうすれば返金を望む顧客が、サポートを探すのと同じ場所でそれを見つけられます。iOS 15とiPadOS 15、Mac Catalyst 15、visionOS 1で出荷されたので、それらのバージョンを対象とするアプリなら今日から表示できます。
シートを開く二つの方法
入口は二つあります。すでに手元にある特定のトランザクションに対してbeginRefundRequest(in:)を呼び出せば、シートをその一つの購入に限定できます。ある製品の購入を顧客に返金してもらいたいときは、製品識別子でシートを開くこともできます。どちらの方法でも、シート、理由の一覧、そして判断はAppleに属します。あなたの仕事はそれを表示し、結果を読むところで終わります。
呼び出しが何を返すか、そして何が起こり得るか
このメソッドはasync throwsなので、ステータスを返すか、エラーをスローするかのいずれかです。どちらも短い一覧で、どちらも扱う価値があります。そうすればシートが閉じた後にUIが本当のことを言えます。
| 結果 | 型 | 意味 |
|---|---|---|
| success | RefundRequestStatus | App Storeが返金リクエストを受け取った。送信済みであり、承認済みではない |
| userCancelled | RefundRequestStatus | 顧客が送信せずにシートを閉じた。何も送られていない |
| duplicateRequest | RefundRequestError | App Storeにはこの購入の返金リクエストがすでにある |
| failed | RefundRequestError | 送信そのものが失敗した。顧客にもう一度試させる |
顧客が送信をタップした後、サーバー上で何が起こるか
シートが閉じることはプロセスの始まりであって終わりではありません。Appleはリクエストを審査し、承認または却下に最大48時間かけます。消耗型のアプリ内課金については、判断する前に、App Storeが利用データを求めるCONSUMPTION_REQUEST通知をサーバーへ送ります。顧客がそのデータの共有に同意していれば、Send Consumption Informationエンドポイントを通じて応答します。同意していなければ、Apple自身の指示は、その通知にはいっさい応答しないことです。
Appleが裁定を下すと、結果はApp Store Server Notificationとしてサーバーに届きます。これはすでに受信しているのと同じフィードで、アプリ内リクエストは、顧客がAppleのreportaproblemページで開始する返金とまったく同じようにそこへ流れ込みます。リクエストがアプリの中で始まったからといって、処理について変わることは何もありません。
| 段階 | 何が発火するか | あなたの動き | タイマー |
|---|---|---|---|
| 顧客がシートを送信 | beginRefundRequestがsuccessを返す | 記録し、返金済みではなく保留中を表示する | 即時 |
| 消耗型のみ、Appleが先に問い合わせ | CONSUMPTION_REQUEST通知 | 顧客が同意していれば消費データを送り、そうでなければ沈黙を保つ | 12時間以内に応答 |
| Appleが承認 | REFUND通知 | そのトランザクションの権利を取り消す | 判断に最大48時間 |
| Appleが却下 | REFUND_DECLINED通知 | 売上を保持し、何も変えない | 判断に最大48時間 |

このボタンにかかるコストと、節約できるもの
あなたが争える返金は、争えないチャージバックに勝る
アプリの中で返金経路を見つけられない顧客は、あきらめません。銀行へ行きます。カードのチャージバックは銀行との間で最終的であり、争議手数料がかかり、判断をあなたとAppleの双方の手から奪います。アプリ内返金リクエストは、その同じ顧客をAppleのシステムの中にとどめます。そこでは消耗型の購入が、応答できるCONSUMPTION_REQUESTと、影響を及ぼせる判断を起動します。争えないチャージバックを、争えるApple審査と引き換えにすること、それがこのボタンの財務的な論点のすべてです。
あなたは返金の摩擦を下げている
正直な反面は、目に見える一タップの返金経路は、奥に埋もれたサポートメールよりも多くの返金リクエストを生むということです。その一部は本来決して起きなかったはずのものです。それは実在するコストであり、だからこそAppleは、入口を購入画面ではなくアカウント設定やヘルプメニューに置くよう指示します。すでに不満な顧客に見つけてほしいのであって、単に好奇心のある顧客に見つけてほしいわけではありません。
最初から最後まで動き続けるコストは、返金済みのアカウントにサービスを提供し続けること
判断がどちらに転んでも、あなたが結果に基づいて動くまで、提供側のメーターは回り続けます。返金済みの権利が生きている一時間ごとに、その裏にある本当のコストを払い続けます。計算資源、モデルのAPI呼び出し、ストレージ、そしてその顧客の利用に紐づくクリエイターやパートナーへの支払いです。アプリ内リクエストはそれを変えません。REFUND通知で速やかに取り消すことが変えます。このボタンの安さは、最終的に生み出される通知をどう処理するか次第です。
アプリ内返金リクエストを出荷すべきか
販売のある場所ではなく、サポートのある場所に置く
Appleの配置ガイダンスに従ってください。アカウント設定とヘルプメニューが正しい置き場所です。ペイウォールの隣の返金リンクは、お金が戻ってくると人々に期待させるよう仕向け、提供する必要のなかった好奇心による返金を招きます。
信頼する前に、サンドボックスで全体のフローをテストする
サンドボックスとXcodeのStoreKitテストで、リクエストを保留中から承認済みまたは却下済みへ動かしながら、経路全体をシミュレートできます。承認はサーバーにREFUND通知を届け、却下はREFUND_DECLINEDを届けるので、実際の顧客が送信をタップする前に、ハンドラーが正しく反応することを証明できます。
すべての結果を扱い、決して過大に主張しない
successでは保留中を表示し、failedでは再試行を提示し、userCancelledでは何も変わっていないと伝え、duplicateRequestは、顧客の以前のリクエストがまだ有効だという静かな注記として扱ってください。害になる唯一の誤りは、手元にあるのが送信済みのリクエストだけなのに、返金が完了したと顧客に伝えることです。
RefundHaltはその後をどう処理するか
アプリ内シートはAppleのものです。その後に来るものはあなたのものであり、そこがRefundHaltの担う部分です。顧客がアプリの中から返金を送信すると、RefundHaltは消耗型の購入についてCONSUMPTION_REQUESTを捕捉し、Appleの判断を助ける利用の証拠とともに12時間の枠の中でそれに応答します。Appleが裁定すると、REFUNDでは取り消し、REFUND_DECLINEDではアクセスをそのまま保持し、それぞれを正確にそのトランザクションに紐づけます。あなたは、審査も証拠も取り消しも手作業の慌てふためきに委ねることなく、より親切なアプリ内返金経路を提供できます。
よくある質問
- beginRefundRequestは何をするのですか?
- 特定のトランザクションについて、アプリ内にAppleの返金リクエストシートを表示します。顧客は自分の購入内容と理由コードの一覧を見て一つを選び、リクエストがAppleへ送られます。このメソッドはsuccessまたはuserCancelledのステータスを返すか、duplicateRequestまたはfailedをスローします。購入そのものを返金するわけではありません。Appleがリクエストを審査し、判断に最大48時間かけるからです。
- アプリ内返金リクエストはすぐにお金を返金しますか?
- いいえ。successの結果は、App Storeがリクエストを受け取ったことを意味し、承認したことは意味しません。Appleは承認または却下に最大48時間かけ、消耗型については、まずCONSUMPTION_REQUEST通知でサーバーに利用データを求めます。successでは顧客に保留中の状態を表示し、返金確定を決して表示しないでください。
- どのiOSバージョンがアプリ内返金リクエストに対応していますか?
- iOS 15とiPadOS 15、Mac Catalyst 15、visionOS 1です。StoreKit 2のメソッドbeginRefundRequest(in:)はこれらのバージョンから利用でき、iOS 15以降を対象とするアプリなら、アプリの中からAppleの返金シートを表示できます。
- アプリ内返金ボタンはどこに置くべきですか?
- Appleのガイダンスは、購入画面やペイウォール画面ではなく、アカウント設定やヘルプメニューから呼び出すことです。そうすれば返金経路は、不満な顧客がサポートを探す場所に置かれ、申請するつもりのなかった顧客に返金を宣伝せずに済みます。
- アプリ内返金は、顧客が銀行に連絡するより良いですか?
- あなたの売上にとっては、たいてい良いです。銀行のチャージバックは最終的で手数料がかかり、Appleとあなたの双方を判断から外します。アプリ内返金リクエストは顧客をAppleのフローの中にとどめ、そこでは消耗型の購入が、応答できるCONSUMPTION_REQUESTと、影響を及ぼせる審査を起動します。争える返金は、争えないチャージバックに勝ります。
出典と参考資料
- Apple Developer: beginRefundRequest(in:)
- Apple Developer: Transaction.RefundRequestStatus
- Apple Developer: Transaction.RefundRequestError
- Apple Developer: App Store Server Notifications V2 notificationType
- Apple Developer: Send Consumption Information
- Apple Developer: Support customers and handle refunds (WWDC21)
RefundHalt
App Store と Google Play の返金を自動処理
続きを読む
Google Play の購入が返金またはチャージバックされたとき、それを知る手段が Voided Purchases API です
Google Play は購入が返金またはチャージバックされると、静かにその購入を無効化します。Voided Purchases API はそうした注文の一覧であり、これを使ってアクセスを取り消せます。ここではすべてのフィールド、30日間のウィンドウ、注文を隠してしまう revoke オプション、そしてそのコストを解説します。
Apple が判断を下した後に 3 種類の App Store 返金通知が届き、REFUND_REVERSED は売上を返してくれる
Apple は App Store Server Notifications V2 を通じて 4 種類の返金メッセージを送りますが、ほとんどのアプリは 2 種類しか処理していません。REFUND は権利の取り消しを指示し、REFUND_DECLINED は売上をそのまま保持することを意味し、REFUND_REVERSED は売上を返したうえで、あなたが取り上げたものを復元するよう求めます。それぞれに何が必要かを説明します。