通道執行手冊
本頁說明
講什麼:每種出金通道從 Remittance 之後到銀行確認的完整技術執行過程 適合誰:需要理解"錢是怎麼從系統到銀行"的產品經理,以及評估通道改造影響的人 前置閱讀:出金生命週期預計閱讀:5 分鐘 負責人:出金產品經理
核心要點:所有出金通道最終通過 SBA 編排執行。BST 通道全自動(秒~分鐘級到賬),非 BST 通道需運營在銀行網銀手動操作後確認完成。
SBA 編排:資金的中樞調度
所有出金通道最終都通過 SBA(Server Bank Account) 執行。SBA 是內部資金編排系統——負責凍結、扣款、轉賬指令的編排和狀態追蹤。
SBA Procedure 狀態機
每筆出金在 SBA 中對應一個 Procedure(編排流程):
SBA 子狀態(ext_status)
主狀態只有 5 個,但子狀態才是精確追蹤進度的關鍵。以下列出最常用的子狀態,完整列表見 出金數據字典 § SBA 子狀態。
| 主狀態 | 子狀態 | PM 視角 |
|---|---|---|
| new | waiting | 用戶此時還可以在 App 撤回出金 |
| new | manual_confirm | 需要運營在 CRM 確認 |
| pending | deduct_done | 錢已扣,等待發起轉賬 |
| pending | transfer_auto | BST:系統正在向銀行發指令 |
| pending | transfer_manual | 非 BST:等運營在銀行網銀操作 |
| pending | transfer_done | 銀行確認收到指令 |
| pending | transfer_reject | 銀行拒絕了出金指令 |
| end_ok | transfer_done | 出金完成 |
用戶可取消的窗口
只有 ext_status = waiting 時用戶才能在 App 撤回出金。一旦進入 deduct_done,資金已扣除,用戶無法自行取消——只能由運營發起沖正。
如果需求變更:擴展 SBA 子狀態
代碼位置:withdraw/src/app/Business/SOA/Srpc/WithdrawRPC.php 中定義了所有 EXT_STATUS_* 常量
子狀態是 SBA(Python 服務)和出金服務(PHP)之間的協議。修改子狀態需要兩端同步。
BST 銀證通道
BST 是唯一走全自動路徑的通道。
銀證授權前提
用戶必須先完成銀證授權(Mandate) 才能使用 BST:
| 銀行 | 授權模型 | 特點 |
|---|---|---|
| 招行/民生 | 傳統銀證簽約 | 只有"已簽約/未簽約"兩個狀態 |
| 天星 | Mandate 授權 | 6 個狀態;一次授權綁定 3 個市場(HK/US/HKCC) |
授權狀態必須為 OPEN 才能出入金。Confirm 步驟會校驗。
執行方式
| 銀行 | 服務 | 協議 | 結果獲取 |
|---|---|---|---|
| 招行 | cmb_stock_trans | Socket 二進制 | 實時推送 |
| 民生 | ms_stock_bank_transaction | Socket 二進制 | 實時推送 |
| 天星 | Airstar BST API | REST + JSON | 輪詢 |
BST 出金遵循凍結-轉賬-釋放三步:
- SBA 凍結用戶可用餘額中等額資金
- 向銀行發送出金指令
- 收到結果後,成功則扣款釋放凍結,失敗則回滾釋放
結果獲取方式
招行/民生和天星獲取銀行結果的方式完全不同:
招行/民生:通過 Socket 雙向鏈路實時推送結果,通常秒級完成。超時(回調碼 -5)時自動切換備用 exit_server 重試。
天星:通過 REST API 分兩階段輪詢獲取結果:
| 階段 | 事件 | 策略 | 累計耗時 |
|---|---|---|---|
| 快速輪詢 | AsbBstTransfer | 每 5 秒查詢,最多 10 次 | ~50 秒 |
| 兜底同步 | SyncAsbBstWithdraw | 2 小時內持續同步未完成指令 | 最長 2 小時 |
| 超時 | — | 標記異常,需運營人工查詢天星 API | — |
exit_server 是什麼
exit_server 是招行/民生 BST 的 Socket 通信地址。每家銀行配置了主備兩個地址,主地址超時時系統自動切換到備用地址重試。
餘額扣減
Remittance 執行時首先調用 autoOut() 扣減 auto_settings 表中的出金餘額:
- 低於
alarm_amount→ 發飛書告警 - 低於
stop_amount→ 自動關閉該幣種自動出金,後續全部降級人工
扣減發生在銀行轉賬之前——即使銀行拒絕,餘額已扣。需運營手動恢復。
BST 異常處理
| 異常 | 觸發 | 系統行為 | 運營操作 |
|---|---|---|---|
| 招行/民生超時(-5) | Socket 超時 | 切換備用 exit_server 重試 | 通常不需干預 |
| 招行/民生拒絕(-6) | 銀行拒絕 | 標記失敗 | 聯繫銀行確認原因 |
| 天星輪詢超時 | 10 次輪詢後仍 PENDING | 進入 2 小時兜底同步 | 等待,關注告警 |
| 天星同步超時 | 2 小時後仍 PENDING | 標記異常 | 人工查詢天星 API |
| 天星指令失敗 | 返回 FAILED | 釋放凍結資金 | 查看 140630xxx 錯誤碼 |
| 授權異常 | Mandate 非 OPEN | Confirm 步驟阻止推進 | 引導用戶重新授權 |
網銀通道(匯豐 / 恒生)
運營通過銀行企業網銀轉賬,CRM 確認完成。
eDDI ≠ 出金
eDDA/eDDI 是入金協議(代扣入金)。匯豐/恒生的出金走企業網銀,不走 eDDI。
流程:
- Confirm 步驟調用
startTransfer()→ SBA 返回transfer_manual - 運營在 CRM 看到"待匯款"任務
- 運營登錄銀行企業網銀操作轉賬
- 轉賬成功後在 CRM Remittance 步驟點擊確認
- Task → DONE
FPS 通道
中銀 / 渣打 FPS
標準半自動流程,與網銀通道類似——運營觸發後 CRM 確認。
FPS 限額:HKD / CNH 金額 < 100 萬才走 FPS。≥ 100 萬升級為 CHATS/RTGS。
收款人名要求:FPS 通道必須使用全名(與 CHATS/TT 可用簡稱不同)。
廣發 FPS(批量提交 + 異步輪詢)
廣發 FPS 是半自動通道中最接近全自動的——有 API 接口,但需運營觸發:
輪詢間隔(遞增):
| 次數範圍 | 間隔 |
|---|---|
| 1~100 | 10 秒 |
| 101~200 | 20 秒 |
| 201~300 | 30 秒 |
| 301~1000 | 40 秒 |
最長輪詢可達數小時。數據存儲在 task_cgb_fps 表。
如果需求變更:接入新的 FPS 通道
- 創建 Go 服務對接銀行 FPS API
- 在 PHP 新建
XxxFpsBiz.php(參考CgbFpsBiz.php) - 新建輪詢事件
SyncXxxFpsResult - 在
Method.php添加通道常量 - 新建
task_xxx_fps表存儲 API 狀態
傳統通道
CHATS/RTGS(文件導出)
通過香港銀行間清算系統出金,運營導出文件後上傳銀行系統。
觸發條件:
- 虛擬銀行 + USD 出金
- 虛擬銀行 + HKD/CNH 金額 ≥ 100 萬
- 非 BST 銀行 + FPS 不可用時的 fall-through
費用:USD $8 / HKD $25 / CNY $25(用戶確認出金時彈窗提示,需用戶明確同意)。
流程:
- 運營在 CRM 選擇待匯款任務
- 系統生成 RTGS/CHATS 格式文件
- 運營上傳文件到銀行系統(線下操作)
- 銀行處理完成後 CRM 確認
文件注意事項:
- 收款人名:可用簡稱
FUTU SECURITIES INTL (HK) LTD(不需要全名) - 收款人姓名限制 140 字符(超過截斷並警告)
- 金額單位為分(乘以 100)
- 姓名從
nick_list表獲取,優先英文名
如果需求變更:調整文件格式
代碼位置:withdraw/src/app/Business/Withdraw/ExportRTGSCHATSFile.php
文件格式是銀行要求的固定格式,修改需和銀行確認。
跨境電匯(tele_transfer / ewb)
純人工通道。運營在銀行網銀操作跨境匯款,完成後 CRM 確認。setTransferDone() 時傳 method = null(由 SBA 按配置路由)。
NSS 名單篩查:跨境電匯在執行前需通過 NSS(Name Screening Service)檢查收款人姓名,確認不在制裁名單上。NSS 不通過的出金需人工升級,運營聯繫合規團隊判斷。
收款人名規則:跨境電匯/TT 可用簡稱 FUTU SECURITIES INTL (HK) LTD。
支票(check)
最傳統的通道,到賬最慢。
操作流程:
- 運營根據出金任務信息開具支票
- 需 2 位授權人簽名(雙簽制度)
- 每日下午由專人送到銀行存入
- 記錄支票編號(
check_extra表) - CRM 確認完成
適用場景:當同行轉賬、FPS、CHATS/RTGS 均不可用時的最終 fall-through 方案。
通道對比總結
| 維度 | BST 銀證 | 廣發 FPS | 其他 FPS/網銀 | 傳統通道 |
|---|---|---|---|---|
| startTransfer 時機 | Remittance | Confirm | Confirm | Confirm |
| SBA ext_status | transfer_auto | transfer_manual | transfer_manual | transfer_manual |
| 結果獲取 | 推送(招行/民生) / 輪詢(天星) | 輪詢(1000次) | CRM 手動確認 | CRM 手動確認 |
| 完成觸發 | 自動完成 | 輪詢自動完成 | 運營確認 | 運營確認 |
| 最大等待 | 秒級(招行/民生) / ~2小時(天星) | 數小時 | 取決於運營 | 取決於運營 |
| 需要運營 | 否(全自動) | 觸發提交 | 銀行操作+確認 | 銀行操作+確認 |
如果需求變更:讓某個手工通道變為半自動
核心改造:把 CRM 手動確認替換為 API 輪詢。參考廣發 FPS 的模式:
- 對接銀行 API(提交轉賬 + 查詢狀態)
- 新建輪詢隊列事件
- Remittance 步驟中針對該通道走異步路徑
startTransfer()時機和 SBA ext_status 不需要改
通道方法分組
代碼中的方法分組決定了 CRM 的展示和操作方式:
| 分組 | 包含的通道 | 用途 |
|---|---|---|
| allEBankMethod() | manual, boc, hase, hsbc, boc_fps, cgb_fps_api, chats_rtgs, sc | 網銀類(8 種) |
| allTeleMethod() | tele_transfer, ewb | 跨境電匯類(2 種) |
| allSetMethod() | 網銀類 + check(9 種) | Confirm 步驟可選通道 |
| allTabMethod() | allSetMethod + ewb + tele_transfer(11 種) | CRM Tab 頁 |
| all() | 全部 12 種 | 所有出金通道 |
為什麼 auto_bs 不在 allSetMethod 裡
BST 是系統自動路由的,不需要運營手動選擇。只有 method = null 時運營才需要從 allSetMethod 中選通道。
常見誤解
| 誤解 | 事實 |
|---|---|
| "SBA 是一家銀行" | 不是。SBA(Server Bank Account)是內部資金編排系統,負責凍結、扣款、轉賬指令的編排和狀態追蹤。所有出金通道最終都通過 SBA 執行 |
| "所有 BST 銀行用同樣的技術" | 不是。招行/民生走 Socket 雙向鏈路(SM2 加密,實時推送結果),天星走 REST API(JSON,輪詢獲取結果)。超時處理、輪詢策略完全不同 |
| "匯豐/恒生出金走 eDDA" | 不走。eDDA/eDDI 僅用於入金代扣。匯豐/恒生的出金走企業網銀轉賬,與 eDDA 無關 |
| "FPS 出金是全自動的" | 不是。廣發 FPS 有 API 接口但仍需運營觸發提交,中銀/渣打 FPS 完全靠運營手動操作。只有 BST 是全自動 |
讀完之後
| 我想... | 去看 |
|---|---|
| 瞭解審批到執行的完整流程 | 出金生命週期 |
| 看自動出金條件和限額規則 | 出金規則手冊 |
| 排查某通道的異常 | 出金排障 |
| 推動通道相關的需求變更 | 出金變更指南 |
| 查 SBA 狀態碼、回調碼 | 出金數據字典 |
| 深入瞭解三家 BST 銀行 | 內銀系 BST 總覽 |