民生銀行 MS Pull 模式
本頁說明
講什麼:民生銀行銀證轉賬(BST)渠道側 Protobuf/SRPC 協議規範 + moomoo 側適配邏輯 適合誰:PM 了解對接細節 / 開發定位代碼 / 運營理解銀行特性 前置閱讀:內銀系 BST 總覽、銀行能力矩陣預計閱讀:8 分鐘 負責人:出入金產品團隊
核心要點:民生採用 Protobuf/SRPC 協議的 Socket 模式,與招行共用雙向鏈路架構但序列化方式不同。
能力總覽
| 能力 | 支持情況 | 協議/通道 | 核心服務 |
|---|---|---|---|
| BST 銀證入金 | ✅ | Protobuf/SRPC(SM2 國密加密) | ms_stock_bank_transaction |
| BST 銀證出金 | ✅ | auto_bs 銀證自動出金 | ms_stock_bank_transaction |
| eDDA 授權 | ❌ | — | — |
| eDDI 代扣 | ❌ | — | — |
| FPS | ❌ | — | — |
| 入金流水匹配 | ❌ | — | — |
民生銀行是 moomoo 接入的第二家 BST 銀行——與招行共同構成內銀系 BST 雙通道,但採用完全不同的協議棧(Protobuf/SRPC vs 二進制 Socket)。
核心標識
| 標識 | 值 | 說明 |
|---|---|---|
| IMPORT_BANK_ID | 13 | CMBC,系統內銀行唯一編號 |
| TransType | 101 (BST), 204 (普通) | 101 用於銀證轉賬,204 用於普通入金 |
| AUTO_SETTING_ID | 1 | 自動出金配置 ID |
| 服務名 | ms_stock_bank_transaction | 核心銀證服務 |
| 代碼目錄 | ms_sb_trans_python/ | 服務代碼根目錄 |
渠道接口概覽
| 維度 | 說明 |
|---|---|
| 協議類型 | Protobuf 序列化 + SRPC 框架 |
| 加密方式 | SM2 國密算法(國家商用密碼標準) |
| 數據格式 | Protobuf 二進制序列化(非 JSON/XML) |
| 通信模式 | RPC 請求-響應(同步調用) |
| 編碼 | GB18030(中文姓名等字段使用 bytes 類型) |
| 簽名算法 | SM2 國密簽名,確保數據不可篡改 |
與招行的協議區別
招行使用自定義二進制 Socket 協議,民生使用 Google Protobuf + 自研 SRPC 框架。兩者都走 SM2 加密,但序列化方式不同——招行是手工二進制編碼,民生是 Protobuf 自動序列化。Protobuf 方案在可維護性上更優。
渠道側接口詳情 — 9 個 RPC 方法
民生銀行提供 9 個 RPC 接口,通過 Request ID 標識不同的業務操作:
| 方法名 | Request ID | 請求 / 響應類型 | 用途(方向) |
|---|---|---|---|
| OpenApproval | 0x01 | OpenApprovalReq / Rsp | 開戶審批(民生 → moomoo) |
| SyncData | 0x02 | CrmReq / CrmRsp | 同步客戶/交易數據(民生 → moomoo) |
| WithDrawApproval | 0x03 | WithDrawApprovalReq / Rsp | 出金審批(民生 → moomoo) |
| Reconciliate | 0x04 | ReconciliationReq / Rsp | 每日對賬(民生 → moomoo) |
| ChangePassword | 0x05 | ChangePasswordReq / Rsp | 修改交易密碼(民生 → moomoo) |
| WithDrawAck | 0x06 | WithDrawAckReq / Rsp | 出金確認——銀行確認到賬(民生 → moomoo) |
| LoginIn | 0x07 | LoginInReq / Rsp | 櫃員登錄系統(民生 → moomoo) |
| LoginOut | 0x08 | LoginOutReq / Rsp | 櫃員登出系統(民生 → moomoo) |
| CreateWithdrawFutu | 0x09 | WithdrawFutuReq / Rsp | 創建出金——moomoo 側主動發起(moomoo → 民生) |
方法調用流程簡述
- 開戶流程:用戶在銀行端簽約 → 銀行調用 OpenApproval → moomoo 審批 → 返回結果
- 入金流程:用戶在銀行端發起 → 銀行通過 SyncData 推送入金數據 → moomoo 處理到賬
- 出金流程:用戶在 moomoo 端發起 → CreateWithdrawFutu 發送出金請求 → 銀行處理 → WithDrawAck 確認
- 對賬流程:每日銀行發起 Reconciliate → 雙方核對交易數據 → 發現差異人工處理
核心接口字段詳情
CrmReq — 數據同步請求
SyncData 方法的請求體,是民生向 moomoo 推送各類業務數據的統一入口:
| 字段 | 類型 | 描述 | 備註 |
|---|---|---|---|
| date | string | 數據日期 | 格式 YYYYMMDD |
| type | ReqType enum | 請求類型(10 種) | 決定本次推送的數據類別 |
ReqType 枚舉 — 10 種數據類型
| 枚舉值 | 名稱 | 說明 | 觸發時機 |
|---|---|---|---|
| 1 | OPEN | 開戶數據 | 用戶在銀行端完成銀證簽約 |
| 2 | OPENRES | 開戶結果 | moomoo 審批後返回給銀行 |
| 3 | DEPOSIT | 入金數據 | 用戶發起入金轉賬 |
| 4 | WITHDRAW | 出金數據 | 出金請求到達銀行 |
| 5 | WITHDRAWRES | 出金結果 | 銀行處理出金後返回 |
| 6 | CLOSE | 銷戶數據 | 用戶解除銀證關係 |
| 7 | OPENRC | 開戶對賬 | 每日對賬——單筆開戶 |
| 8 | BATCHOPENRC | 批量開戶對賬 | 每日對賬——批量開戶 |
| 9 | WITHDRAWRC | 出金對賬 | 每日對賬——單筆出金 |
| 10 | BATCHWITHDRAWRC | 批量出金對賬 | 每日對賬——批量出金 |
數據推送 vs 輪詢
與天星(REST API 輪詢)不同,民生採用推送模式——銀行主動通過 SyncData 將數據推送到 moomoo 側。moomoo 不需要定時輪詢銀行接口。
DepositItem — 入金數據字段
銀行推送入金數據時,每筆入金以 DepositItem 表示:
| 字段 | 類型 | 描述 | 取值範圍/格式 |
|---|---|---|---|
| TraDat | string | 交易日期 | YYYYMMDD |
| TraTim | string | 交易時間 | HHMMSS |
| RefNo | string | 參考號 | 銀行側唯一標識,對賬關鍵 |
| SDNo | string | 券商編號 | 固定值,標識 moomoo |
| SecAc | string | 證券賬號 | moomoo 賬號(與 CID 映射) |
| CusAc | string | 客戶賬號 | 銀行卡號 |
| Ccy | string | 幣種 | HKD / USD(不支持 CNH) |
| Amt | string | 金額 | 字符串格式,如 "50000.00" |
| AcCkDt | string | 對賬日期 | YYYYMMDD,對賬時使用 |
WithDrawItem — 出金數據字段
| 字段 | 類型 | 描述 | 取值範圍/格式 |
|---|---|---|---|
| TraDat | string | 交易日期 | YYYYMMDD |
| RefNo | string | 參考號 | 銀行側唯一標識 |
| SDNo | string | 券商編號 | 固定值 |
| SecAc | string | 證券賬號 | moomoo 賬號 |
| CusAc | string | 客戶賬號 | 銀行卡號 |
| Ccy | string | 幣種 | HKD / USD |
| Amt | string | 金額 | 字符串格式 |
| AcCkDt | string | 對賬日期 | YYYYMMDD |
| SucFlg | string | 成功標誌 | Y = 成功 / N = 失敗 |
| TraTime | string | 交易時間 | HHMMSS |
OpenApprovalReq — 開戶審批請求
銀行推送開戶審批,moomoo 側決定是否通過:
| 字段 | 必填 | 類型 | 描述 |
|---|---|---|---|
| AgrNo | ✅ | string | 協議號。銀證簽約協議唯一標識 |
| SDNo | ✅ | string | 券商編號。固定值 |
| SecAc | ✅ | string | 證券賬號。需在 moomoo 系統中存在 |
| CusAc | ✅ | string | 客戶賬號。銀行卡號 |
| AprSts | ✅ | string | 審批狀態。銀行端預審結果 |
| RejRsn | ❌ | string | 拒絕原因。僅審批不通過時有值 |
| CusEnm | ❌ | string | 客戶英文名。用於姓名校驗 |
| CusCnm | ❌ | bytes | 客戶中文名。bytes 類型(GB18030 編碼) |
CusCnm 使用 bytes 類型
中文姓名字段 CusCnm 不是 string 而是 bytes 類型。這是因為 Protobuf 的 string 要求 UTF-8 編碼,但民生銀行使用 GB18030 編碼傳輸中文——如果用 string 類型會導致解碼錯誤。開發時需特別注意編碼轉換。
WithDrawApprovalReq — 出金審批請求
| 字段 | 必填 | 類型 | 描述 |
|---|---|---|---|
| OrgRefNo | ✅ | string | 原始參考號。關聯原始出金請求 |
| SDNo | ✅ | string | 券商編號。固定值 |
| SecAc | ✅ | string | 證券賬號。moomoo 賬號 |
| CusAc | ✅ | string | 客戶賬號。銀行卡號 |
| Ccy | ✅ | string | 幣種。HKD / USD |
| Amt | ✅ | string | 金額。字符串格式 |
| AprSts | ✅ | string | 審批狀態。通過 / 拒絕 |
| RejRsn | ❌ | string | 拒絕原因。僅拒絕時填寫 |
與招行的關鍵差異
民生和招行同屬內銀系 BST,但協議和實現有顯著差異:
| 維度 | 招行 CMB | 民生 MS |
|---|---|---|
| IMPORT_BANK_ID | 12 | 13 |
| AUTO_SETTING_ID | 2 | 1 |
| 協議 | 自定義二進制 Socket 協議 | Protobuf/SRPC 框架 |
| 序列化 | 手工二進制編碼/解碼 | Protobuf 自動序列化 |
| 加密算法 | SM2 國密 | SM2 國密 |
| CNH 支持 | 僅限 HK 銀行卡持有者 | 完全不支持 |
| 處理時段 | 08:40 ~ 15:59 | 08:40 ~ 15:59 |
| 保證金時段 | 08:40 ~ 10:59 | 08:40 ~ 10:59 |
| 錯誤碼體系 | Socket 響應碼(0/-5/-6) | Protobuf 錯誤枚舉(2001~2006) |
| 對賬方式 | 每日文件對賬 | SyncData(type=7~10)推送對賬 |
| 服務名 | cmb_stock_trans | ms_stock_bank_transaction |
| 代碼語言 | Python | Python |
| 接口數量 | — | 9 個 RPC 方法 |
一句話總結:招行是"裸"二進制協議(靈活但維護難),民生是 Protobuf 標準協議(結構清晰但依賴 proto 文件同步)。
CNH 限制
民生銀行完全不支持人民幣(CNH)幣種。這是在代碼層面硬編碼的限制:
checkCurrency() → 檢測到 CNH → 直接拒絕 → 返回錯誤碼 2001 (MsBsRejRsn::LOCK_OF_CASH)| 幣種 | 支持情況 | 說明 |
|---|---|---|
| HKD | ✅ | 完全支持 |
| USD | ✅ | 完全支持 |
| CNH | ❌ | checkCurrency() 直接拒絕 |
CNH 入金會被誤報為"資金不足"
由於 CNH 拒絕使用的錯誤碼是 2001(LOCK_OF_CASH = 資金不足),用戶可能看到"資金不足"的錯誤提示,但實際原因是幣種不支持。運營排查時需注意區分。
對比:
- 招行:CNH 僅限 HK 銀行卡持有者(有條件支持)
- 天星:HKD / USD / CNH 全面支持
- 民生:CNH 完全不支持
錯誤碼體系
民生特有錯誤碼(MsBsRejRsn 枚舉)
| 錯誤碼 | 枚舉名 | 含義 | 處理方式 |
|---|---|---|---|
| 2001 | LOCK_OF_CASH | 資金不足 / 幣種不支持。賬戶餘額不足,或 CNH 入金被攔截 | 通知用戶檢查餘額/幣種 |
| 2002 | ACCOUNT_ABNORMAL | 賬戶狀態異常。賬戶被凍結、已銷戶等 | 聯繫民生銀行確認賬戶狀態 |
| 2003 | OTHER_REJECTION | 其他拒絕原因。銀行側風控攔截等 | 人工排查,聯繫銀行獲取詳情 |
| 2004 | NSS_ISSUE | NSS 問題。網路安全子系統異常 | 技術排查網路/證書配置 |
| 2005 | GDCA_ISSUE | GDCA 問題。廣東省數字證書認證異常 | KYC/證書相關排查 |
| 2006 | INVALID_BANKCARD | 銀行卡無效。卡號錯誤、已註銷、未啟用 | 引導用戶重新綁卡 |
與通用 BST 錯誤碼的映射
| 民生錯誤碼 | 對應通用狀態 | 對用戶的展示 |
|---|---|---|
| 2001 | FAILED(入金失敗) | "資金不足,請檢查銀行賬戶餘額" |
| 2002 | FAILED(賬戶異常) | "銀行賬戶狀態異常,請聯繫銀行" |
| 2003 | FAILED(拒絕) | "銀行拒絕處理,請聯繫客服" |
| 2004 | FAILED(系統異常) | "系統異常,請稍後重試" |
| 2005 | FAILED(KYC 異常) | "身份驗證異常,請聯繫客服" |
| 2006 | FAILED(卡無效) | "銀行卡無效,請更換銀行卡" |
入金流程
民生 BST 入金流程
民生入金由銀行端主導——用戶在民生銀行 App/櫃台發起轉賬到證券賬戶:
入金時段限制
| 時段 | 時間範圍 | 可執行操作 |
|---|---|---|
| 正常交易時段 | 08:40 ~ 15:59 | 入金 + 出金 |
| 保證金入金時段 | 08:40 ~ 10:59 | 僅保證金類入金 |
| 非交易時段 | 16:00 ~ 次日 08:39 | 不接受入金/出金請求 |
時段外入金
民生銀行在非交易時段發起的入金請求會被 moomoo 側拒絕。與天星不同(天星會暫存請求等待交易時段),民生需要用戶在交易時段內重新發起。
出金流程
標準出金流程
民生出金支持兩種模式:
| 模式 | 觸發方式 | 接口 | 說明 |
|---|---|---|---|
| moomoo 端發起 | 用戶在 moomoo App 點擊出金 | CreateWithdrawFutu (0x09) | moomoo 主動調用銀行接口 |
| 銀行端發起 | 銀行推送出金請求 | WithDrawApproval (0x03) | 民生銀行推送,moomoo 審批 |
moomoo 端出金流程
銀行端出金審批流程
當用戶在民生銀行端發起出金時:
- 銀行發送
WithDrawApproval(0x03)到 moomoo - moomoo 執行風控檢查(餘額、限額、黑名單等)
- 審批通過:返回 AprSts = 通過 → 銀行執行轉賬
- 審批拒絕:返回 AprSts = 拒絕 + RejRsn(拒絕原因)
auto_bs 自動出金
民生出金走 auto_bs 自動出金通道,AUTO_SETTING_ID = 1。自動出金需滿足以下全部條件:
| 條件 | 說明 |
|---|---|
| 賬戶狀態正常 | 非凍結、非銷戶 |
| 不在黑名單 | 出金黑名單檢查通過 |
| 單筆不超限 | 金額在限額範圍內 |
| 每日不熔斷 | 當日累計未觸發熔斷 |
| 交易時段內 | 08:40 ~ 15:59 |
| 幣種支持 | HKD 或 USD(非 CNH) |
不滿足任一條件則轉人工審批。
對賬機制
每日對賬流程
民生通過 SyncData 接口的 4 種對賬類型實現每日對賬:
| ReqType | 對賬類型 | 說明 |
|---|---|---|
| 7 (OPENRC) | 單筆開戶對賬 | 逐筆核對開戶記錄 |
| 8 (BATCHOPENRC) | 批量開戶對賬 | 批量核對開戶記錄 |
| 9 (WITHDRAWRC) | 單筆出金對賬 | 逐筆核對出金記錄 |
| 10 (BATCHWITHDRAWRC) | 批量出金對賬 | 批量核對出金記錄 |
對賬差異處理
| 差異類型 | 說明 | 處理 |
|---|---|---|
| 長款(moomoo 有,銀行無) | moomoo 側多了一筆交易 | 核實是否銀行漏推送,必要時沖正 |
| 短款(銀行有,moomoo 無) | 銀行側多了一筆交易 | 核實是否 moomoo 漏處理,必要時補錄 |
| 金額不一致 | 同一筆交易金額不同 | 以銀行側為準,調整 moomoo 側記錄 |
| 狀態不一致 | 同一筆交易狀態不同 | 人工判斷並修正 |
安全與加密
SM2 國密算法
民生銀行使用中國國家商用密碼標準 SM2 算法進行通信加密:
| 維度 | 說明 |
|---|---|
| 算法類型 | SM2 橢圓曲線公鑰密碼 |
| 密鑰長度 | 256 位 |
| 等效安全性 | 約等於 RSA-3072 |
| 用途 | 請求/響應數據加密 + 數字簽名 |
| 合規要求 | 中國境內銀行通信必須使用國密算法 |
加密流程
- 請求端:將 Protobuf 序列化後的二進制數據用 SM2 公鑰加密
- 傳輸:加密後的數據通過 SRPC 框架傳輸
- 接收端:用 SM2 私鑰解密,再用 Protobuf 反序列化
- 簽名驗證:每個請求附帶 SM2 數字簽名,接收端驗簽確保數據完整性
異常場景手冊
入金異常(4 類)
| # | 異常 | 症狀 | 原因與處理 |
|---|---|---|---|
| 1 | 入金被拒(2001) | 銀行返回 LOCK_OF_CASH | CNH 幣種被攔截 / 餘額不足。確認幣種,若為 CNH 則告知不支持 |
| 2 | 賬戶異常(2002) | 銀行返回 ACCOUNT_ABNORMAL | 銀行卡凍結/銷戶。聯繫民生銀行確認狀態 |
| 3 | SyncData 未到達 | moomoo 未收到入金推送 | 網路中斷/SRPC 通信異常。檢查網路連通性,查看 SRPC 日誌 |
| 4 | 數據解密失敗 | Protobuf 反序列化錯誤 | SM2 密鑰不匹配/數據損壞。檢查密鑰配置,聯繫銀行技術 |
出金異常(5 類)
| # | 異常 | 症狀 | 原因與處理 |
|---|---|---|---|
| 1 | CreateWithdrawFutu 失敗 | 出金請求被銀行拒絕 | 參數錯誤/銀行側風控。檢查請求參數和錯誤碼 |
| 2 | WithDrawAck 未到達 | 出金後長時間無確認 | 銀行處理延遲/通信中斷。人工查詢銀行側狀態 |
| 3 | 凍結未釋放 | 出金失敗但資金仍凍結 | 回滾流程異常。手動釋放凍結 |
| 4 | 審批超時 | WithDrawApproval 無響應 | moomoo 審批服務異常。檢查審批服務日誌 |
| 5 | 重複出金 | 同一筆出金多次執行 | RefNo 去重失敗。通過 OrgRefNo 排查重複 |
對賬異常(3 類)
| # | 異常 | 症狀 | 原因與處理 |
|---|---|---|---|
| 1 | 對賬數據缺失 | 某日對賬未收到 | Reconciliate 調用失敗。手動觸發對賬 |
| 2 | 長款/短款 | 雙方記錄不一致 | 網路丟包/處理時序差異。人工核對並調整 |
| 3 | 批量對賬超時 | BATCHOPENRC/BATCHWITHDRAWRC 處理慢 | 數據量過大。分批處理或擴容 |
櫃員系統
民生銀行有獨立的櫃員登錄/登出機制,通過 LoginIn/LoginOut 接口管理:
| 接口 | Request ID | 用途 | 說明 |
|---|---|---|---|
| LoginIn | 0x07 | 櫃員登錄 | 銀行櫃員開始操作前登錄 |
| LoginOut | 0x08 | 櫃員登出 | 銀行櫃員操作結束後登出 |
櫃員系統的業務意義
民生銀行的部分操作(如開戶審批、出金審批)需要銀行櫃員參與。櫃員登錄後才能執行審批操作,登出後系統記錄操作日誌。這是傳統銀行體系的特有流程,天星等虛擬銀行不需要此機制。
密碼管理
ChangePassword(0x05)接口用於修改銀證交易密碼:
| 維度 | 說明 |
|---|---|
| 觸發場景 | 用戶在銀行端申請修改交易密碼 |
| 影響範圍 | 修改後所有銀證操作需使用新密碼 |
| 安全要求 | 密碼在傳輸中經 SM2 加密,moomoo 側不存儲明文 |
代碼位置與服務部署
| 維度 | 說明 |
|---|---|
| 服務名 | ms_stock_bank_transaction |
| 代碼目錄 | ms_sb_trans_python/ |
| 語言 | Python |
| Proto 文件 | 民生側提供 .proto 定義文件 |
| 依賴 | SM2 國密庫、Protobuf 運行時、SRPC 框架 |
關鍵代碼模組
| 模組 | 職責 |
|---|---|
ms_sb_trans_python/handler/ | 9 個 RPC 方法的請求處理器 |
ms_sb_trans_python/crypto/ | SM2 加解密和簽名驗簽 |
ms_sb_trans_python/proto/ | Protobuf 生成的消息類 |
ms_sb_trans_python/service/ | 業務邏輯(入賬、出金、對賬) |
ms_sb_trans_python/config/ | 銀行連接配置、密鑰配置 |
需求變更指引
| 變更需求 | 改動位置 | 說明 |
|---|---|---|
| 新增支持 CNH | checkCurrency() + 銀行側協商 | 需銀行側同步支持 CNH,修改幣種校驗邏輯 |
| 修改錯誤碼映射 | handler/ 中的錯誤處理 | 調整 MsBsRejRsn 到用戶提示的映射 |
| 修改處理時段 | 時段校驗邏輯 | 同步修改前後端時段判斷 |
| 新增 RPC 方法 | 銀行提供新 proto → 生成代碼 → 實現 handler | 需銀行側先發佈 proto 文件 |
| 更換 SM2 密鑰 | config/ 密鑰配置 | 需與銀行協調密鑰輪換時間窗口 |
| 修改對賬規則 | service/reconciliation.py | 調整差異判斷閾值或處理策略 |
| 修改自動出金條件 | auto_bs 配置 + AUTO_SETTING_ID | 參考 出金規則手冊 |
| 調整限額 | 限額配置(SQL seed) | 修改單筆上限/報警/熔斷閾值 |
常見客訴 Top 3
| # | 用戶反饋 | 原因 | 客服話術 |
|---|---|---|---|
| 1 | "BST 出金超時" | Socket 連接抖動,回調碼 -5 | "出金正在處理中,系統已自動重試,請稍候查看結果" |
| 2 | "為什麼民生不支持 CNH" | 民生銀證不支持離岸人民幣 | "民生銀行目前支持港幣和美元出入金,暫不支持人民幣" |
| 3 | "出金被銀行拒絕" | 回調碼 -6 或餘額不足 | "請確認賬戶餘額充足,如仍被拒請聯繫客服核實原因" |
監控與告警
關鍵監控項
| # | 監控項 | 觸發條件 | 處理方式 |
|---|---|---|---|
| 1 | SRPC 連接中斷(嚴重) | 與民生銀行的 SRPC 連接斷開 | 檢查網路,自動重連 |
| 2 | SM2 解密失敗(高) | 收到的數據無法解密 | 檢查密鑰配置是否一致 |
| 3 | 入金失敗率突增(高) | 單位時間內失敗數量超限 | 排查具體錯誤碼分佈 |
| 4 | 出金確認超時(高) | CreateWithdrawFutu 後無 WithDrawAck | 人工查詢銀行側狀態 |
| 5 | 對賬差異(中) | 每日對賬發現長款/短款 | 運營核對處理 |
| 6 | 櫃員異常登錄(中) | LoginIn 頻率異常或非工作時間登錄 | 安全團隊排查 |
讀完之後
| 我想... | 去看 |
|---|---|
| 看三家 BST 銀行的整體對比 | 內銀系 BST 總覽 |
| 了解招行的二進制 Socket 協議 | 招商銀行 CMB |
| 看天星的 REST API 方案 | 天星銀行 Airstar |
| 查 BST 錯誤碼 | 統一錯誤碼中心 |
| 看出金自動審批條件 | 出金規則手冊 |
| 看所有銀行的能力對比 | 銀行能力矩陣 |