廣發 CGB Push 模式 Direct 模式
本頁說明
講什麼:廣發銀行的 FPS API 批量出金通道、FPS 消息類型、批量處理機制 適合誰:需要了解廣發對接細節的產品經理 前置閱讀:銀行能力矩陣預計閱讀:2 分鐘 負責人:出金產品經理
核心要點:廣發 FPS 出金採用批量提交模式——多筆出金打包成一個 batch,系統輪詢獲取每筆結果,最多輪詢 1500 次(可達數小時)。
能力總覽
| 能力 | 支持情況 | 協議/通道 | 核心服務 |
|---|---|---|---|
| 入金流水 | ❌ | — | — |
| 出金 FPS API | ✅ | Form-URLEncoded HTTP POST(XML payload) | cgb_fps_service (Go) |
| FPS 入金 | ✅ | FPS 收款 | — |
| eDDA/eDDI | ❌ | — | — |
| 銀證 BST | ❌ | — | — |
廣發是唯一支持 FPS API 批量出金的銀行——可以一次提交多筆出金,由銀行批量處理。
出金:FPS API
出金方法
| 維度 | 說明 |
|---|---|
| 方法碼 | TRANSFER_METHOD_CGB_FPS_API = 'cgb_fps_api' |
| 分類 | 電子銀行方法(allEBankMethod) |
| 中文名 | FPS API(廣發) |
FPS 消息類型
廣發 FPS 通過 4 種消息類型完成出金生命週期:
| 消息類型 | 用途 | 方向 |
|---|---|---|
| 2063 | 單筆出金請求 | moomoo → 廣發 |
| 2064 | 批量出金請求 | moomoo → 廣發 |
| 2065 | 單筆出金查詢 | moomoo → 廣發 |
| 2066 | 批量出金查詢 | moomoo → 廣發 |
單筆出金(2063)
| 參數 | 說明 | 示例 |
|---|---|---|
| Remote Type | 地區 | 01=香港, 02=澳門 |
| Remit Currency | 匯款幣種 | HKD/CNY/MOP |
| Payee Account Type | 收款賬號類型 | BBAN/SVID/MOBN/AIIN/EMAL |
| Transaction Status | 交易狀態 | 0=成功, 1=失敗, 2=處理中 |
批量出金(2064)
廣發獨有的批量能力,一次最多提交 2000 筆出金:
| 參數 | 說明 |
|---|---|
| Customer Batch No | 批次號(20 位) |
| All Count | 總筆數(最大 2000) |
| Records | 多條 Fps2064Record |
| Batch Status | 1=失敗, 2=處理中 |
批量出金數據流
狀態碼映射
不同消息類型的狀態碼含義不同,需要注意區分:
| 狀態碼 | 2063(單筆請求) | 2065(單筆查詢) | 2066(批量查詢) |
|---|---|---|---|
| 0 | 成功 | 處理中 | 失敗 |
| 1 | 失敗 | 成功 | 成功 |
| 2 | 處理中 | 失敗 | 處理中 |
注意
2063 和 2065/2066 的狀態碼含義是反的——2063 中 0=成功,但 2065 中 0=處理中。開發時務必區分請求類型。
錯誤處理
批量查詢(2066)返回每筆的詳細信息:
- Success Count:成功筆數
- Fail Count:失敗筆數
- 每筆失敗會附帶錯誤原因碼和錯誤描述
- 區分付款方錯誤(Error Type=0)和收款方錯誤(Error Type=1)
渠道接口詳情
渠道接口概覽
| 維度 | 說明 |
|---|---|
| 協議類型 | Form-URLEncoded HTTP POST(XML payload) |
| 認證方式 | SM2 國密簽名 |
| 數據格式 | XML (UTF-8) |
| 端口 | 9091 (HTTPS) |
| 超時 | 30 秒 |
| 核心服務 | cgb_fps_service(Go) |
SM2 簽名配置
廣發使用國密 SM2 算法進行請求簽名,涉及以下密鑰:
| 密鑰 | 路徑 | 格式 |
|---|---|---|
| 富途私鑰 | conf/keys/futu.pvk | PKCS#8 |
| 富途公鑰 | conf/keys/futu.puk | — |
| 銀行公鑰 | conf/keys/gfs.tst.puk | — |
| 用戶 ID | 16 字節字符串 | "1234567812345678" |
簽名流程:使用富途私鑰對請求 XML 做 SM2 簽名,簽名結果 Base64 編碼後放入 SIGN 塊;銀行響應使用銀行公鑰驗簽。
接口 1:2063 單筆出金(FPS Single Payment)
請求 COMMHEAD(公共報文頭):
| 字段 | 描述 | 示例 |
|---|---|---|
TRANCODE | 交易碼 | "2063" |
CIFMASTER | 客戶主號 | "1000001287" |
ENTSEQNO | 流水號(≤20 位) | 財務唯一序號 |
ENTUSERID | 用戶 ID | "100001" |
TRANDATE | 交易日期 | "YYYYMMDD" |
TRANTIME | 交易時間 | "HHMMSS" |
請求 BODY:
| 字段 | 類型 | 必填 | 描述 |
|---|---|---|---|
REMITTYPE | string | ✅ | 匯款類型。取值 "01"=香港, "02"=澳門 |
PAYACC | string | ✅ | 付款賬號。如 "3597601080012948" |
REMITCUR | string | ✅ | 幣種。取值 香港: "HKD" / "CNY", 澳門: "HKD" / "MOP" |
REMITAMOUNT | decimal(16,2) | ✅ | 金額。如 "1000.00" |
PAYEEACTYPE | string | ✅ | 收款方賬號類型。取值 "BBAN" / "SVID" / "MOBN" / "AIIN" / "EMAL" |
BENEFCORPACCT | string | ✅ | 收款方賬號/ID。根據 PAYEEACTYPE 填寫對應格式 |
PAYEEBANK | string | ✅ | 收款銀行代碼。取值 "359"=內部 HK,或 FPS 銀行代碼 |
BENEFCORPNAME | string(≤140) | ✅ | 收款方姓名 |
PAYPURS | string | ✅ | 付款用途。取值 "CXBSNS"=商業, "CXSALA"=薪資, "CXMRCH"=商戶, "CXPSNL"=個人 |
REMITMEMO | string | ❌ | 備註。≤34 中文字符 / 102 英文字符 |
MEMO | string | ❌ | 註釋。≤50 中文字符 / 150 英文字符 |
SIGN 塊:
| 字段 | 描述 |
|---|---|
CSTID | 客戶 ID(16 字節) |
SIGNVALUE | Base64 編碼的 SM2 簽名 |
響應:
| 字段 | 描述 |
|---|---|
RETCODE | 通信碼:"000"=成功 |
ERRORCODE | 業務碼:"0000"=成功 |
ERRORMESSAGE | 錯誤描述 |
TRACENO | 銀行追蹤號 |
TRANSTATUS | "0"=成功, "1"=失敗, "2"=處理中 |
接口 2:2064 批量出金(FPS Batch Payment)
在 2063 單筆基礎上增加以下批量特有字段:
| 字段 | 描述 |
|---|---|
CUSTOMERBATCHNO | 批次號(≤20 位,全局唯一) |
ALLCOUNT | 總筆數(≤2000) |
ALLAMOUNT | 總金額(decimal 精確計算,不可有浮點誤差) |
RECORD.CUSTOMERSALARYSEQ | 明細序號(20 字符,批次內唯一) |
每條 RECORD 包含與 2063 單筆相同的 PAYEEACTYPE、BENEFCORPACCT、REMITAMOUNT 等字段。
批量金額校驗
ALLAMOUNT 必須嚴格等於所有明細 REMITAMOUNT 之和。系統使用 decimal 類型精確計算,避免浮點誤差導致銀行拒絕整批。
接口 3:2065 單筆查詢
| 字段 | 描述 |
|---|---|
ORIGENTSEQNO | 原始流水號(= 2063 請求中的 ENTSEQNO) |
STARTRANSDATE | 查詢開始日期 |
ENDTRANSDATE | 查詢結束日期 |
響應 TRANSTATUS:"0"=處理中, "1"=成功, "2"=失敗
狀態碼含義不同
注意 2065 查詢的狀態碼與 2063 請求的狀態碼含義完全相反:2063 中 "0"=成功,2065 中 "0"=處理中。開發和排查時務必區分請求類型。
接口 4:2066 批量查詢
| 字段 | 描述 |
|---|---|
CUSTOMERBATCHNO | 批次號(= 2064 請求中的批次號) |
BATCHSTATUS | "0"=失敗, "1"=完成, "2"=處理中 |
SUCCESSCOUNT | 成功筆數 |
FAILCOUNT | 失敗筆數 |
每筆明細的 TRANSTATUS 含義與 2065 一致("0"=處理中, "1"=成功, "2"=失敗)。
2066 雙層狀態
2066 響應包含兩層狀態:BATCHSTATUS(批次級:0=失敗, 1=成功, 2=處理中)和 TRANSTATUS(明細級:0=處理中, 1=成功, 2=失敗)。明細級狀態與 2065 含義一致,與批次級含義相反。
冪等性規則
廣發對重複請求有嚴格的冪等性校驗:
| 場景 | 行為 | 影響範圍 |
|---|---|---|
重複 CUSTOMERBATCHNO | 整批拒絕 | 整個批次 |
批次內重複 CUSTOMERSALARYSEQ | 僅該條失敗 | 單筆明細 |
歷史重複 CUSTOMERSALARYSEQ | 該條失敗 | 單筆明細 |
冪等性設計建議
CUSTOMERBATCHNO建議使用"日期 + 業務序號"格式確保全局唯一CUSTOMERSALARYSEQ建議使用出金訂單 ID 確保跨批次也不重複- 重試時必須使用新的
CUSTOMERBATCHNO,不能複用舊批次號
配置
| 參數 | 值 | 說明 |
|---|---|---|
pay_acc_hkd | "3597601080012948" | HKD 付款賬號 |
pay_acc_cny | "3597601080012939" | CNY 付款賬號 |
batch_max_count | 3 | 單批最大筆數(銀行上限 1999,保守設置) |
為什麼 batch_max_count 設為 3?
雖然銀行支持最多 2000 筆/批,但實際運營中設為 3,原因是:出金通常需要逐筆審核和追蹤,過大的批次會增加排查難度;如果某批失敗需要重試,小批次影響範圍更可控。
moomoo 側適配
DBQueue 異步提交:出金服務不直接調用廣發 API,而是將出金指令寫入 DBQueue,由 cgb_fps_service 異步消費並提交銀行。
兜底查詢:系統通過 DBQueue 機制持續輪詢,每 15 秒檢查一次未完成交易狀態,最多重試 1500 次(約 6 小時覆蓋)。
狀態映射(TRANSTATUS → 內部狀態):
| TRANSTATUS (2065/2066) | 含義 | 內部狀態 |
|---|---|---|
0 | 處理中 | pending |
1 | 成功 | success |
2 | 失敗 | failed |
需求變更指引
| 變更需求 | 改動位置 | 說明 |
|---|---|---|
| 修改批量上限 | cgb_fps_service → 批量構建邏輯 | 調整 2000 筆上限 |
| 新增收款賬號類型 | cgb_fps_service → 2063 請求參數 | 添加 Payee Account Type |
| 修改查詢頻率 | cgb_fps_service → 輪詢配置 | 調整 2066 查詢間隔 |
| 新增幣種支持 | cgb_fps_service → 請求參數 | 添加 Remit Currency 選項 |
| 修改出金審批模板 | Task.php → $stepTemplates | 調整廣發出金審批流程 |
常見客訴 Top 3
| # | 用戶反饋 | 原因 | 客服話術 |
|---|---|---|---|
| 1 | "FPS 出金失敗" | 銀行系統繁忙(A014)或收款信息有誤 | "轉賬暫時失敗,系統正在自動重試,請稍候" |
| 2 | "出金狀態顯示未知" | 批量查詢返回 UNKNOWN 狀態 | "您的出金正在確認中,我們會盡快更新狀態" |
| 3 | "出金金額和申請不一致" | 批量金額匯總計算差異 | "請核對出金記錄,如有差異請聯繫客服處理" |
監控與告警
| 告警項 | 觸發條件 | 嚴重度 | 處理步驟 |
|---|---|---|---|
| 批量發送超時 | 2064 批量請求無響應 | 🔴 高 | 系統自動降級為單筆(2063)重發,檢查降級日誌 |
| 簽名驗簽失敗 | SIGN_ERROR | 🔴 高 | 檢查簽名密鑰配置,確認未被更換 |
| 狀態碼誤判告警 | 2063/2065 vs 2064/2066 狀態碼含義不同 | 🟡 中 | 確認消息類型後重新判斷,參考狀態碼含義反轉 |
讀完之後
| 我想... | 去看 |
|---|---|
| 看廣發在各銀行中的位置 | 銀行能力矩陣 |
| 了解廣發出金的完整審批流程 | 出金生命週期 |
| 對比另一家 FPS 出金銀行 | 渣打 SCB |
| 查 FPS 消息類型的錯誤碼 | 統一錯誤碼中心 |