コンテンツへスキップ
DedicatedPHP 接触

WooCommerceで確認が遅れても二重請求を防ぐ方法

決済確認が遅れたり重複したりしても、再請求したり注文を不用意に変更したりしてはいけません。検証・追跡が可能で安全なフローを設計しましょう。

決済試行、検証済み通知、不一致の確認を示すWooCommerce決済確認フローの図

購入者が決済を終えてストアに戻ってきたものの、確認ページが読み込まれないことがあります。また、決済プロバイダーから同じ通知が複数回届くこともあります。いずれの場合も、ストアに表示される状態がプロバイダー側で実際に起きたことを反映しない可能性があります。戻り画面をより信頼するだけではリスクを解消できません。ブラウザーからの応答、実際の決済状態、注文状態を区別する必要があります。

WooCommerceでの決済確認は、再請求の指示ではなく、検証と照合のプロセスとして扱う必要があります。各試行を個別に識別できるようにし、通知の重複による二重処理を防ぎ、注文を変更したり後続処理を開始したりする前に不一致を確認することが目的です。

遅れて届いた応答だけで注文を変更してはいけない理由

遅れて届いた応答だけで注文を変更してはいけない理由 — guía visual de DedicatedPHP

購入者がサイトに戻ることと、プロバイダーからの通知は、それぞれ異なる役割を担います。戻り画面は顧客への案内に役立ちますが、ブラウザー、接続、セッションに依存します。Webhookなどのプロバイダー通知は決済システムから送られますが、遅延したり、重複して送信されたりすることがあります。どちらのシグナルも、送信元、その決済試行との関連性、ストアにとっての意味を確認せずに解釈してはいけません。

遅延は決済失敗を意味するものでもありません。すぐに応答が届かないからといってストアが再請求すると、二重請求が発生する可能性があります。同様に、顧客が成功ページに到達したという理由だけで注文を支払い済みにすると、取引が確認されていないのにアクセスを許可したり、発送を開始したりするおそれがあります。

決済試行ごとの状態、プロバイダーから受信したイベント、WooCommerceにおける注文の運用状態という3つの結果を分けて管理しましょう。試行を確認中の間、注文は保留中のままでもかまいません。先行する試行が失敗し、後続の試行が完了する場合もあります。この経過を記録すれば、すべてを調査しにくい単一のラベルにまとめずに済みます。

決済試行、通知、注文状態を分ける

注文は購入とその商取引上のライフサイクルを表します。決済試行は、決済ゲートウェイに対する個別の処理を表します。通知は、承認、売上確定、拒否、返金などのイベントに関するメッセージです。これらは相互に関連しますが、同じものではありません。各試行について、プロバイダー側の識別子、金額、通貨、日時、判明している結果を保持する必要があります。

新しい試行を開始する前に、その注文について進行中の試行や支払い確認済みの取引がすでに存在しないか、フローで確認します。ゲートウェイに対する処理を再試行する場合は、プロバイダーが対応していれば冪等性キーの使用が望ましいでしょう。これにより、同じリクエストの技術的な再送を同一処理として認識し、二重請求になるのを防げます。ただし、キーの提供状況や動作は連携方式とプロバイダーによって異なるため、対応していると決めつけてはいけません。

通知は、イベント識別子と、対応する取引または試行の識別子に関連付ける必要があります。プロバイダーが信頼できる一意の識別子を提供しない場合は、利用可能なデータに基づいて適切な重複排除方法を定め、その制約を文書化します。同じ注文に正当な複数の試行が存在する可能性があるため、注文だけを基準に重複排除するのは避けましょう。

有効な状態遷移を定義し、順序が前後したイベントを扱う

注文を更新する前に、決済方法ごとに有効な状態遷移を定義します。たとえば、保留中の試行は確認済みまたは失敗に遷移できますが、古い保留通知によって、すでに確認済みの試行を以前の状態に戻してはいけません。承認と売上確定も別の状態である場合があります。承認されても、必ずしも資金が回収されたとは限りません。

連携処理では、受信イベントを記録済みの状態および関連する取引と照合する必要があります。適用済みのイベントが再度届いた場合は、認識したうえで副作用を繰り返さずに応答します。副作用には、在庫の減算、メール送信、アクセス権の付与、外部システムへの通知などがあります。中断によって注文は更新されたのにイベントが処理済みと記録されない、あるいはその逆となる可能性を減らすため、状態変更とイベント処理の記録を連携させる必要があります。

イベントの順序が前後した場合は、サーバー時刻を単純に比較するのではなく、明確なルールに従います。プロバイダーの状態の意味に基づき、必要に応じてAPIを通じて取引の現在状態を照会します。安全な遷移を判断できない場合は、結果を推測せず、既知の状態を維持して確認に回します。

検証・記録・更新を追跡可能にする

署名検証など、その連携方式で文書化された方法に従って、通知が本当にプロバイダーから送信されたことを確認します。また、アカウントや環境がストアと一致すること、金額、通貨、参照情報、注文が想定どおりであることも確認します。有効な識別子が含まれている、または推測しにくいURLに届いたというだけで、メッセージを受け入れてはいけません。

変更を適用する前に、調査に役立つ記録を保存します。イベント識別子、プロバイダー側の参照情報、関連する注文と試行、イベント種別、検証結果、受信時刻、判断内容を記録します。認証情報や個人情報は保護し、調査に必要な情報だけを記録してください。カード番号全桁や秘密情報は記録しません。必要以上の人が参照できるデバッグログに機密データを含めないようにします。

WooCommerceとプロバイダーの間に不一致があっても、新たな取引を作成して解決しようとしてはいけません。プロバイダーのツールまたはAPIで処理状態を確認し、ストアの記録と照合します。支払いが確認された場合は、ゲートウェイに対応したフローを通じて注文を更新し、後続処理が一度だけ実行されることを確認します。結果が依然として曖昧なら、確認が取れるまで注文を支払い済みにせず、新たな請求も開始しないでください。

例外を確認するためのキューを作成する

金額や通貨の不一致、注文に関連付けられていない参照情報、無効な署名、1件の購入に対する複数の支払い確認、予期しない返金、状態遷移が許可されないケースなど、人による確認が必要な状況を定義します。キューには、調査に必要な参照情報、最後に確認された状態、例外の理由を表示し、適切な権限を設定します。

確認作業は再現可能な手順に沿って行います。プロバイダーで取引を照会し、注文とその試行を確認し、更新・返金・エスカレーションのいずれが適切か判断して、判断者を記録します。記録を削除したり、データベース上で状態を直接変更したりして不一致を解消しないでください。経緯が失われ、拡張機能や後続タスクとの不整合が生じる可能性があります。

遅延・重複・部分的な障害をテストする

通常のフローを阻害する状況を、制御された環境でテストします。Webhookより前または後にブラウザーが戻る場合、通知の重複、イベントの順序の前後、長時間の遅延、無効な署名、処理中のストア停止などです。状態を保存した後、プロバイダーへの応答前に接続が切れるといった部分的な障害も含め、再試行で処理が重複しないことを確認します。

また、失敗した試行の後に成功した試行が明確に記録されること、古い通知が状態を巻き戻さないこと、請求リクエストの再送で別の取引が作成されないことも確認します。ゲートウェイのテスト機能と本番以外のデータを使い、実際の注文に対する請求を強制してシナリオをテストしてはいけません。WooCommerceとプロバイダーの管理画面またはAPIの両方で結果を確認します。

不一致が疑われる場合の運用チェックリスト

不一致が疑われる場合の運用チェックリスト — guía visual de DedicatedPHP
  • 注文、各試行、プロバイダー側の参照情報を特定します。ある参照情報が別の参照情報と同じものだと決めつけないでください。
  • 信頼できる情報源で取引の現在状態を照会し、金額と通貨を照合します。
  • イベントが認証済みか、すでに処理済みか、順序が前後して届いたものかを確認します。
  • アクセス権付与、メール送信、発送準備など、注文に伴う後続処理が実行されたか確認します。
  • 結果が明らかになっていない試行がある間は、再請求しません。
  • 判断を記録し、曖昧なケースはエスカレーションします。二重請求が発生した場合は、プロバイダーの返金手順に従い、その結果を顧客に伝えます。

信頼できるフローに必要なのは、すべての応答が時間どおりに届くことではありません。遅延、重複、不確かな状態によって、取り消せない処理が不用意に実行されないことです。注文と決済試行を分け、各イベントを検証し、状態遷移を冪等に処理し、例外を確認することで、証拠に基づく調査が可能になり、二重請求のリスクを抑えられます。

これらのアイデアをあなたのプロジェクトに活用してみませんか?あなたのPHPプラットフォームについて話し合いましょう。
関連サービスを見る