招商銀行 CMB Pull 模式
本頁說明
講什麼:招商銀行銀證轉賬(BST)渠道側 Socket 協議規範 + moomoo 側適配邏輯 適合誰:PM 了解對接細節 / 開發定位代碼 / 運營理解銀行特性 前置閱讀:銀行能力矩陣 · BST 銀證轉賬預計閱讀:8 分鐘 負責人:出入金產品團隊
核心要點:招行通過 SM2 加密的 Socket 雙向鏈路實現秒級銀證轉賬,是三家 BST 銀行中協議最複雜但響應最快的。
能力總覽
| 能力 | 支持情況 | 協議/通道 | 核心服務 |
|---|---|---|---|
| 入金(BST 銀證轉賬) | ✅ | 二進制 Socket 雙向鏈路 | cmb_stock_trans Entry Server |
| 出金(BST 銀證自動) | ✅ | 二進制 Socket 雙向鏈路 | cmb_stock_trans Exit Server |
| SM2 國密加密 | ✅ | SM2 簽名 + 加密 | 內置加密模組 |
| eDDA/eDDI | ❌ | — | — |
| FPS | ❌ | — | — |
招商銀行是 moomoo 的核心 BST(銀證轉賬)渠道之一,通過專線 Socket 雙向持久連接實現實時入金通知和出金指令下發。支持 SM2 國密加密,保障資金指令的安全性。
核心參數速查
| 參數 | 值 | 說明 |
|---|---|---|
| IMPORT_BANK_ID | 7 | 系統內銀行標識 (CMBCCHINA) |
| TransType | 102 (BST) / 205 (普通) | 銀證轉賬 / 普通入金兩種類型 |
| AUTO_SETTING_ID | 2 | auto_settings 表中的限額配置 ID |
| 協議類型 | 二進制 Socket | 固定字節長度消息幀 |
| 加密方式 | SM2 國密算法 | 可選,默認 'N' 不加密 |
| 通信模式 | 雙向持久連接 | Entry Server + Exit Server |
渠道接口概覽
協議架構
| 維度 | 說明 |
|---|---|
| 協議類型 | 二進制 Socket(固定字節長度消息幀) |
| 加密方式 | SM2 國密算法(可選,默認 'N' 不加密) |
| 數據格式 | 二進制(固定長度字段,ASCII 編碼) |
| 通信模式 | 雙向持久連接(Entry Server 接收 + Exit Server 發送) |
| 心跳機制 | 0009/1009 和 0010/1010 雙向心跳保活 |
| 連接管理 | 斷連自動切換備用 Exit Server |
消息幀結構
每條 Socket 消息由固定格式的頭部 + 可變長度的業務數據組成:
| 部分 | 長度 | 格式 | 說明 |
|---|---|---|---|
| 加密類型 | 1 字節 | char | 'N' = 不加密,'Y' = SM2 加密 |
| 包總長度 | 2 字節 | little-endian uint16 | 整個消息幀的長度 |
| 簽名 | 64 字節 | binary | SM2 數字簽名(不加密時為空白填充) |
| 命令碼 | 4 字節 | ASCII | 如 "0001"、"4001" |
| TX 包長度 | 2 字節 | little-endian uint16 | 業務數據部分的長度 |
| 頭部合計 | 73 字節 | ||
| 業務數據 | 可變 | binary | 固定長度字段拼接 |
字節序注意
包長度字段使用 little-endian 字節序,開發時需注意編解碼方向。
渠道側接口詳情 — 完整命令碼表
登錄與認證
| 命令碼 | 方向 | 消息名 | 用途 |
|---|---|---|---|
| 0001 | 券商→銀行 | BrokerageLoginToBankReq | 券商登錄銀行,建立 Entry 鏈路 |
| 1001 | 銀行→券商 | BrokerageLoginToBankRsp | 登錄響應,返回認證結果 |
| 0002 | 銀行→券商 | BankLoginToBrokerageReq | 銀行登錄券商,建立 Exit 鏈路 |
| 1002 | 券商→銀行 | BankLoginToBrokerageRsp | 銀行登錄響應 |
| 0003 | 券商→銀行 | BrokerageLoginoutReq | 券商主動登出 |
| 1003 | 銀行→券商 | BrokerageLoginoutRsp | 登出響應確認 |
密碼與配置
| 命令碼 | 方向 | 消息名 | 用途 |
|---|---|---|---|
| 0004/1004 | 雙向 | ModifyPwd | 修改通信密碼 |
| 0005/1005 | 雙向 | ChangeDate | 修改對賬日期 |
心跳保活
| 命令碼 | 方向 | 消息名 | 用途 |
|---|---|---|---|
| 0009/1009 | 券商→銀行 | Keepalive | 券商側心跳(moomoo 發起) |
| 0010/1010 | 銀行→券商 | Keepalive | 銀行側心跳(招行發起) |
雙向心跳確保連接存活。任一方超時未收到心跳即判定連接斷開,觸發重連。
客戶管理
| 命令碼 | 方向 | 消息名 | 用途 |
|---|---|---|---|
| 2001/3001 | 銀行→券商 | GetCustmorInfo | 銀行查詢客戶在券商的信息 |
| 2002/3002 | 券商→銀行 | NotifyCustmorResult | 通知客戶驗證結果(開戶/驗證) |
| 2003/3003 | 銀行→券商 | Cancel | 取消客戶的銀證授權關係 |
資金轉賬(核心)
| 命令碼 | 方向 | 消息名 | 用途 |
|---|---|---|---|
| 4001/5001 | 銀行→券商 | BankMarginIn | ⭐⭐⭐ 入金通知 — 銀行告知券商有客戶轉入資金 |
| 4002/5002 | 券商→銀行 | BrokerageMarginOut | ⭐⭐⭐ 出金指令 — 券商指示銀行將資金轉出到客戶帳戶 |
| 4003/5003 | 銀行→券商 | BankMarginOut | ⭐⭐⭐ 出金結果通知 — 銀行告知出金處理結果 |
| 4004/5004 | 券商→銀行 | BankMarginOutReject | ⭐⭐ 拒絕出金 — 券商拒絕銀行側發起的出金請求 |
對賬
| 命令碼 | 方向 | 消息名 | 用途 |
|---|---|---|---|
| 6001/7001 | 雙向 | MarginCheck | 對賬請求發起 |
| 6011/7011 | 銀行→券商 | BankMarginInList | 入金對賬清單 |
| 6013/7013 | 銀行→券商 | BankNewCustmoerList | 新開戶客戶清單 |
| 6014/7014 | 銀行→券商 | BankCancelList | 取消授權客戶清單 |
| 6015/7015 | 銀行→券商 | BankMarginOutList | 出金對賬清單 |
| 6003/7003 | 券商→銀行 | NewCustmoerCheck | 新客戶對賬確認 |
| 6004/7004 | 券商→銀行 | CancelCheck | 取消授權對賬確認 |
| 6005/7005 | 券商→銀行 | MarginOutCheck | 出金對賬確認 |
核心接口字段詳情
4001 BankMarginInReq(入金通知)
銀行通知券商有一筆入金到賬,是 BST 入金的核心消息。
| 字段 | 長度 | 類型 | 描述 |
|---|---|---|---|
| m_brokerage_custmor_id | 20B | string | 券商客戶 ID。取值 moomoo UID |
| m_bank_custmor_id | 16B | string | 銀行客戶 ID。取值 銀行卡號 |
| m_currency | 3B | string | 幣種。取值 HKD / USD / CNH |
| m_amount | 20B | string | 金額。如 "50000.00" |
| m_tx_date | 8B | string | 交易日期。格式 YYYYMMDD |
| m_tx_time | 6B | string | 交易時間。格式 HHMMSS |
| m_tx_seq | 16B | string | 交易序號。唯一標識(去重依據) |
| m_reconciliation_date | 8B | string | 對賬日期。格式 YYYYMMDD |
字段編碼說明
所有字段為固定長度 ASCII 字符串,不足部分右補空格。金額字段包含小數點,如 "50000.00" 後補空格至 20 字節。幣種嚴格 3 字節:HKD、USD、CNH。
4002 BrokerageMarginOutReq(出金指令)
券商向銀行發起出金指令,將客戶資金從證券帳戶轉回銀行帳戶。
| 字段 | 長度 | 類型 | 描述 |
|---|---|---|---|
| m_brokerage_custmor_id | 20B | string | 券商客戶 ID。moomoo UID |
| m_bank_custmor_id | 16B | string | 銀行客戶 ID。銀行卡號 |
| m_bank_custmor_name | 20B | string | 銀行客戶姓名。用於銀行側驗證 |
| m_currency | 3B | string | 幣種。HKD / USD / CNH |
| m_amount | 20B | string | 金額。出金金額 |
| m_tx_date | 8B | string | 交易日期。格式 YYYYMMDD |
| m_tx_time | 6B | string | 交易時間。格式 HHMMSS |
| m_tx_seq | 16B | string | 交易序號。唯一標識 |
| m_reconciliation_date | 8B | string | 對賬日期。格式 YYYYMMDD |
通用響應字段
| 字段 | 長度 | 類型 | 描述 |
|---|---|---|---|
| m_rsp_code | 4B | string | 響應碼,"0000" = 成功 |
moomoo 側適配
Entry/Exit Server 雙向架構
招行 BST 採用雙向持久連接架構,moomoo 側部署兩個 Server 分別處理入站和出站消息:
| Server | 進程名 | 職責 | 連接方向 |
|---|---|---|---|
| Entry Server | entrance_business | 接收銀行發來的消息(入金通知、對賬清單等)→ 轉發給 CRM | 銀行 → moomoo |
| Exit Server | exit_business | 接收 CRM 的出金指令 → 發送給銀行 | moomoo → 銀行 |
斷連處理:Exit Server 支持備用地址。當主連接斷開時,自動切換到備用 exit_server 地址,確保出金指令不中斷。
SM2 國密加密流程
招行 BST 支持 SM2 國密算法對消息進行簽名和加密,保障資金指令的安全性。
加密配置
- 加密類型字段 = 'Y' 時啟用 SM2
- 默認為 'N'(不加密),可按需開啟
- 證書文件位於
cmb_stock_trans/conf/目錄下
入金:BST 實時入金
入金流程
BST 入金的最大優勢是實時性和確定性:銀行直接告知客戶 ID 和金額,無需像普通銀行轉賬那樣做模糊匹配。
出金:BST 自動出金 (auto_bs)
出金流程
處理時段
| 幣種 | 處理時段 | 說明 |
|---|---|---|
| HKD / USD | 交易日 08:40 ~ 15:59 | 全交易日可處理 |
| CNH | 交易日 08:40 ~ 10:59 | 僅上午,下午不可處理 |
| 保證金提取 | 交易日 08:40 ~ 10:59 | 與 CNH 同窗口 |
CNH 出金時段限制
CNH(離岸人民幣)的出金窗口僅到上午 10:59,遠短於 HKD/USD。運營和用戶需注意在此窗口內發起 CNH 出金,超時將延至下一個交易日處理。
CNH 出金限制
calcMethod() 方法中對 CNH 有額外限制:
- CNH + 非香港銀行 → method = null(不支持)
- 即 CNH 出金到大陸銀行卡 = 不支持
- CNH 僅支持出金到香港本地的招行帳戶
出金取消規則
| 場景 | 可否取消 | 條件 |
|---|---|---|
| 非交易時間(< 08:20 或 ≥ 16:00) | ✅ | 無條件可取消 |
| 交易日 08:20 ~ 16:00 | ✅ / ❌ | 距預定執行時間 ≥ 10 分鐘方可取消 |
| 非交易日 | ✅ | 無條件可取消 |
為什麼交易時段內有 10 分鐘限制? 出金指令一旦進入銀行處理佇列就無法撤回。10 分鐘的緩衝期確保取消請求能在銀行實際執行前到達。
回調結果碼
| result | 含義 | 系統處理 | 是否需人工 |
|---|---|---|---|
| 0 | 成功 | Task 狀態 → DONE | ❌ |
| -5 | 超時 | 自動切換備用 exit_server 重試 | ❌ |
| -6 | 銀行拒絕 | Task 狀態 → 異常 | ✅ 人工處理 |
超時重試機制
當收到 result = -5(超時)時:
- 記錄當前 exit_server 超時事件
- 切換到備用 exit_server 地址
- 使用相同的 m_tx_seq 重新發送出金指令
- 如果備用 exit_server 也超時,標記為異常,等待人工處理
出金限額配置
招行 BST 出金的限額通過 auto_settings 表配置(WHERE id = 2):
| 字段 | 含義 | 說明 |
|---|---|---|
| hk_max_amount | 單筆最大金額 | 超過則拒絕 |
| hk_alarm_amount | 告警金額 | 超過則觸發告警但不阻斷 |
| hk_stop_amount | 熔斷金額 | 超過則暫停自動出金 |
三級閾值邏輯:
- 金額 ≤ alarm_amount:正常自動處理
- alarm_amount < 金額 ≤ max_amount:自動處理 + 觸發告警通知
- 金額 > max_amount 或累計 > stop_amount:暫停自動出金,轉人工審批
異常場景與告警
Socket 斷連
| 告警項 | 級別 | 響應時限 | 說明 |
|---|---|---|---|
| Entry Server 斷連 | 嚴重 | 15 分鐘內 | 無法接收入金通知 |
| Exit Server 斷連 | 嚴重 | 15 分鐘內 | 無法發送出金指令 |
| 雙向心跳超時 | 警告 | 30 分鐘內 | 可能即將斷連 |
Socket 斷連是最嚴重的告警之一——斷連期間所有 BST 入金通知和出金指令都會中斷。系統會自動嘗試重連,但如果 15 分鐘內未恢復,需要開發人員介入排查。
常見異常處理
| 異常場景 | 表現 | 處理方式 |
|---|---|---|
| Socket 斷連 | 入金/出金中斷 | 自動重連;15 分鐘未恢復則人工介入 |
| SM2 簽名驗證失敗 | 消息被拒絕 | 檢查證書是否過期或被替換 |
| 出金超時 (result=-5) | 銀行無響應 | 自動切換備用 exit_server |
| 銀行拒絕 (result=-6) | 出金失敗 | 人工核實原因後重試或退款 |
| 對賬不平 | 入金/出金金額不一致 | 運營核查差異,聯繫招行對賬 |
| CNH 超時段出金 | 出金被拒 | 延至下一個交易日上午處理 |
雙方功能對應矩陣
| 功能 | 渠道側(招商銀行) | moomoo 側 | 說明 |
|---|---|---|---|
| 登錄認證 | 雙向握手 | Entry/Exit Server | 0001-1003,建立雙向鏈路 |
| 心跳保活 | 雙向心跳 | Entry/Exit Server | 0009-1010,每 30s 一次 |
| 入金通知 | 4001 BankMarginIn | Entry → CRM | m_brokerage_custmor_id 等,實時入金 |
| 出金指令 | 5002 接收執行 | CRM → Exit → 銀行 | m_amount / m_currency 等,自動出金 |
| 出金結果 | 4003 BankMarginOut | Entry → CRM | result 碼,回調通知 |
| 對賬 | 6xxx 系列 | Entry/Exit | 多種清單,每日對賬 |
| 加密 | SM2 驗簽解密 | SM2 簽名加密 | 消息頭 64B 簽名,可選 |
定時任務
| 任務 | 頻率 | 說明 |
|---|---|---|
| 心跳檢測 | 每 30 秒 | Entry/Exit Server 雙向心跳 |
| 斷連檢查 | 每 5 分鐘 | 檢查 Socket 連接狀態,異常則告警 |
| 對賬發起 | 每日收盤後 | 發起 6001 對賬請求 |
| 對賬核驗 | 每日 T+1 | 比對入金/出金/客戶清單 |
需求變更指引
| 變更需求 | 改動位置 | 說明 |
|---|---|---|
| 修改出金限額 | auto_settings WHERE id = 2 | 調整 max/alarm/stop 三級閾值 |
| 修改處理時段 | exit_business → 時段配置 | 調整各幣種的處理窗口 |
| 修改 CNH 限制 | calcMethod() → CNH 判斷邏輯 | 修改 CNH 出金的銀行/地區限制 |
| 修改取消規則 | 出金取消邏輯 → 時間判斷 | 調整 10 分鐘緩衝期 |
| 更換 SM2 證書 | cmb_stock_trans/conf/ | 替換公私鑰文件並重啟服務 |
| 調整心跳間隔 | cmb_stock_trans → keepalive 配置 | 修改心跳頻率 |
| 新增命令碼 | cmb_stock_trans/comm/pact.h | 協議定義文件 |
| 修改 Entry Server 邏輯 | cmb_stock_trans/entrance_business/ | 入站消息處理 |
| 修改 Exit Server 邏輯 | cmb_stock_trans/exit_business/ | 出站消息處理 |
| 調整備用 exit_server | Exit Server 配置 | 修改備用地址列表 |
代碼位置速查
| 模組 | 路徑 | 說明 |
|---|---|---|
| 協議定義 | cmb_stock_trans/comm/pact.h | 所有命令碼和消息結構定義 |
| Entry Server | cmb_stock_trans/entrance_business/ | 入站消息接收和轉發 |
| Exit Server | cmb_stock_trans/exit_business/ | 出站消息發送(出金指令) |
| SM2 加密 | cmb_stock_trans/ 內置模組 | 簽名 / 加密 / 解密 |
| 限額配置 | auto_settings 表 id = 2 | 數據庫配置 |
| 出金通道 | withdraw/.../Method.php → auto_bs | 出金方法註冊 |
與其他 BST 銀行的對比
| 維度 | 招商銀行 CMB | 民生銀行 | 天星銀行 |
|---|---|---|---|
| 協議 | 二進制 Socket | — | — |
| 加密 | SM2 國密 | — | — |
| 連接模式 | 雙向持久連接 | — | — |
| 入金 | ✅ 實時通知 | ✅ | ✅ |
| 出金 | ✅ auto_bs | ✅ | ✅ |
| CNH 支持 | ✅(僅上午) | — | — |
| 對賬 | 自動對賬 | — | — |
BST 的優勢
相比普通銀行轉賬入金需要模糊匹配,BST 銀證轉賬最大的優勢是確定性——銀行直接告知客戶 ID 和金額,無需匹配引擎介入,入金實時到賬。
常見客訴 Top 3
| # | 用戶反饋 | 原因 | 客服話術 |
|---|---|---|---|
| 1 | "BST 出金超時" | Socket 連接抖動,回調碼 -5 | "出金正在處理中,系統已自動重試,請稍候查看結果" |
| 2 | "BST 出金被拒" | 回調碼 -6,銀行側拒絕 | "銀行暫時無法處理您的出金,請稍後重試或聯繫客服" |
| 3 | "為什麼不能用招行出金" | 銀證授權未生效或已失效 | "請確認您的銀證授權狀態正常,如已過期請重新簽約" |
讀完之後
| 我想... | 去看 |
|---|---|
| 了解 BST 銀證轉賬的整體架構 | BST 銀證轉賬 |
| 看招行在各銀行中的位置 | 銀行能力矩陣 |
| 了解出金通道的執行細節 | 通道執行手冊 |
| 了解出金審批規則 | 出金規則與審批 |
| 查 TransType 和 Bank ID 對照 | 入金規則速查 |
| 查錯誤碼和狀態碼 | 統一錯誤碼中心 |
| 了解其他入金匹配邏輯 | 匹配與自動入賬 |