電文は二度届くことがある
一言でいうと
レスポンスが来ないことと、処理されていないことは別の事実ですが、送った側はその2つを区別できません。そのため、再送が二重送金を生みます。防ぐ方法は冪等キーただ1つです。
なぜ必要なのか
銀行同士がやり取りするメッセージを電文と呼びます。口座間送金1件が電文1件で、各電文には電文番号が付きます。
問題はこれです。電文を送ったのに、レスポンスが来ませんでした。このとき送った側が知っている事実は「レスポンスを受け取れなかった」の1つだけです。相手が受け取っていないのかもしれませんし、受け取って処理したもののレスポンスが失われたのかもしれません。この2つは、送った側からは区別する方法がありません。
お金を送る側にとって、再送しなければ顧客の送金は失敗のまま終わります。そこで再送します。相手が最初の電文をすでに処理していたなら、今度は同じお金が2回出ていきます。
どう動くのか
解決策は冪等キー(idempotency key)です。元取引1つにつき1つ付く識別子です。
전문 번호(msg_id) 전송할 때마다 새로 매긴다. 재전송하면 다른 번호가 붙는다.
멱등키(idem_key) 원거래 하나에 하나. 재전송해도 같은 값을 쓴다.
2つの韓国語コメントは、順に、電文番号(msg_id)は送信するたびに新しく採番され、再送すると別の番号が付くことと、冪等キー(idem_key)は元取引1つにつき1つで、再送しても同じ値を使うことを述べています。
受け取る側は冪等キーを記憶しておき、すでに見たキーが再び来たら処理せず、最初の処理の結果をそのまま返します。失敗で答えるのではなく、成功のレスポンスをもう一度返すことが要点です。失敗で答えると、送った側はまた再送します。
冪等キーには有効期限が必要です。永久に記憶することはできないからです。通常は数日から1か月の間に設定しますが、この期間が再送の窓より短いと、冪等性が静かに崩れます。
ここで、FDEが知っておくべき決定的な事実があります。二重送金は突合では捕まりません。
こちらが電文を2回送り、相手が2回処理したなら、こちらの元帳にも2件が残り、相手の清算ファイルにも2件が入ってきます。件数も金額も完全に一致します。総計の突合は完璧に通ります。
捕まる場所は1か所だけです。同じ冪等キーに電文が2つ以上ぶら下がっていないかを見ることです。突合が「2つの帳簿が同じか」を問うのに対し、この照会は「こちらの帳簿の中で、同じ取引が何回も出ていないか」を問います。2つの質問はまったく違います。
現場での姿
第一に、「送金が2回出ています」という問い合わせを、突合の結果で反論してはいけません。突合が合っていたことは、何の根拠にもなりません。冪等キーでまとめて照会するまでは、二重送金がないとは言えません。
第二に、タイムアウト値が短いと、この事故が増えます。相手システムの処理時間が延びた日(締めバッチが重なった日や、連休の直前など)には、タイムアウトが大量に発生し、再送が殺到します。そのため、二重送金は散発的には起きず、特定の日付に集中して起きます。調査のときに時間の分布を先に見ると、原因が早く絞り込めます。
第三に、再送を生み出すのは人のこともあります。画面でレスポンスが来ないため担当者がボタンをもう一度押す場合、バッチが失敗と判断して再投入する場合、監視ツールがリトライする場合は、すべて同じ結果を生みます。冪等キーがなければ、この3つをすべて防がなければなりませんが、それは不可能です。
第四に、超過分の戻し入れは、新しい送金ではなく訂正として処理します。余分に出たお金を単に反対方向に送ると、元帳には送金が3件残り、そのうちどれが元取引でどれが訂正なのかわからなくなります。元帳側は反対仕訳で、外部側は元取引の参照を付けた返却電文で送って初めて、あとで追跡できます。
次のラボですること
こちらの元帳と相手の清算ファイルを突合したあと、突合が完璧に通った状態から、冪等キーで二重送金を見つけ出します。冪等キー2つに電文5件がぶら下がっており、超過して出た金額がいくらかを計算します。そして、その金額が差額清算ポジションにそのまま混ざっていること、つまり決済の前に調整する必要があることを確認します。