保留中の購入は売上のように見えても、まだお金は届いておらず、先に付与すると製品をタダで渡すことになる
App Store も Google Play も保留中の購入という状態を持っています。ストアが受け付けたものの、まだ課金していない注文のことです。支払いが確定する前にロック解除すると、成立しなかった注文はそのまますべてコストになります。本記事では、保留中の購入が各ストアでどのように動くのか、誤って付与すると何を失うのか、そして損失を出さずに扱う方法を説明します。

要点
- 保留中の購入は、ストアが受け付けたものの、まだ課金していない実在の注文です。あなたのコードは新しい購入を見ますが、お金はまだ届いておらず、永遠に届かないこともあります。
- Google Play では状態が PURCHASED のとき、Apple ではトランザクションが完了したときにのみ権利を付与してください。PENDING 状態や Apple の保留中の結果でロック解除しては絶対にいけません。
- Google Play では、店頭での現金払い、銀行振込、一部のキャリア決済は帯域外で決済されるため、顧客が実際に支払うまで、購入は PURCHASED ではなく PENDING として返ってきます。
- Apple では、保留中の購入はたいてい Ask to Buy で、ファミリーの管理者が承認する必要があります。承認には数時間から数日かかることがあり、完了したトランザクションは後から Transaction.updates を通じて届きます。
- その後キャンセルされる保留中の注文でロック解除すると、確定しなかった課金のために、計算リソース、API 呼び出し、ストレージ、あるいは消耗型アイテムの実際の付与を費やしたことになります。返金と違い、取り戻すお金はありません。そもそも一度も回収されていないからです。
- 保留中の注文が成立しなかったとき、ストアはそれを知らせてくれます。Google は ONE_TIME_PRODUCT_CANCELED、タイプ 2、または SUBSCRIPTION_PENDING_PURCHASE_CANCELED、タイプ 20 を送ります。Apple は単に完了したトランザクションを届けません。
- 保留中の注文は、アプリが閉じている間に本物の売上に変わることがあるため、復帰時に再確認してください。Google Play では onResume() で queryPurchasesAsync() を呼び出し、Apple では Transaction.updates を監視し続けます。
誰かがあなたのアプリで購入をタップします。ログには新しい注文が表示され、課金リスナーが発火し、あなたは商品を引き渡します。ほとんどの購入ではそれで正解です。しかし保留中の購入では間違いです。注文は存在しても、お金は存在しないからです。顧客は後で決済される支払い方法を選び、ストアはまだ入金を待っており、あなたは確定しないかもしれない課金のために有料機能を引き渡してしまったのです。これは返金の物静かな親戚です。ここでは何も取り消されません。そもそも何も回収されていないからです。あなたはただ製品をタダで渡しただけです。
保留中の購入は、まだ支払われていない状態にある実在の注文で、App Store も Google Play もこれを持っています。どちらのストアも、待つようにはっきりと伝えています。厄介なのは、保留中の注文がコード上では完了した注文とほとんど見分けがつかないことです。そのため、すべての新しい購入を売上として扱う実装は、ストアがまだ回収しようとしている注文で商品を出荷してしまいます。正しく扱えば何も失いません。誤って扱えば、成立しなかった遅い支払いはすべて、あなたの負担で引き渡された純粋なコストになります。
保留中の購入とは実際には何か
保留中の購入は、ストアが記録したものの、まだ課金していない注文です。買い手はフローを始め、ストアはそれを受け付け、決済はあなたのアプリからは見えないどこかで進行しています。Google Play はこれを PENDING 状態と呼びます。Apple は保留中、または延期されたトランザクションと呼びます。名前は違っても事実は同じです。ストアは入金を待つ間、注文を開いたまま保持しており、その注文をお金として扱わないようにと伝えているのです。
Google Play:支払いは別の場所で進んでいる
一部の支払い方法は帯域外で決済されます。実店舗での現金、銀行振込、一部のキャリア決済はいずれも、タップと課金の間に追加の手順を挟みます。顧客がそのひとつを選ぶと、Google は購入を PURCHASED ではなく PENDING 状態で返します。現金払いの場合、顧客は通知とメールでコードを受け取り、それを対応店舗に持って行き、レジで支払います。それが起きるまで、Google は何も回収しておらず、あなたも同じです。Google のルールは一行です。getPurchaseState() を使い、状態が PURCHASED のときにのみ権利を付与すること。また、PENDING の間は購入を確認応答しないようにとも伝えています。確認応答は支払い済みの注文に属するものであり、約束された注文のものではないからです。
Apple:この購入は誰かのタップを待っている
Apple の保留中の状態は、トランザクションが完了する前に外部のアクションを必要とすることを意味します。最も一般的なのは Ask to Buy で、子どもが購入を始め、ファミリーの管理者が承認しなければなりません。StoreKit 2 では購入呼び出しが Product.PurchaseResult.pending を返します。より古い StoreKit では、トランザクションは deferred として報告されます。いずれにせよ、Apple は誰にも課金しておらず、完了したトランザクションは、もし届くのであれば、Transaction.updates を通じて非同期に届きます。顧客には待機状態を表示し、完了したトランザクションが届くまで何もロック解除しないでください。
保留中の購入を付与するとなぜ実際にお金を失うのか
ここでの損失は、計上したお金が引き戻される返金のたぐいではありません。ある一点でそれより悪いのです。引き戻すお金がありません。そもそも一度も回収されていないからです。
あなたは引き渡すが、ストアは決して回収しない
後でキャンセルされる保留中の注文でロック解除すると、あなたはすでにそれを提供するために費やしています。機能を動かした計算リソース、あなたが料金を払った第三者の API 呼び出し、割り当てたストレージ、そして消耗型アイテムであれば、売ったものの実際の付与です。それらすべてが、収益を生まなかった注文のために外へ出て行きます。返金は少なくとも、実際に発生した課金から始まります。誤って付与された保留中の購入には、そもそも課金が一度もなかったので、出て行くお金としてすら表示されません。それは何も表示されません。だからこそ見落としやすく、繰り返しやすいのです。
キャンセルのシグナルと、その意味
保留中の注文が消えるとき、ストアはたしかにそれを知らせます。Google Play では、成立しなかった一回限りの商品は ONE_TIME_PRODUCT_CANCELED 通知、タイプ 2 を送り、保留中だったサブスクリプションは SUBSCRIPTION_PENDING_PURCHASE_CANCELED、タイプ 20 を送ります。同じ注文が逆に成立したときは、ONE_TIME_PRODUCT_PURCHASED、タイプ 1、または SUBSCRIPTION_PURCHASED、タイプ 4 を受け取ります。Apple では捕まえるべきキャンセルイベントはありません。拒否された延期トランザクションは、単に完了したトランザクションにならないからです。早くロック解除していたなら、その沈黙が請求書です。
| 問い | Google Play | Apple |
|---|---|---|
| 何が引き起こすか | 現金、銀行振込、一部のキャリア決済 | Ask to Buy の承認、またはその他の必要なアクション |
| 見える状態 | PurchaseState PENDING | 保留中の結果、または延期されたトランザクション |
| 権限を付与するとき | 状態が PURCHASED | トランザクションが完了 |
| 成立した場合 | ONE_TIME_PRODUCT_PURCHASED (1)、SUBSCRIPTION_PURCHASED (4) | Transaction.updates 経由の完了したトランザクション |
| 成立しなかった場合 | ONE_TIME_PRODUCT_CANCELED (2)、SUBSCRIPTION_PENDING_PURCHASE_CANCELED (20) | 完了したトランザクションは一切届かない |
| お金は回収されたか | いいえ、PURCHASED になるまでは | いいえ、トランザクションが完了するまでは |
その待ち時間と、誰が誰を待っているのか
保留中の購入は、あなたが競走している時計ではありません。あなたの側から見れば、まだ動き始めていない時計です。
Google Play が顧客に与えるのは数分ではなく数日
現金または銀行振込の支払いは、あなたのではなく顧客のスケジュールで決済されます。注文は、顧客が支払うか、期限が切れて Google がキャンセルするまで PENDING にとどまります。あなた自身の三日間の確認応答期限、つまり確認応答しなかった購入を自動的に返金するあの期限は、購入が PENDING から PURCHASED に移行するまで始まりすらしません。ですから保留中の注文を提供する必要は少しもありません。あるのはただ、状態が変わるのを待つ規律だけです。
Apple の承認はファミリー管理者の電話の中にある
Ask to Buy のリクエストは、管理者のデバイスにプロンプトとして届き、彼らは手が空いたときに承認または拒否します。それは数分後、数時間後、あるいは一日後かもしれず、あなたのアプリはそれを急かせません。唯一正しい振る舞いは、待機状態を反映し、承認が来たなら、そのときに StoreKit が完了したトランザクションを渡してくれるのに任せることです。

損失を出さずに保留中の購入を扱う方法
作業全体は四つの習慣に行き着きます。どれも難しくはなく、そのどれか一つでも飛ばすと、そこがお金の出て行く場所になります。
支払い済みの状態で付与し、保留中の状態では決して付与しない
Google Play では getPurchaseState() を確認し、PURCHASED のときにのみ付与し、PENDING の間は購入を確認応答しないでください。Apple では完了したトランザクションでのみロック解除し、保留中の結果では決して行わないでください。この一つのルールが漏れ全体を塞ぎます。あとはすべて、支払い済みの状態が届いたときにきちんと気づけるようにするための話です。
アプリが戻ってきたら再確認する
保留中から支払い済みへの移行は、あなたのアプリが動いていないときに起きることが多いです。Google Play では、onResume() ハンドラで queryPurchasesAsync() を呼び出して、バックグラウンドで PURCHASED になった注文を拾い、Real-time Developer Notifications リスナーをサーバー側の信頼できる情報源として保ってください。Apple では、承認されたトランザクションが元の購入呼び出しが返ってからずっと後に届くことがあるため、アプリの全生涯にわたって Transaction.updates を監視してください。
保留中のサポートを有効にし、両方の結末をテストする
Google は BillingClient を構築するときに enablePendingPurchases() を呼び出すことを要求しており、一回限りの商品で保留中のトランザクションをサポートすることは任意ではなく必須です。出荷する前にテストしてください。ライセンステスターには、遅延型の支払いのための二つの追加テスト手段が与えられ、そこでは支払いが数分後に自動的に完了するか自動的にキャンセルされるので、支払いの経路と成立しない経路の両方を端から端まで見届けられます。
注文がまだ終わっていないことを顧客に伝える
保留中の買い手は、購入の途中にいる実在の顧客であって、失敗ではありません。注文が彼らの支払いか承認を待っていることを示し、それを終えるために戻ってこられる明確な道を与えてください。沈黙した保留中の状態は、きちんとラベル付けすれば取り戻せる売上を失います。こうした買い手のほとんどはまだそのものを欲しがっており、あと一手順を残しているだけだからです。
RefundHalt が返金とチャージバックのためにすでに読み取っている、その同じ Real-time Developer Notifications と App Store Server Notifications のフィードは、これらのシグナルも運んでいます。保留中の注文がついに確定したと伝える購入済みの通知と、確定しなかったと伝えるキャンセルの通知は、あなたのダッシュボードで他の収益イベントの隣に届きます。ですから、成立しなかった保留中の注文は、うっかり代金を払わされたものではなく、目で見えるものになります。
手短に言うと
保留中の購入は支払いのない注文であり、両ストアともあなたが待つべきだと明言しています。Google Play は現金、銀行振込、一部のキャリア決済の注文を PENDING 状態で返し、PURCHASED のときにのみ権限を付与するようにと伝えます。Apple は Ask to Buy やその他の必要なアクションのために保留中または延期されたトランザクションを返し、完了したトランザクションを後から Transaction.updates を通じて届けます。支払い済みの状態でロック解除し、アプリが再開したら再確認し、保留中のサポートを有効にしてテストし、待機中の注文を顧客のためにラベル付けしてください。そうすれば保留中の購入は何のコストもかかりません。それを飛ばせば、決して来なかった課金のために有料製品を引き渡すことになります。それは、指し示せる領収書のない唯一の損失です。
よくある質問
- 保留中の購入とは何ですか?
- 保留中の購入は、ストアが受け付けたものの、まだ課金していない注文です。Google Play では PENDING 購入状態で、現金、銀行振込、一部のキャリア決済など、後で決済される支払い方法に使われます。Apple では保留中または延期されたトランザクションで、最も多いのはファミリー管理者の承認を待つ Ask to Buy の購入です。どちらの場合もまだお金は回収されていないので、アクセスを付与すべきではありません。
- 購入が保留中の間、アクセスを付与すべきですか?
- いいえ。Google Play では状態が PURCHASED のとき、Apple ではトランザクションが完了したときにのみ権利を付与してください。注文がまだ保留中のうちに機能をロック解除し、支払いが決して確定しなければ、あなたは製品を無料で引き渡したことになり、取り消すべき課金もありません。そもそも一度も行われていないからです。
- Google Play で保留中の購入を引き起こす支払い方法はどれですか?
- 帯域外で決済される支払い方法です。実店舗での現金払い、銀行振込、一部のキャリア決済のオプションは、タップと課金の間に追加の手順を必要とするため、Google は購入を PURCHASED ではなく PENDING 状態で返します。現金払いの場合、顧客は通知とメールでコードを受け取り、対応店舗で支払います。
- Ask to Buy とは何ですか。保留中の購入とどう関係しますか?
- Ask to Buy は Apple の Family Sharing 機能で、子どもがファミリー管理者の承認を必要とする購入をリクエストできるようにするものです。リクエストが待機している間、購入は Apple の保留中の状態にあり、StoreKit 2 では Product.PurchaseResult.pending として、より古い StoreKit では延期されたトランザクションとして返されます。完了したトランザクションは、管理者が承認したときにのみ、Transaction.updates を通じて届きます。
- 保留中の購入が一度も支払われなかったらどうなりますか?
- 注文はキャンセルされ、お金のやり取りはありません。Google Play では、一回限りの商品には ONE_TIME_PRODUCT_CANCELED 通知、タイプ 2、サブスクリプションには SUBSCRIPTION_PENDING_PURCHASE_CANCELED、タイプ 20 を受け取ります。Apple では、延期されたトランザクションは単に完了したトランザクションになりません。すでにアクセスを付与していたなら、その瞬間に損失が現実になります。
- 保留中の購入は返金と同じですか?
- いいえ。返金は実際に回収された支払いを取り消します。成立しなかった保留中の購入は、そもそも一度も課金されていないので、取り消すものはなく、返金レポートにも何も表示されません。早くロック解除していたなら、そのコストは、収益を生まなかった注文を提供するために費やした計算リソース、API 呼び出し、ストレージ、または消耗型アイテムです。
出典と参考資料
- Android Developers: Integrate the Google Play Billing Library (PENDING purchase state, grant entitlement only on PURCHASED, enablePendingPurchases, queryPurchasesAsync, cash payment code flow, three-day acknowledgement window begins on transition to PURCHASED)
- Android Developers: Real-time developer notifications reference (OneTimeProductNotification ONE_TIME_PRODUCT_PURCHASED=1 and ONE_TIME_PRODUCT_CANCELED=2; SubscriptionNotification SUBSCRIPTION_PURCHASED=4 and SUBSCRIPTION_PENDING_PURCHASE_CANCELED=20)
- Android Developers: Test Google Play Billing (license testers get delayed-payment test instruments that auto-complete or auto-cancel for testing pending transactions)
- Apple Developer: Product.PurchaseResult (the pending case, returned when a purchase needs action such as Ask to Buy approval before it completes)
- Apple Developer: SKPaymentTransactionState.deferred (a transaction whose final status is pending an external action such as Ask to Buy)
- Apple Developer: Transaction.updates (StoreKit delivers transaction updates, including ones approved later, asynchronously)
RefundHalt
App Store と Google Play の返金を自動処理
続きを読む
解約よりも更新失敗のほうが多く起きており、その非自発的チャーンはまだ取り戻せる収益です
多くのサブスクリプションを終わらせるのは、解約のタップではなくカードの拒否であり、ストアは数週間にわたって回収を試み続けます。App Store と Google Play での請求猶予期間、請求リトライ、アカウント保留の仕組みと、非自発的チャーンが実際にいくら失わせているのかを解説します。
子どもによる無断アプリ内課金はほぼ必ず親へ返金され、その負担は開発者が負う
子どもが親のスマートフォンでコインパックを買うと、Apple も Google もそれを返金し、どちらも事前に開発者へ確認しません。規制当局がそう設計させたのです。こうした無断アプリ内課金の返金が各ストアでどう処理されるのか、お金が動く15分の猶予、そして実際にいくらの損失になるのかを解説します。