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/方言用語) |