金融科技工程手冊 – 建構金錢關鍵系統的完整指南
金融科技工程手冊 – 建構金錢關鍵系統的完整指南
TL;DR
金融科技工程手冊將構建以金錢為主要資料模型的軟體所需的不可變、可稽核、且不依賴信任的模式加以編纂。 它涵蓋從金錢表示、帳本設計、外部整合、存取控制到測試的所有面向,皆與三大指導原則相結合。
誰該使用本手冊?
- 新進金融科技員工 – 針對領域特定模式與詞彙的速成課程。
- 有經驗的金融科技工程師 – 解決具體問題的參考資料,也是跨團隊討論的共同語言。
- 非金融科技領域的工程師 – 為何金錢系統與一般 Web 應用不同的入門說明。
歡迎貢獻;本文件預計持續演進。
核心原則
| 原則 | 所強制的內容 | 常見機制 |
|---|---|---|
| 不允許虛構資料 | 金錢不能任意產生或消失。 | 冪等鍵、去重、雙式簿記、保留金。 |
| 不允許遺失資料 | 每筆金錢事件必須被持久化且可追蹤。 | 全精度型別、至少一次投遞、事件溯源、不可變稽核追蹤。 |
| 不信任 | 不假設外部提供者或內部元件可靠。 | Webhook 簽章、結構驗證、跨來源對帳、明確的失敗處理。 |
表示金錢
精度處理
- 避免使用浮點數 – 會產生非決定性的四捨五入。
- 使用整數次要單位 來表示法幣(例如將 €12.34 儲存為
1234)。加密貨幣常需任意寬度的整數,因為代幣小數位數可高達 18 位。 - 任意精度函式庫(
BigDecimal等)非常適合用於外匯或定價等中間計算。 - 有理數 能保證零精度損失,但較慢且較難序列化。
關鍵規則: 以最小單位的整數儲存金額,計算時使用高精度型別;序列化時以字串或整數呈現,絕不要使用 JSON 數字。
四捨五入策略
- 明確四捨五入 – 每一次除法、轉換、手續費或精度變更都必須呼叫四捨五入步驟。
- 依業務決定方向 – 為避免超支而向下取整,或使用銀行家捨入以求統計公平;選擇會影響稅務/法律結果。
- 盡可能延後四捨五入 – 在持久化或呈現給使用者前保持完整精度。
- 處理餘額 – 分割金額時,追蹤四捨五入的剩餘,以免產生餘額漂移。
關鍵規則: 四捨五入絕不能創造或銷毀金錢;餘額必須放入專門帳戶。
幣別處理
- 將金額與幣別一起封裝於
Money型別。 - 禁止在不同幣別之間直接做算術運算;必須以受控匯率明確轉換。
- 在系統邊界驗證幣別代碼,使用精選清單。
- 對於加密貨幣,使用
(network, contract address)來識別資產,而非 ISO 4217 代碼。
外匯匯率
- 匯率是 方向性的 – EUR/USD ≠ USD/EUR;買賣價差意味著倒數並非簡單的倒數。
- 時間戳記很重要 – 實時估值使用即時匯率,稅務或報表則使用價值日匯率。
- 區分 交易匯率(實際兌換時使用)與 參考匯率(中間市場或央行匯率,用於估值)。
- 沒有單一的權威來源;必須儲存來源識別碼以供稽核。
記錄金錢:帳本
雙式簿記
- 每筆分錄將相同金額從 貸方 帳戶移至 借方 帳戶,保證帳本永遠平衡。
- 餘額是衍生值,永遠不直接儲存。
- 帳戶類型(資產、負債、權益、收入、費用)強制會計等式
assets = liabilities + equity。 - 更正透過沖銷分錄完成;原始列保持不可變。
時間維度
- 價值時間 – 經濟事件發生的時間。
- 入帳時間 – 事件被系統記錄的時間。
- 結算時間 – 實際資金轉移的時間(通常表示為 T+X)。
- 必須同時記錄三個時間戳記;合併會失去可重建性。
稽核與稽核追蹤
- 捕捉每一次變更的 何時、何事、誰/什麼、為何——不僅是餘額更新,還包括設定變更、權限更新與規則評估。
- 事件溯源 把事件日誌視為真相來源,使稽核追蹤成為主要資料。
- 不可變性 – 只允許追加寫入、執行時檢查與防篡改機制(雜湊鏈)防止靜默編輯。
- 撤銷 vs. 更正 – 撤銷會抵消原始分錄;更正則貼上淨差額,保留歷史。
執行金錢流
不變式
- 透過 建構時(型別安全建構子、資料庫限制)、執行時(斷言、屬性測試)以及 事後(對帳工作)來強制關鍵屬性。
資金保留
- 在呼叫外部服務前先保留資金;區分 總額 與 可用額(
available = total – reserved)。 - 保留必須 線性化,且最終一定會被釋放或結算,以避免資金死鎖。
透支處理
- 區分 有意 透支(信用產品)與因外部不匹配而產生的 無意 透支。
- 不要把「餘額 ≥ 0」寫成硬性型別限制;應以不變式方式強制,並明確處理違反情況。
冪等性
- 使用 明確的冪等鍵,範圍限定於操作與客戶端。
- 把重複的投遞視為單一邏輯效果;重試必須合併為一次結果。
- 冪等性需同時在系統的 入站 與 出站 兩側實施。
完全可恢復性
- 將長時間執行的流程建模為 耐久的狀態機;每一步完成後即持久化進度。
- 外部驅動程式必須能偵測未完成的流程並恢復它們。
- 每一步必須 冪等;外部效應不可恢復,故只能向前重試或發出補償動作(Saga 模式)。
外部世界
消費 API
- 積極驗證 回應;對意外的結構變更要大聲失敗。
- 預期 所有呼叫都有可能失敗 – 實作重試、逾時與指數退避。
- 持久化每一次請求與回應 – 這是稽核追蹤的一部份,也能支援重新處理。
- 考慮 提供者冗餘 以保護關鍵路徑,但要留意隨之而來的複雜度。
處理 Webhook
- 不要信任順序、有效性或傳遞保證。
- 儲存 原始 payload,並驗證簽章(HMAC 或非對稱加密)。
- 把 webhook 當作 觸發,再透過提供者的 API 取得權威狀態。
- 快速回應(2xx)並非同步處理;確保處理具冪等性。
可靠通知(Outbox / CDC)
- 與狀態變更 交易性 發布事件(outbox table)或使用 變更資料捕捉 串流已提交的列。
- 投遞是 至少一次;消費者必須使用穩定的事件 ID 去重。
對帳
- 定期(每小時、每日等)將內部記錄與外部來源比對。
- 以提供者產生的 ID 為主鍵;若無則使用啟發式(金額 + 時間戳記)。
- 透過 更正分錄 或重新處理解決不符,絕不直接覆寫歷史資料。
控制與存取
職務分離與四眼原則
- 任何可能移動或錯報資金的操作(大額提款、帳本更正、費率變更)都必須有第二位審批者。
- 記錄 誰提出 與 誰批准;批准必須是不同的執行者。
存取控制
- 透過基於角色的存取控制(RBAC)實施 最小權限。
- 每一次授權/撤銷都要記錄,使用與金錢事件相同的稽核欄位。
- 執行 定期重新認證,以捕捉過時的權限。
變更追蹤(SDLC)
- 把 原始碼控制歷史 視為程式碼變更的權威記錄。
- 強制必須的程式碼審查、受保護分支與簽名提交。
- 部署必須可追溯(誰、何時、哪個版本),以便在事件發生時追溯至負責的變更。
測試金錢關鍵系統
- 屬性測試 – 針對任意輸入斷言不變式(例如總借方 = 總貸方)。
- 每一步後的不變式檢查 – 自動驗證帳務規則在產生的操作序列中始終成立。
- 生成式冪等測試 – 重複每個操作並確認不會產生雙重計數。
- 崩潰與恢復注入 – 在步驟之間模擬失敗,以驗證可恢復性。
- 往返測試 – 序列化/反序列化金錢型別,確保無精度損失。
- 金色測試 – 鎖定複雜計算(手續費、對帳單),偵測回歸。
- 向後相容測試 – 確認目前程式碼能讀取歷史事件格式。
- 在正式環境測試 – 使用真實金錢執行金絲雀或合成交易,並加上標籤以便之後撤銷;絕不可繞過帳本。
附錄
附錄 A – 領域詞彙表
列出金融科技關鍵術語(帳本、IOU、次要單位、買賣價差、T+X 等)並提供手冊相關章節的連結。
附錄 B – 端對端流程範例
- 加密貨幣提領 – 示範冪等性、保留、合規檢查、鏈上廣播、最終性等待、帳本入帳與對帳。
- 卡片入金 – 展示 webhook 處理、清算帳戶、結算延遲與拒付撤銷。
- 應用內兌換加回饋 – 突顯幣別隔離、精度保留、邊界四捨五入,以及同時記錄價差收入與促銷費用的雙式分錄。
結論
金融科技工程手冊提供一套 自足、以原則為導向的藍圖,用於建構金錢不可被虛構、遺失或隱性信任的系統。遵循本文所述的模式——精確的表示、不可變的雙式帳本、明確的不變式、健全的外部整合、嚴格的存取控制與徹底的測試——工程師即可交付能夠通過稽核、符合法規審查,且能在分散式系統必然失敗的情況下仍然可靠的金融產品。