Project

General

Profile

CR #201 » SDD-003_Sequence-Diagrams.md

內容更新:內部稱謂去識別化(2026-10-18) - Redmine Admin, 10/18/2026 05:32 AM

 

SDD-003 Sequence Diagrams

項目 內容
文件編號 SDD-003
版本 1.1
狀態 已核定
撰寫者 SD
審查者 SA / TL / QA
對應需求 AUT-1.11.3、ISS-2.22.13、RWD-5.15.3、POC-0614、POC-17

1. 說明

本文件定義 15 條關鍵情境之互動順序,為程式實作與測試劇本之共同依據。

1.1 參與者代號

代號 意義
Client 呼叫端(前端、通路、卡組織或排程器)
GW API 閘道
Authz authorization-service
Limit limit-service
Card card-service
Party party-service
Product product-service
Posting posting-service
Payment payment-service
Statement statement-service
Pricing pricing-service
Inst installment-service
Rewards rewards-service
Clearing clearing-service
Notif notification-service
Kafka 事件匯流
Outbox 事件輸出表
HSM 加密機

1.2 通用規則

規則 說明
交易邊界 每個服務之處理為獨立交易(SDD-000 TX-01)
事件發布 一律先寫 Outbox,交易提交後才發布(SDD-000 TX-02/TX-05)
冪等 所有寫入命令須帶 Idempotency-Key
逾時 所有跨服務呼叫設逾時(3 秒),失敗即回滾
追蹤 trace_id 貫穿全部呼叫與事件

2. 情境索引

# 情境 對應 POC/FR
3 授權交易(本行卡核准) POC-17、AUT-1.1
4 授權交易(拒絕與收單分流) POC-13、AUT-1.2 / 1.3
5 請款入帳與重複入帳防範 POC-09、ISS-2.3
6 額度調整與同步 POC-08、ISS-2.4
7 繳款即時恢復額度 POC-11、ISS-2.6
8 三日未銷帳重新佔額 POC-11 情境三
9 帳單批次產製 POC-16、ISS-2.8
10 信用卡快發快綁 POC-06、ISS-2.2
11 錯帳沖正 POC-09、ISS-2.3
12 分期建立與佔用 POC-05、ISS-2.7
13 點數兌換(Online Redeem) POC-04、RWD-5.2
14 清算比對與撥款 POC-03、ISS-2.13
15 爭議帳款處理 BRD-001 BF-09
16 Stand-in 代授權 AUT-1.1
17 讀寫分離同步與補償 POC-14、SYS-2.1

3. 授權交易(本行卡核准)

sequenceDiagram
  autonumber
  participant Client
  participant GW
  participant Authz
  participant Card
  participant Limit
  participant Product
  participant HSM
  participant Outbox
  participant Kafka

  Client->>GW: POST /api/v1/authorizations
  GW->>GW: 驗證權杖與速率限制
  GW->>Authz: 轉發請求(含 trace_id 與 idempotency_key)
  Authz->>Authz: 冪等檢核
  Authz->>Authz: 解析 ISO 8583 電文與欄位校驗
  Authz->>Product: GET /api/v1/parameters/auth-check
  Product-->>Authz: 檢核規則清單與順序
  Authz->>Card: GET /api/v1/cards/{cardId}
  Card-->>Authz: 卡片狀態與管制碼
  Authz->>Limit: GET /api/v1/accounts/{accountId}/limits
  Limit-->>Authz: 可用額度與專用額度
  alt 需 EMV 驗證
    Authz->>HSM: 驗證 ARQC
    HSM-->>Authz: ARPC
  end
  Authz->>Authz: 依序執行檢核規則
  alt 全部通過
    Authz->>Limit: POST /api/v1/limit-holds
    Limit->>Limit: 條件更新可用額度(available >= amount)
    Limit-->>Authz: 佔用成功(holdId)
    Authz->>Outbox: 寫入 authorization.authorization.approved.v1
    Authz-->>GW: 201 核准(含授權碼)
    GW-->>Client: 201 核准
    Outbox->>Kafka: 發布授權核准事件
  else 任一檢核失敗
    Authz->>Outbox: 寫入 authorization.authorization.declined.v1
    Authz-->>GW: 422 拒絕(含回應碼)
    GW-->>Client: 422 拒絕
  end

驗收重點

  • 授權 P99 ≤ 200 ms(不含卡組織往返)。
  • 額度以條件更新扣減,併發下不得超額。
  • 核准與事件在同一交易內寫入(Outbox),事件不得早於資料提交。

4. 授權交易(拒絕與收單分流)

sequenceDiagram
  autonumber
  participant Org
  participant GW
  participant Authz
  participant Split
  participant Legacy
  participant NCCC
  participant Kafka

  Org->>GW: 授權請求(ISO 8583)
  GW->>Authz: 轉發
  Authz->>Authz: 電文解析與卡別判斷
  Authz->>Split: 取得分流決策(商店代號或卡號區段)
  alt 分流至新系統
    Split-->>Authz: NEW
    Authz->>Authz: 新系統授權處理
    Authz-->>GW: 授權回應
  else 分流至舊系統
    Split-->>Authz: LEGACY
    Authz->>Legacy: 模擬轉接至舊系統
    Legacy-->>Authz: 舊系統授權回應
    Authz->>Kafka: 寫入分流佐證事件(含 LOG 識別碼)
    Authz-->>GW: 轉發舊系統回應
  else 他行卡
    Split-->>Authz: NCCC
    Authz->>NCCC: 繞送取授權
    NCCC-->>Authz: 授權回應
    Authz->>Kafka: 寫入繞送佐證事件
    Authz-->>GW: 轉發回應
  end
  GW-->>Org: 授權回應
  Note over Authz,Kafka: 每一筆轉接須留存 LOG 與 trace_id 佐證(POC-13)

5. 請款入帳與重複入帳防範

sequenceDiagram
  autonumber
  participant Client
  participant GW
  participant Posting
  participant Pricing
  participant Limit
  participant Outbox
  participant Kafka

  Client->>GW: POST /api/v1/postings
  GW->>Posting: 轉發(含 idempotency_key)
  Posting->>Posting: 計算業務冪等鍵(卡號+授權碼+日期+金額+幣別)
  Posting->>Posting: 查詢 idempotency_key 是否已存在
  alt 冪等鍵已存在且指紋相同
    Posting-->>GW: 200 回傳前次結果(不重複入帳)
    GW-->>Client: 200 前次結果
  else 冪等鍵已存在但指紋不同
    Posting-->>GW: 409 冪等鍵衝突
    GW-->>Client: 409 衝突
  else 全新請求
    Posting->>Posting: 請款格式與特店檢核
    Posting->>Posting: 授權請款比對
    alt 比對相符
      Posting->>Pricing: 計算費用與利息分攤
      Pricing-->>Posting: 費用明細
      Posting->>Posting: 產生入帳交易並分欄位
      Posting->>Posting: 更新餘額與帳齡
      Posting->>Outbox: 寫入 posting.transaction.posted.v1
      Posting->>Limit: 釋放授權佔用(部分請款釋放差額)
      Limit-->>Posting: 釋放完成
      Posting-->>GW: 201 入帳成功
      GW-->>Client: 201 入帳成功
      Outbox->>Kafka: 發布帳務事件
    else 比對不符(金額不符 / 授權失效 / 重複請款)
      Posting->>Posting: 寫入異常紀錄(可查詢)
      Posting->>Outbox: 寫入 posting.exception.raised.v1
      Posting-->>GW: 422 異常待處理
      GW-->>Client: 422 異常待處理
    end
  end

驗收重點(POC-09):併發 200 筆同冪等鍵請求,僅 1 筆成功入帳。


6. 額度調整與同步

sequenceDiagram
  autonumber
  participant Client
  participant GW
  participant Limit
  participant Product
  participant Outbox
  participant Kafka
  participant Authz

  Client->>GW: POST /api/v1/limit-adjustments
  GW->>Limit: 轉發(含 idempotency_key)
  Limit->>Product: 取得額度政策與可設定上限
  Product-->>Limit: 依角色與客層之上限
  Limit->>Limit: 權限檢核(申請人可設定之上限)
  alt 超過上限
    Limit->>Limit: 標記需主管複核
    Limit-->>GW: 202 待複核
    GW-->>Client: 202 待複核
  else 未超過上限
    Limit->>Limit: 套用額度異動(樂觀鎖)
    Limit->>Outbox: 寫入 limit.limit.adjusted.v1
    Limit-->>GW: 200 生效
    GW-->>Client: 200 生效
    Outbox->>Kafka: 發布額度異動事件
    Kafka->>Authz: 更新授權服務額度快取
    Note over Limit,Authz: 額度同步延遲須 ≤ 1 秒(BR-04-04)
  end

7. 繳款即時恢復額度

sequenceDiagram
  autonumber
  participant Client
  participant GW
  participant Payment
  participant Posting
  participant Limit
  participant Outbox
  participant Kafka
  participant Notif

  Client->>GW: POST /api/v1/payments
  GW->>Payment: 轉發(含 idempotency_key)
  Payment->>Payment: 繳款受理與銷帳檢核
  Payment->>Payment: 繳款分配(費用與違約金→利息→本金)
  Payment->>Posting: 產生繳款入帳交易
  Posting->>Posting: 更新餘額、帳齡與繳款評等
  Posting-->>Payment: 入帳完成
  Payment->>Limit: 即時恢復可用額度
  Limit->>Limit: 條件更新 available_amount
  Limit-->>Payment: 恢復完成
  Payment->>Outbox: 寫入 payment.payment.posted.v1
  Payment-->>GW: 201 繳款完成(含恢復後可用額度)
  GW-->>Client: 201 繳款完成
  Outbox->>Kafka: 發布繳款事件
  Kafka->>Notif: 發送繳款通知
  Note over Payment,Limit: 額度恢復須於入帳後 1 秒內完成(BR-05-01、POC-11)

8. 三日未銷帳重新佔額

sequenceDiagram
  autonumber
  participant Scheduler
  participant Payment
  participant Limit
  participant Posting
  participant Outbox

  Scheduler->>Payment: 每日執行未銷帳檢核
  Payment->>Payment: 查詢 unmatched_flag 為真且超過三日之繳款
  loop 每一筆未銷帳繳款
    Payment->>Payment: 判定是否收到銷帳檔
    alt 已收到銷帳檔
      Payment->>Payment: 標記已匹配
    else 逾三日仍未收到
      Payment->>Limit: 重新佔額(回復原可用額度)
      Limit->>Limit: 條件更新 available_amount
      Limit-->>Payment: 重新佔額完成
      Payment->>Posting: 寫入重新佔額調整紀錄
      Posting-->>Payment: 完成
      Payment->>Outbox: 寫入 payment.payment.unmatched.v1
      Note over Payment,Limit: 三日後可用額度須回復原值(POC-11 情境三)
    end
  end

9. 帳單批次產製

sequenceDiagram
  autonumber
  participant Scheduler
  participant Statement
  participant Party
  participant Posting
  participant Pricing
  participant Outbox
  participant Kafka

  Scheduler->>Statement: POST /api/v1/statement-cycles/{id}/runs
  Statement->>Statement: 建立批次與 Checkpoint
  loop 分批處理(可參數調整並行度)
    Statement->>Party: 取得歸戶與合併設定
    Party-->>Statement: 歸戶資料
    Statement->>Posting: 取得本期帳務餘額與交易
    Posting-->>Statement: 帳務資料
    Statement->>Pricing: 計算本期利息與費用
    Pricing-->>Statement: 計息結果
    Statement->>Statement: 產生帳單並套用帳彩
    Statement->>Statement: 更新 Checkpoint
    alt 某筆異常
      Statement->>Statement: 記錄異常資料與原因
      Statement->>Statement: 中止並保留 Checkpoint
      Statement-->>Scheduler: 批次中止(可自 Checkpoint 續跑)
    end
  end
  Statement->>Statement: 產生各形式帳單
  Statement->>Outbox: 寫入 statement.statement.issued.v1
  Outbox->>Kafka: 發布帳單事件
  Statement-->>Scheduler: 批次完成(含筆數與耗時)
  Note over Scheduler,Statement: 1,000 萬筆須於 1 小時內完成,批次期間 ONLINE ≥ 200 TPS(POC-16)

10. 信用卡快發快綁

sequenceDiagram
  autonumber
  participant Client
  participant GW
  participant Card
  participant Party
  participant Product
  participant HSM
  participant Outbox
  participant Kafka

  Client->>GW: POST /api/v1/cards/{cardId}/instant-issuance
  GW->>Card: 轉發
  Card->>Card: 確認快發條款已勾選
  alt 未勾選快發條款
    Card-->>GW: 422 條款未勾選
  else 已勾選
    Card->>Product: 取得產品與版面參數
    Product-->>Card: 產品設定
    Card->>Party: 取得歸戶與持卡人
    Party-->>Card: 客戶資料
    Card->>Card: 亂數給號並檢查號碼未使用
    Card->>Card: 產生核准序號
    Card->>Card: 產生卡號與效期
    Card->>HSM: 產生 CVV2(不儲存)
    HSM-->>Card: CVV2 值
    Card->>Card: 寫入卡片(狀態 UNACTIVATED)
    Card->>Outbox: 寫入 card.card.issued.v1
    Card-->>GW: 201 發卡成功
    GW-->>Client: 201 發卡成功
    Outbox->>Kafka: 發布發卡事件
  end
  Client->>GW: POST /api/v1/cards/{cardId}/tokens(綁卡)
  GW->>Card: 轉發
  Card->>Card: 驗證部分開卡三要素
  alt 驗證通過
    Card->>Card: 建立 Token 並綁定行動支付
    Card->>Outbox: 寫入 card.token.bound.v1
    Card-->>GW: 201 綁卡成功
  else 驗證失敗
    Card-->>GW: 422 身分驗證失敗
  end
  Note over Card,HSM: CVV2 不得落地儲存(BR-01-03、POC-06 情境 6-8)

11. 錯帳沖正

sequenceDiagram
  autonumber
  participant Client
  participant GW
  participant Posting
  participant Limit
  participant Clearing
  participant Outbox
  participant Kafka

  Client->>GW: POST /api/v1/postings/{id}/reversals
  GW->>Posting: 轉發(含 idempotency_key)
  Posting->>Posting: 鎖定原始交易(不得修改原紀錄)
  Posting->>Posting: 判定原始交易狀態
  alt 已入帳未出帳
    Posting->>Posting: 產生反向沖銷交易
  else 已出帳
    Posting->>Posting: 產生調整交易(下期帳單呈現)
  else 已清算
    Posting->>Clearing: 提出清算調整
    Clearing-->>Posting: 調整受理
    Posting->>Posting: 產生調整交易
  end
  Posting->>Posting: 產生反向分錄(借貸平衡)
  Posting->>Limit: 還原授權佔用
  Limit-->>Posting: 還原完成
  Posting->>Posting: 更新餘額(記錄前後值)
  Posting->>Outbox: 寫入 posting.transaction.reversed.v1
  Posting-->>GW: 200 沖正完成
  GW-->>Client: 200 沖正完成
  Outbox->>Kafka: 發布沖正事件
  Note over Posting: 沖正須成對產生,原紀錄不得刪除(BR-12-01)

12. 分期建立與佔用

sequenceDiagram
  autonumber
  participant Client
  participant GW
  participant Inst
  participant Limit
  participant Product
  participant Posting
  participant Outbox

  Client->>GW: POST /api/v1/installments
  GW->>Inst: 轉發(含 idempotency_key)
  Inst->>Product: 取得分期參數(期數、費率、手續費)
  Product-->>Inst: 分期參數
  Inst->>Limit: 檢核可用額度
  Limit-->>Inst: 可用額度
  alt 額度不足
    Inst-->>GW: 422 額度不足
  else 額度足夠
    Inst->>Inst: 計算首期金額與每期金額
    Inst->>Inst: 建立分期計畫與各期明細
    Inst->>Limit: 佔用分期額度
    Limit-->>Inst: 佔用完成
    Inst->>Posting: 首期入帳
    Posting-->>Inst: 入帳完成
    Inst->>Outbox: 寫入 installment.plan.created.v1
    Inst-->>GW: 201 分期成立
    GW-->>Client: 201 分期成立
  end

13. 點數兌換(Online Redeem)

sequenceDiagram
  autonumber
  participant Client
  participant GW
  participant Rewards
  participant Product
  participant Posting
  participant Authz
  participant Outbox
  participant Kafka

  Client->>GW: POST /api/v1/rewards/redemptions
  GW->>Rewards: 轉發(含 idempotency_key)
  Rewards->>Product: 取得折抵參數(比例、點值、上限、特殊期間)
  Product-->>Rewards: 折抵參數
  Rewards->>Rewards: 檢核點數餘額與效期
  alt 點數不足且設定為拒絕
    Rewards-->>GW: 422 點數不足(回覆原因碼)
  else 點數足夠或設定為部分折抵
    Rewards->>Rewards: 折抵計算(先到期先用)
    Rewards->>Rewards: 扣點並寫入點數帳
    Rewards->>Authz: 取得授權(折抵後之實付金額)
    alt 授權被拒
      Authz-->>Rewards: 拒絕
      Rewards->>Rewards: 回滾扣點(不扣點)
      Rewards-->>GW: 422 授權被拒
    else 授權核准
      Authz-->>Rewards: 核准
      Rewards->>Posting: 產生點數帳務(點數帳/商店帳/發卡帳)
      Posting-->>Rewards: 帳務完成
      Rewards->>Outbox: 寫入 rewards.points.redeemed.v1
      Rewards-->>GW: 201 兌換成功
      GW-->>Client: 201 兌換成功
    end
  end
  Note over Rewards,Authz: 授權被拒時不得扣點(POC-04 情境四)

14. 清算比對與撥款

sequenceDiagram
  autonumber
  participant Scheduler
  participant Clearing
  participant Posting
  participant GL
  participant Outbox

  Scheduler->>Clearing: POST /api/v1/clearing/runs
  Clearing->>Posting: 取得當日帳務交易
  Posting-->>Clearing: 交易明細
  Clearing->>Clearing: 依卡組織分派與幣別分組
  Clearing->>Clearing: 匯率轉換並產生本行清算檔
  Clearing->>Clearing: 與卡組織清算檔比對
  alt 差異筆數為零
    Clearing->>Clearing: 比對通過
  else 有差異
    Clearing->>Clearing: 產出差異明細
    Clearing->>Clearing: 差異分類(時間差/匯率差/實質差異)
    alt 時間差或匯率差
      Clearing->>Clearing: 自動調整後重新比對
    else 實質差異
      Clearing->>Clearing: 標記待人工查核
    end
  end
  Clearing->>Clearing: 調扣項目處理與撥款方向判定
  Clearing->>Posting: 產生會計分錄
  Posting-->>Clearing: 分錄完成
  Clearing->>GL: 傳送會計分錄
  GL-->>Clearing: 接收確認
  Clearing->>Outbox: 寫入 clearing.batch.matched.v1
  Clearing-->>Scheduler: 清算完成(差異為零)

15. 爭議帳款處理

sequenceDiagram
  autonumber
  participant Client
  participant GW
  participant Dispute
  participant Posting
  participant Clearing
  participant Notif
  participant Outbox

  Client->>GW: POST /api/v1/disputes
  GW->>Dispute: 轉發
  Dispute->>Dispute: 案件建檔與類型分流
  Dispute->>Clearing: 提出調單請求
  Clearing-->>Dispute: 調單受理
  alt 證據完整
    Dispute->>Dispute: 依卡組織規則裁決
  else 證據不完整
    Dispute->>Dispute: 要求補充資料
  end
  alt 需仲裁
    Dispute->>Clearing: 提交卡組織仲裁
    Clearing-->>Dispute: 仲裁結果
  end
  Dispute->>Posting: 帳務調整(暫付或扣回)
  Posting-->>Dispute: 調整完成
  Dispute->>Notif: 結案通知持卡人
  Notif-->>Dispute: 已發送
  Dispute->>Outbox: 寫入 dispute.case.closed.v1
  Dispute-->>GW: 200 結案
  GW-->>Client: 200 結案

16. Stand-in 代授權

sequenceDiagram
  autonumber
  participant Org
  participant GW
  participant Authz
  participant Standin
  participant Limit
  participant Queue
  participant Outbox

  Org->>GW: 授權請求
  GW->>Authz: 轉發
  Authz->>Authz: 偵測發卡主機狀態
  alt 發卡主機可用
    Authz->>Authz: 正常授權流程
  else 發卡主機不可用
    Authz->>Standin: 啟動代授權判斷
    Standin->>Standin: 檢核代授權限額與次數
    alt 在限額內
      Standin->>Limit: 以代授權額度佔用
      Limit-->>Standin: 佔用完成
      Standin->>Outbox: 寫入 authorization.authorization.approved.v1(標記 STANDIN)
      Standin-->>Authz: 代授權核准
      Standin->>Queue: 寫入補正佇列
    else 超出限額
      Standin-->>Authz: 拒絕(主機無回應)
    end
    Authz-->>GW: 授權回應
  end
  GW-->>Org: 授權回應
  Note over Standin,Queue: 主機恢復後須自補正佇列逐筆補正,拒絕者產生追償紀錄

17. 讀寫分離同步與補償

資料庫對應(v1.1):本文件各情境中之「寫入庫」= Oracle(權威 OLTP),
「讀取庫」= PostgreSQL(CQRS 讀模型 proj)。Outbox 位於 Oracle CC_PLT,
與服務自身 schema 同庫同交易。詳見 SAD-003 §3 與 CSP-006 §2.4。

sequenceDiagram
  autonumber
  participant Client
  participant Authz
  participant Limit
  participant WDB as 寫入庫(Oracle)
  participant Outbox
  participant Kafka
  participant Projector as 投影器
  participant RDB as 讀取庫(PostgreSQL)

  Client->>Authz: 授權請求
  Authz->>Limit: 佔用額度
  Limit->>WDB: 更新可用額度(樂觀鎖)
  Limit->>Outbox: 寫入 limit.hold.created.v1(同一交易)
  Limit->>WDB: 交易提交
  Limit-->>Authz: 佔用完成
  Authz-->>Client: 授權回應
  Note over WDB,Outbox: 資料與事件同時成立,不可分離
  Outbox->>Kafka: 發布事件(至少一次)
  alt Kafka 至讀取庫連線正常
    Kafka->>Projector: 消費事件
    Projector->>RDB: 更新查詢視圖(冪等)
  else 連線中斷
    Note over Kafka,RDB: 事件保留於 Kafka,恢復後續傳
  end
  Client->>RDB: GET /api/v1/accounts/{id}/balances
  RDB-->>Client: 餘額與明細(依交易順序)
  Note over Limit,RDB: 端到端同步延遲須 ≤ 1 秒,且 AP log、Kafka log、Listener log 可依 trace_id 串接(POC-14)

18. 情境與測試案例對照

# 情境 測試案例 驗收標準
3 授權核准 UT-AUTH-001 授權成功、額度正確扣減
3 授權核准(併發) PT-AUTH-001 1,000 TPS、無超額
4 授權分流 UT-AUTH-060 三條路徑皆有 LOG 佐證
5 請款入帳 UT-POST-001 分欄位正確、佔用釋放
5 重複入帳防範 UT-POST-040 併發 200 筆僅 1 筆成功
6 額度調整 UT-LIM-001 權限上限正確、同步 ≤ 1 秒
7 繳款即時恢復 UT-PAY-040 恢復 ≤ 1 秒、金額正確
8 三日重新佔額 UT-PAY-041 三日後回復原額度
9 帳單批次 UT-STM-001 1 小時內完成、可續跑
10 快發快綁 UT-CARD-020 CVV2 不落地、綁卡成功
11 錯帳沖正 UT-POST-060 成對產生、餘額正確
12 分期建立 UT-INS-001 首期與每期金額正確
13 點數兌換 UT-RWD-002 授權被拒不扣點
14 清算比對 UT-CLR-001 差異為零
15 爭議處理 UT-DSP-001 全程留痕、帳務調整正確
16 Stand-in UT-AUTH-080 限額內代授權、可補正
17 讀寫分離 UT-CQRS-001 ≤ 1 秒、鏈路可追蹤

19. 修訂記錄

版本 日期 修訂者 說明
1.0 2026-09-17 SD / SA 初版
1.1 2026-09-18 SD / SA §17 讀寫分離情境之參與者標籤由泛稱「寫入庫/讀取庫」明確化為「寫入庫(Oracle)/讀取庫(PostgreSQL)」,並加註 Outbox 位於 Oracle CC_PLT。本文件其餘 17 個情境之序圖未變——因該等圖僅描述服務間互動與事件流,不含資料庫方言(經全文檢核,無 SQL/DDL/方言用語)
(8-8/67)