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

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

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

銀行エンジニアリング 30:資源APIと振込の「依頼」(範囲・所有者検査・冪等)

トークンを持つアプリが何を読めて、何をしてはいけないのかを追います。特に振込は、アプリは『依頼』までで、送金を決めるのは顧客本人です。

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

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

Prerequisite: BANKING SYSTEM

LEARNING GOALS

このページで学ぶこと

  • 範囲(scope)と所有者検査の二重の確認
  • 振込の依頼と承認を分ける理由
  • 応答が消えたときの冪等な照会

PLAIN LANGUAGE

まず、ここだけつかむ

1

トークンを持つアプリでも、同意された範囲の、本人の情報しか読めません。範囲と所有者をDBが毎回確かめます。

2

振込は、アプリは『依頼』までです。資金が動くのは、顧客が既存の画面でワンタイムコードを確認したときだけです。

3

応答が消えたときは、新しいキーで再依頼せず、元のキーで照会します。

DIFFICULT PARTS, STEP BY STEP

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

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

01

範囲(scope)

やさしく言うと

トークンで許された操作の種類です。

なぜ必要?

必要な操作だけを許して、被害を小さくするためです。

Minibankでは

accounts.read/balances.read/transactions.read/transfers.write。不足は OB011。

02

所有者検査

やさしく言うと

読もうとしている対象が、その顧客のものかを確かめることです。

なぜ必要?

IDを推測して他人の口座を読むのを防ぐためです。

Minibankでは

口座のIDを推測しても『見つからない』(OB030)。

03

冪等キー

やさしく言うと

同じ依頼を何度送っても、1回分として扱うための印です。

なぜ必要?

通信が切れて再送しても、二重の依頼を作らないためです。

Minibankでは

Idempotency-Key。同じ内容は元の依頼を返し、内容が違えば OB020。

Level 1 基礎:アプリが読めるのは、同意された範囲の、本人の情報だけ

トークンがあっても、何でも読めるわけではありません。読む前に、次を毎回確かめます。

①トークンが有効か。②その同意がまだ有効か(取り消されていないか)。③アプリが停止されていないか。④必要な範囲が同意されているか。⑤読もうとしている口座が、その顧客のものか。

API必要な範囲内容
GET /api/open-banking/v1/accountsaccounts.read本人の口座の一覧。他人の口座は含まれない
GET .../accounts/{id}/balancesbalances.read残高(整数の円)と時点
GET .../accounts/{id}/transactionstransactions.read追記専用の元帳から作る取引。新しい順
POST /api/open-banking/v1/transferstransfers.write振込の依頼。Idempotency-Key が必須
GET .../transfers/{id}、?idempotency_key=transfers.writeそのアプリが依頼した振込の状態
GET .../events有効なトークンなら可同意ごとのイベント列

Level 2 銀行業務:依頼と承認を分ける

第三者のアプリは、顧客に代わって『この人に1,500円送りたい』と依頼できます。しかし、実際にお金を動かすのは、顧客がMiniBankの画面で内容を確かめ、ワンタイムコード(TOTP)で承認したときだけです。アプリの依頼だけでは、資金は1円も動きません。

依頼の状態は、PENDING_CUSTOMER_APPROVAL(顧客の承認待ち)、COMPLETED、FAILED、EXPIRED、CANCELLEDなどです。顧客が何もしなければ期限で EXPIRED になります。

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

  • public.ob_gateway は匿名でも呼べる入口だが、openbanking.resolve_token が毎回、トークン→同意→顧客とクライアントの状態を確かめる。無効なトークンはすべて OB010、範囲の不足は OB011。他人の口座IDは『見つからない』(OB030)
  • 振込の依頼(openbanking.initiate_transfer)は、既存の public.request_transfer を呼ぶ。限度額・KYC・宛先の検査・呼出し回数の制限・冪等性は、既存の契約のまま。API側では再実装しない
  • 同じ Idempotency-Key と同じ内容は、元の依頼をそのまま返す。同じキーで内容が違えば OB020(409)。新しいキーで再依頼しない
  • 依頼の状態はイベント(transfer.initiated、transfer.status_changed)として、状態の変更と同じトランザクションで記録する
  • アプリは依頼の承認も取消もできない。承認のAPIは存在せず、承認は顧客の既存の操作だけ
  • トークンは監査ログにも残さない。監査には client と consent の識別子を入れ、外部アプリ経由であること(via=open_banking)も残す
  • 1つの同意が残せる未承認の依頼は3件まで(OB021)。外部のアプリが、顧客本人の振込の依頼枠(1分5件)を使い切れないようにするため
  • 同意が失効したあとは、そのアプリの依頼の状態変更をイベントにしない(顧客の承認は通常どおり完了する)

異常時:依頼の応答が届かなかった

段階内容
症状アプリが振込を依頼したが、通信が切れて結果が分からない
やってはいけないこと新しいIdempotency-Keyで再依頼する(同じ振込が2件の依頼になる)
正しい対応元のキーで GET /transfers?idempotency_key=... を呼ぶ、または同じキー・同じ内容でPOSTし直す
確認依頼は1件のまま。状態がPENDING_CUSTOMER_APPROVALなら、顧客の承認を待つ

Level 4 アーキテクチャ:既存の契約を再利用する

新しい入口ができるたびに、限度額やKYCの検査を作り直すと、入口ごとに抜けが生まれます。MiniBankは、外部からの依頼も、顧客本人が画面から行う依頼と同じ関数を通します。検査は1か所にあり、テストも1か所です。

どこを確認すればよいか

  • 管理画面「Open Banking」の同意とイベント
  • 顧客画面「振込の依頼と結果」(/app/transfer/requests):アプリが依頼した振込を、認証アプリ(TOTP)で承認する。心当たりのない依頼は承認せず、期限で失効させる

CHECK YOUR UNDERSTANDING

3問で理解チェック

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

Q1アプリが振込を依頼すると、残高は減りますか?
答え

減りません。顧客が承認するまで、資金は動きません。

Q2別のアプリのトークンで、他のアプリが依頼した振込を見られますか?
答え

見られません。そのアプリが依頼した振込だけです。

Q3依頼の応答が届かなかったとき、どうしますか?
答え

元のキーで照会するか、同じキー・同じ内容で再送します。新しいキーは使いません。

ここまで読めましたか?

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

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-openbanking-oauth-consent同意とトークンの発行
  • RELATED LESSON/docs/be-openbanking-events-webhooksイベントとWebhook
  • RELATED LESSON/docs/transfer振込の依頼と確認(OTP/TOTP)
  • CURRENT IMPLEMENTATIONsupabase/migrations/20260930120000_v16_open_banking.sqlpublic.ob_gateway / openbanking.resolve_token匿名の入口。Bearerトークン→同意→顧客をDBが毎回解決し、所有者・scope・同意・クライアントの状態を確かめる
  • CURRENT IMPLEMENTATIONsupabase/migrations/20260930120000_v16_open_banking.sqlopenbanking.initiate_transfer / openbanking.sync_transfer振込の依頼は既存のrequest_transferを呼ぶ。確認は顧客本人。冪等キーと状態のイベント化
  • CURRENT IMPLEMENTATIONscripts/regression/suites/privilege.mjs匿名が実行できる関数の許可リスト(ob_gateway、ob_token の2つだけ)。ほかを匿名に開けると権限スイートが失敗する
  • CURRENT IMPLEMENTATIONscripts/banking/v16-openbanking.test.mjs登録・認可・PKCE・コード再使用・スコープ・所有者検査・同意の失効・振込の依頼と確認・イベント/Webhook・秘密の非保存のDBテスト