決済連携で見落としやすい「失敗・取消・再実行・通知」の設計
- 1 日前
- 読了時間: 11分
オンライン決済は、正常に支払いが完了する流れだけを作れば終わりではありません。通信が途中で切れた、取消に失敗した、結果通知が遅れて届いた――こうした例外が起きたときに、注文や予約をどう扱うかまで決めて初めて、実運用できる決済連携になります。
特に重要なのは、「失敗」と「結果が分からない状態」を分けることです。ここを曖昧にすると、二重決済や未回収、注文状態との不整合につながる可能性があります。

はじめに:決済連携は「うまくいかなかったとき」の設計で差が出る
既存Webシステムへ決済を追加するときには、注文・予約などの業務状態と、決済状態を分けて考える必要があります。
この基本的な考え方については、既存Webシステムへ決済機能を追加するとき、発注前に確認すべきことで詳しく解説しました。
実際の運用では、さらにその先を考える必要があります。
たとえば利用者が「支払う」ボタンを押した直後に通信がタイムアウトしたとします。
自社システムから見ると、決済APIの正常な応答は受け取れていません。しかし、だからといって決済そのものが失敗したとは限りません。
決済事業者側では処理が完了しているものの、戻りの通信だけが途切れている可能性があるからです。
このとき、
エラーになったから、もう一度決済する
と単純に再実行してしまうと、二重に処理されるリスクがあります。
決済連携では、正常系だけでなく、失敗・結果不明・取消・再実行・通知遅延まで含めて状態を設計することが重要です。
結論:「成功か失敗か」の2択で決済状態を管理しない
決済連携では、最低でも次のような状態を区別して考えることをおすすめします。
決済前
決済処理中
決済成功
決済失敗
結果確認中
取消処理中
取消完了
取消失敗
システムによって名称や必要な状態は変わります。
重要なのは、処理結果をまだ判断できない状態を用意することです。
「成功した」という情報がないから失敗。
「取消APIを呼んだ」から取消済み。
このように、APIを呼び出した事実と、その処理が確定した事実を一緒にしてしまうと、通信障害や外部サービス障害が起きたときに正しい状態を判断できなくなります。
決済連携では、
要求した状態
と
実際に確定した状態
を分けて考えます。
これは技術的な都合だけではありません。
その状態によって、
商品を発送してよいか
予約を確定してよいか
利用者へ再決済を案内してよいか
サービスを提供してよいか
経理上どの取引として扱うか
といった業務判断が変わるためです。
「決済失敗」と「決済結果不明」は別のもの
決済処理がうまくいかなかったときは、大きく分けて2種類あります。
結果が明確に失敗しているケース
決済事業者からエラー結果が返り、その取引が成立していないことを確認できているケースです。
この場合は、エラー内容や決済方式に応じて、
利用者に再度操作してもらう
別の支払方法へ変更してもらう
運用担当者が確認する
といった次の処理へ進めます。
結果そのものを取得できていないケース
注意したいのはこちらです。
たとえば、
自社システムから決済事業者へ決済要求を送信
決済事業者側で処理
自社システムへ結果を返送
途中の通信障害で結果を受信できない
というケースです。
自社システムから見るとエラーですが、決済事業者側で決済が成立している可能性があります。
GMOペイメントゲートウェイのPGマルチペイメントサービス開発者ドキュメントでも、通信障害によるタイムアウトなどで決済結果を取得できなかった場合は、取引状態を照会するインターフェースを利用するよう案内されています。
したがって、このケースで必要なのは「再決済」ではありません。
まず、
この取引は実際にはどうなったのか
を確認することです。
自社システム側では一旦「結果確認中」のような状態へ置き、決済事業者への取引照会や後続の結果通知によって最終状態を確定させる設計が考えられます。
「エラーを受け取った」と「決済に失敗した」は同じではない。
これは決済連携で特に重要な考え方です。
取消・返金も「実行したら終わり」ではない
予約キャンセルや注文取消があるシステムでは、決済後の取消・返金も設計する必要があります。
ここでも、
取消APIを呼び出した = 決済が取り消された
とは考えません。
一般的には、
業務上の取消要求が発生する
対象となる決済取引を特定する
決済事業者へ取消・返金処理を要求する
処理結果を確認する
自社システムの決済状態を更新する
必要に応じて注文・予約状態を更新する
利用者や運用担当者へ通知する
という流れを考えます。
特に注意したいのは、予約や注文のキャンセルと、決済の取消・返金は別の処理だということです。
たとえば自社システム上では予約をキャンセルできたのに、決済事業者側の取消処理が何らかの理由で完了していなければ、
予約はキャンセル済みなのに、決済は残っている
という状態が生まれます。
そのため、
取消処理中
取消完了
取消失敗
などを区別し、取消に失敗した取引を後から確認できるようにしておくことが重要です。
また、取消や返金で利用できる処理や、その後の取引状態は、決済サービス、決済手段、現在の取引状態、処理するタイミングなどによって異なります。
GMOペイメントゲートウェイのクレジットカード決済でも、取引状態や処理タイミングによって、取消後の扱いが分かれています。
発注側が個々の決済用語を覚える必要はありません。
発注時には、
いつまでキャンセルできるのか
全額取消だけか、一部返金もあるのか
利用後の返金はあるのか
金額変更はあるのか
取消に失敗した場合、誰が対応するのか
といった業務ルールを開発会社へ共有することが重要です。
再実行には「同じ処理の再送」と「新しい決済」の2種類がある
「決済に失敗したらリトライする」という言葉も注意が必要です。
実際には、大きく2種類の再実行があります。
通信障害などに対する技術的な再送
一時的な通信障害などによって要求を再送するケースです。
この場合は、同じ処理を2回送っても二重処理にならない仕組みがあるかを確認する必要があります。
決済APIによっては、同一処理を識別するためのキーなどを使い、安全に再送できる仕組みが提供されています。
一方、そのような仕組みがない場合や、すでに処理済みか判断できない場合には、先に現在の取引状態を確認してから次の処理を決める必要があります。
決済失敗後に利用者がもう一度支払う
こちらは、一度目の決済が失敗したことを確認したうえで、新しい決済を行うケースです。
技術的な再送とは意味が違います。
決済サービスによっては、一度使用した取引識別子をそのまま次の決済へ使えない場合もあります。
そのため、
元の注文・予約ID
1回目の決済試行
2回目の決済試行
を区別して管理できるようにしておくと追跡しやすくなります。
たとえば一つの予約に対して、
予約ID:R-1001 決済試行1:失敗 決済試行2:成功
という形で、一つの業務データに複数の決済試行が紐づく可能性を考えておきます。
これにより、問い合わせや障害調査の際にも「どの決済が実際に成立したのか」を追いやすくなります。
結果通知は「一度、順番どおりに届く」とは限らない
決済事業者から自社システムへ、決済結果を非同期で通知する仕組みが提供されていることがあります。
いわゆるWebhookや結果通知です。
これは非常に便利ですが、
通知が必ず一度だけ、取引順に、すぐ届く
ことを前提にシステムを作るのは危険です。
GMOペイメントゲートウェイのPGマルチペイメントサービスでは、結果通知の受信に失敗した場合の再送機能が用意されています。
また公式ドキュメントでは、通信状態などによって結果通知が届かない可能性があるため、取引照会APIとの併用が推奨されています。
さらに、再送が発生すると、実際の取引履歴とは異なる順序で通知を受信する可能性も説明されています。
たとえば、
与信
売上確定
取消
という順に処理された取引でも、売上確定の通知だけ一度受信に失敗すれば、
与信の通知
取消の通知
再送された売上確定の通知
という順番で届く可能性があります。
ここで最後に届いた通知だけを見て、
売上確定の通知が来たから「決済済み」へ戻す
と処理してしまうと、実際には取消済みの決済状態を巻き戻してしまいます。
そのため結果通知を受け取る側では、
どの取引の通知なのか
どの処理についての通知なのか
すでに処理済みではないか
現在の状態から、その状態へ遷移してよいのか
通知された処理日時はいつなのか
などを確認して処理する必要があります。
「最後に届いた通知が最新状態」とは限らないという前提が重要です。
具体例:決済直後に通信がタイムアウトした予約システム
予約サイトで、利用者が10,000円の予約をカード決済するケースを考えます。
利用者が「支払う」を押した直後、自社システムと決済事業者間の通信がタイムアウトしました。
このとき、すぐに、
決済失敗
と表示して再決済を案内する設計にしていると危険です。
代わりに、たとえば次のように扱います。
1. 決済状態を「結果確認中」にする
予約自体は保持し、まだ「支払済」にも「決済失敗」にもしません。
2. 決済事業者側の取引状態を確認する
取引照会や結果通知を使い、その決済が成立しているかを確認します。
3. 結果に応じて状態を確定する
決済成功が確認できれば「決済済み」。
失敗が確認できれば「決済失敗」。
一定時間たっても判断できなければ、運用担当者が確認できる対象にします。
4. 状態確定後に次の業務を進める
予約確定メールを送る、サービス提供対象へする、再決済を案内するといった後続処理は、状態が確定してから行います。
この設計なら、利用者がブラウザを閉じたり、通信障害が起きたりしても、
お金は取れているのに予約がない 予約はあるのに再決済して二重に支払った
といった状況を防ぎやすくなります。
発注前に決めておきたい7つの項目
決済連携を発注するときには、API仕様を細かく理解するより、次の7項目を整理しておくと設計が進めやすくなります。
1. 何をもって決済成功とするか
決済事業者から成功結果を受けた時点なのか、売上確定まで終わった時点なのかを整理します。
2. 決済結果を確認できないとき、業務をどう止めるか
予約や注文を保持するのか、在庫を確保するのか、利用者へ何と表示するのかを決めます。
3. 再決済できる条件
明確な失敗時だけ再決済させるのか、運用担当者の確認が必要なケースがあるのかを整理します。
4. キャンセル・返金の業務ルール
全額取消、一部返金、利用後返金、金額変更など、実際に発生するパターンを洗い出します。
5. 結果通知をどこまで使うか
決済事業者から通知を受け取るだけでなく、通知失敗時の再確認方法まで決めます。
6. 異常取引を誰が確認するか
自動で解決できない取引を、管理画面や一覧から担当者が確認できるようにするかを決めます。
7. テストでどこまで例外系を確認するか
正常な決済だけでなく、
決済失敗
タイムアウト
再決済
取消
返金
通知失敗
同じ通知の再受信
など、実運用で起こり得るケースも試験対象にします。
外部API連携全般の発注準備については、自社システムと外部サービスをAPI連携するとき、発注前に整理すべき情報も参考にしてください。
プレイリーソリューションズでは、正常系と例外系を一緒に整理します
プレイリーソリューションズは、カーシェアなど予約・会員・課金を伴うシステムをはじめ、継続課金や利用状況に応じた変動金額の決済などを扱ってきました。
決済連携で特に重視しているのは、単にAPIが呼べることではなく、
この取引はいま何の状態なのか 次にシステムが何をしてよいのか 異常が起きたとき、どう正常な状態へ戻すのか
を後から判断できるようにすることです。
プレイリーソリューションズでは、GMOペイメントゲートウェイのPGマルチペイメントサービスについて、プロトコルタイプ・OpenAPIタイプ双方の設計・実装経験があります。
既存Webシステムへの決済追加では、決済APIだけを先に実装するのではなく、
現在の業務フロー → 業務状態 → 決済状態 → 例外系 → リカバリ方法 → API実装 → 試験
という順で整理します。
仕様書が十分にない既存システムであれば、現行システムの調査やデータ構造の確認から始めることも可能です。
注意点:正しい処理方法は決済サービスごとに確認する
この記事で紹介したのは、決済連携を設計するときの基本的な考え方です。
実際には、
利用できる決済状態
取消・返金の方法
再実行の仕様
取引IDの扱い
結果通知の方式
再送の回数やタイミング
取引照会の方法
などは決済サービスによって異なります。
また、同じ決済サービスでも、クレジットカード、コード決済、コンビニ決済など決済手段が変われば処理方法が変わる場合があります。
そのため実装時には、利用する決済サービスの最新ドキュメントとテスト環境で仕様を確認することが必要です。
まとめ:決済連携では「結果が分からないときにどうするか」を先に決める
決済連携の設計では、成功するケースだけでなく、
決済に失敗した
結果を取得できなかった
取消・返金に失敗した
再実行が必要になった
結果通知が届かなかった
通知が再送された
通知が処理順とは違う順番で届いた
といったケースまで考える必要があります。
特に最初に確認したいのは、
「決済結果が分からない状態を、現在のシステムで表現できるか」
です。
「成功」「失敗」しか持っていない場合は、そこから見直すと例外系を整理しやすくなります。
既存Webシステムへ決済を追加したいものの、現在の注文・予約状態と決済状態をどう組み合わせればよいか分からない場合は、プレイリーソリューションズへご相談ください。
既存システムの調査から、決済状態・例外系・リカバリ方法の整理、API連携の設計・実装・試験まで対応します。


