学習・技術検証用デモ — 本システムは実際の銀行サービスではありません。

公開情報をもとに構築した教育目的のシステムです。実在する個人情報・口座情報・機密情報・認証情報等を入力しないでください。

ミニ銀行ACADEMY SYSTEM LEARNING
教材メニュー
学習進捗0 / 134
あと134項目
INTERMEDIATE · 中級COURSE 09 · BANKING ENGINEERING

銀行エンジニアリング 06:支払の状態遷移(Payment State Machine)

支払は「成功か失敗か」の2つではありません。MiniBank v9の9つの状態と、許可された遷移だけを通す仕組みを学びます。

07 / 55
BANKING ENGINEERING · 銀行エンジニアリング

v8以降に実装した台帳・記帳エンジンなどを実際に動かし、正常時と異常時の両方から銀行システムの構造を学ぶ。

Prerequisite: BANKING SYSTEM

LEARNING GOALS

このページで学ぶこと

  • 9つの支払状態の意味
  • 許可された遷移とDBでの強制
  • 指図内容を変更できない理由

PLAIN LANGUAGE

まず、ここだけつかむ

1

支払には9つの状態があり、許可された遷移だけがDBで通ります。

2

TIMEOUTとRESULT_UNKNOWNは「失敗」ではなく「分からない」状態です。

3

一括処理でも支払は1件ずつ独立し、部分的な失敗は他を巻き戻しません。

DIFFICULT PARTS, STEP BY STEP

難しいポイントを、順番にほどく

専門用語を覚えることより、「なぜ必要か」「このシステムのどこで使うか」を理解することが目標です。

01

State Machine

やさしく言うと

状態と、許される状態の移り方の決まりです。

なぜ必要?

ありえない状態の変化を防ぐためです。

Minibankでは

interbank.transitions と guard_transition()。違反は IB010。

02

Immutable Instruction

やさしく言うと

作成後に変更できない指図内容です。

なぜ必要?

送った内容と記録が食い違わないようにするためです。

Minibankでは

金額・口座・相手行の変更は IB011 で拒否。

03

Partial Failure

やさしく言うと

まとめて処理した一部だけが失敗することです。

なぜ必要?

1件の失敗で全体を止めない設計が必要なためです。

Minibankでは

決済バッチの PARTIAL と RETURN_POSTING_FAILED。

Level 1 基礎:状態とは「いま分かっていること」

支払の状態は、MiniBankがその支払について「いま何を知っているか」を表します。特に TIMEOUT と RESULT_UNKNOWN は「失敗」ではなく「分からない」という状態です。

状態意味お金
CREATED受付済みまだ動いていない
AUTHORIZED資金確保済み顧客預金 → 未決済送金
SENT決済システムへ送信済み未決済送金のまま
ACCEPTED決済システムが受理未決済送金のまま
SETTLED決済済み未決済送金 → 中央銀行当座預金から支払
REJECTED不成立資金確保を取消して顧客へ戻す(資金確保前なら何も動かない)
TIMEOUT期限内に応答がない未決済送金のまま(結果は分からない)
RESULT_UNKNOWN結果不明。照会が必要未決済送金のまま
RETURNED決済後に受取銀行から返却中央銀行当座預金 → 顧客預金

Level 2 銀行業務:許可された遷移

この一覧は interbank.transitions テーブルそのものです。表にない遷移(例:SETTLED から CREATED)はDBが IB010 で拒否します。

  1. 01CREATED → AUTHORIZED / REJECTED
  2. 02AUTHORIZED → SENT
  3. 03SENT → ACCEPTED / REJECTED / TIMEOUT
  4. 04TIMEOUT → RESULT_UNKNOWN / ACCEPTED / REJECTED
  5. 05RESULT_UNKNOWN → ACCEPTED / REJECTED / SENT(条件付き再送)
  6. 06ACCEPTED → SETTLED
  7. 07SETTLED → RETURNED

Level 3 システム:MiniBankでの実装

  • interbank.guard_transition() トリガーが、状態変更のたびに遷移表を確認し、revision を1つ進め、追記専用の interbank.payment_events に1行残す
  • 送金額・口座・相手行などの指図内容は作成後に変更できない(IB011)。変更したいなら別の支払にする
  • 支払行の削除はできない。不成立も返却も、状態として残る
  • 画面が出す操作は src/domain/platform/interbank.ts の availableActions() が状態から決めるが、最終判断は常にDB側の関数

異常時:一括送信で結果がばらばらになった(Partial Failure)

段階内容
症状「資金確保済を送信」で、受理・拒否・応答なしが混在した
考え方支払は1件ずつ独立して状態を持つ。1件の拒否で他の支払を巻き戻す必要はない
決済での部分失敗決済バッチでは、決済と返却を支払ごとの別サブトランザクションで記帳する。返却先の口座が凍結されていると返却だけが失敗し(RETURN_POSTING_FAILED)、バッチは PARTIAL になる
対応口座の凍結を解除して次の決済実行で返却を再処理する。決済済みの事実は巻き戻さない

Level 4 アーキテクチャ:状態をDBで守る理由

状態の正しさをアプリの if 文だけに任せると、別の画面・バッチ・手作業のSQLから不正な遷移が入り込みます。遷移表とトリガーで守れば、どの経路から更新しても同じ規則が適用され、遷移の履歴も漏れなく残ります。

どこを確認すればよいか

  • 支払詳細の「MiniBank側:状態遷移」
  • 決済バッチの「返却/未確認/失敗」件数と details

CHECK YOUR UNDERSTANDING

3問で理解チェック

答えを頭の中で考えてから、各項目を開いて確認してください。

Q1SETTLED から CREATED へ戻せますか?
答え

戻せません。IB010で拒否されます。

Q2返却が失敗したとき、決済済みの事実も取り消されますか?
答え

取り消されません。決済と返却は別のサブトランザクションです。

Q3不成立の支払は削除されますか?
答え

されません。REJECTEDとして残ります。

ここまで読めましたか?

完全に暗記する必要はありません。大切な考え方を説明できそうなら押してください。

SOURCE TRAIL

根拠と関連教材

CURRENT IMPLEMENTATIONは確認したrepository内の実装です。HISTORICAL IMPLEMENTATIONは導入・修正の履歴で、後続migrationによる再定義があり得ます。RELATED LESSONは教材への案内で、実装の一次Sourceではありません。ASSUMPTIONは仮定、UNKNOWNは未確認を表します。

確認基点: d02eae8914f39cbf06bfe422dc39c71886f82b3e / 2026-09-11。稼働環境への適用確認: UNKNOWN。パス実在の自動検査と、記述した技術的事実の確認は別です。

Implementation Status: IMPLEMENTED IN MINIBANK(この教材が扱うコードの範囲)

  • RELATED LESSON/docs/be-interbank-basics銀行間振込の登場人物
  • RELATED LESSON/docs/domain-modeling業務をデータモデルへ翻訳する
  • CURRENT IMPLEMENTATIONsupabase/migrations/20260924110000_v9_interbank_simulator.sqlinterbank.guard_transition / interbank.reconcile状態遷移の検査と未決済送金の照合
  • CURRENT IMPLEMENTATIONsrc/domain/platform/interbank.tsavailableActions()状態ごとに画面が出す操作
  • CURRENT IMPLEMENTATIONsupabase/migrations/20260924110000_v9_interbank_simulator.sqlinterbank.apply_return返却(支払ごとのサブトランザクション)
  • CURRENT IMPLEMENTATIONsupabase/migrations/20260930130000_v17_reliability.sqlinterbank.run_settlement決済バッチ(支払ごとのサブトランザクション。v17で、書込停止中は部分失敗として記録せず RY001 で止める)