深色模式
广发 CGB
本页说明
讲什么:广发银行的 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 消息类型的错误码 | 统一错误码中心 |
这个页面有帮助吗?