Skip to content

新人导读:一笔钱的旅程

本页说明

讲什么:以 FPS 入金、eDDA 入金、银证出金三个核心场景,端到端走一遍完整链路,串联全书知识点 适合谁:刚接手出入金业务、需要快速建立全局认知的产品经理 前置阅读:无,这是起点 预计阅读:8 分钟 负责人:出入金产品团队

核心要点:三个核心场景串联全书知识点——FPS 入金走 Push 匹配链路,eDDA 入金走 Pull 代扣链路,BST 出金走自动审批+银证转账链路。理解这三条链路就掌握了系统全貌。


30 秒全景

用户发起申请 → 银行流水/指令对接 → 自动匹配/审批 → 资金到账/汇出 → 对账

出入金系统是 moomoo 证券交易平台的资金通道层——连接用户银行账户与证券账户的桥梁。

维度数量说明
入金方式10 种BST、FPS、eDDA(恒生/汇丰)、网银、ATM、支票、缴费、海外、天星
出金通道12 种银证、中银银企/FPS、恒生/汇丰网银、渣打/广发 FPS、CHATS、电汇、支票
支持银行16 家中银、汇丰、恒生、工银、渣打、广发、招行、民生、天星、EWB 等
货币5 种HKD、USD、CNH、JPY、SGD
边界系统负责系统不负责
入口接收用户入金/出金请求用户注册、KYC、开户
银行对接流水解析、汇款指令、eDDA/eDDI银行内部处理、SWIFT 中转
资金操作通过 SBA 创建 procedure 操作账本账本余额管理本身(SBA 负责)
风控调用黑白名单、高风险检查风控规则引擎本身
通知触发入金/出金结果通知推送通道管理

入金和出金是两套完全独立的服务——入金核心是"匹配"(钱到了,找到是谁的),出金核心是"审批"(钱要走,能不能放行)。


按角色选择阅读路径

不同角色关注的重点不同。先看完下面三个场景建立全局认知,然后按你的角色深入:

产品经理:理解业务规则 + 知道改什么

核心路径入金方式总览匹配与自动入账出金规则手册银行能力矩阵

重点关注:每个页面底部的 如果需求变更 折叠块——告诉你"改这个功能要动哪些代码"

速查入金规则速查 · 出金数据字典 · 退款与冲正 · 常见问题 FAQ

运营人员:掌握操作流程 + 处理异常

核心路径人工匹配指引出金审批指引冲正/退款指引定时任务与监控

重点关注:CRM 导航路径、字段对照表、决策流程图、SLA 时效

排障入金排障 · 出金排障

开发者:理解系统架构 + 定位代码

核心路径系统架构与数据流SBA 资金编排银行卡与授权

重点关注:每个页面的代码位置标注(如果需求变更 折叠块中的文件路径)

银行对接内银系 BST · 汇丰 · 恒生 · 中银


下面用三个真实场景,带你走完入金和出金的每一步。FPS 和 eDDA 是两种截然不同的入金模式——前者是用户主动转账(Push),后者是系统从用户银行账户扣款(Pull)。理解这个区别是理解整个入金体系的关键。


入金之旅:一笔 HKD 50,000 的 FPS 入金

场景:用户在 moomoo App 选择「FPS 转数快」,向证券账户转入 HKD 50,000。

Step 1: 用户发起申请

用户在 App 点击「入金」,选择入金方式 fps(方式代码 3),填入金额 50,000,选择币种 HKD。

系统调用入金服务的 ApplyController.applyAction(),经过以下检查:

检查项说明
用户权限验证 WEB/OA 签名,确认用户身份
入金限制调用 AccountLockBusiness::isDepositRestricted() 检查账户是否被限制入金

检查通过后,创建一条 Apply 记录,写入 applys_{uid % 100} 分表:

字段说明
status0(PENDING)用户已申请,等待匹配
deposit_methodfpsFPS 转数快
amount50000申请金额
currencyHKD港币
export_bank_id用户选择的银行付款银行(用户侧)
import_bank_id系统分配收款银行(公司侧)

深入了解

全部 10 种入金方式 → 入金方式总览 Apply 表每个字段的含义 → 入金规则速查 § 核心字段

Step 2: 用户完成 FPS 转账

用户切换到银行 App,通过 FPS(转数快)完成 HKD 50,000 的转账。

FPS 是即时到账的支付系统,钱立刻从用户银行扣出,进入公司在渣打(SCB)或广发(CGB)的子账户。

Step 3: 银行流水到达系统

渣打/广发的 FPS 网关将交易流水推送到系统。流水写入 flows_{bankType}_{YYYYMM} 分表,关键信息:

字段说明
流水类型FPS 轉賬FPS transfer 标识
备注FPS...FPS 交易参考号
金额50000.00实际到账金额
币种HKD港币

不同银行的流水采集方式差异很大:

银行方式时效
中银B2E 主动拉取每日 3 次 + 2 小时转换
汇丰MT910 实时推送秒级
渣打/广发FPS API实时
招行/民生银证双向链路事件驱动,实时
EWBCSV + BAI2 文件按需手工上传

深入了解

各银行采集频率完整表 → 架构与数据流 各银行 FPS 能力 → 银行能力矩阵

Step 4: 自动匹配引擎启动

匹配引擎是一组定时任务,每家银行一个,每 3 分钟运行一次(如 php artisan match:boc)。

引擎拿到所有 status = PROCESSING 的未处理流水和 status = PENDING 的待匹配申请,执行五维比对

维度匹配字段匹配逻辑
1. 币种currency必须完全一致
2. 金额amount容差范围内匹配(HKD/CNH/JPY: 0~20 差额;USD/SGD: 0~3 差额)
3. 姓名en_name / cn_name精确匹配或模糊匹配
4. 日期date申请日期 ±15 天内
5. 卡号bank_card_number银行账号匹配

匹配结果有三种:

结果码含义后续
2 (RESULT_DEPOSIT)完全匹配,可自动入账→ 进入自动入账判定
1 (RESULT_NORMAL)部分匹配,需人工确认→ 创建匹配记录,等运营审核
0 (RESULT_NOT)不匹配→ 不操作

我们这笔 FPS 入金:币种 HKD 一致、金额 50,000 精确匹配、姓名一致、日期当天、卡号匹配 → RESULT_DEPOSIT(完全匹配)

深入了解

五维匹配的完整规则和容差逻辑 → 自动匹配引擎 匹配失败后怎么办 → 异常与人工处理

Step 5: 自动入账判定

匹配成功不等于自动入账。系统还需要检查 5 个自动入账条件

#条件本笔情况
1金额未超过币种限额HKD 50,000 < HKD 2,000,000 限额 → 通过
2流水未被人工拒绝过reject == 0 → 通过
3在允许的自动处理时间窗口内工作时间内 → 通过
4一条流水只对应一个用户count(uids) == 1 → 通过
5当日自动入账次数未超 10 笔首笔 → 通过

各币种自动入账限额

币种最大自动入账金额
HKD2,000,000
USD300,000
CNH2,000,000
JPY40,000,000
SGD350,000

5 个条件全部通过 → 系统判定为 NORMAL(正常模式) 入金类型。

深入了解

6 种入金编排模式 → SBA 资金编排 各币种限额和状态码 → 入金规则速查

Step 6: SBA 编排执行

系统向 SBA(Server Bank Account)发起入金编排请求,创建一个 Procedure

入金 Procedure(NORMAL 模式)执行序列:
  1. 检查冻结 →
  2. 资金入账(加到证券账户余额)→
  3. 解除冻结 →
  4. 完成

SBA 是系统的"内部银行"——所有涉及资金余额变动的操作都通过 SBA Procedure 完成,确保原子性和一致性。

深入了解

SBA 是什么 → SBA 概念与数据模型 6 种入金编排模式的触发条件 → SBA 资金编排

Step 7: 资金到账,用户收到通知

Procedure 执行成功,Apply 状态更新为 2(DONE)

系统发送推送通知(NOTICE_TYPE_NORMAL),用户在 App 看到"入金成功"。

从用户提交到到账,这笔 FPS 入金的全链路时间:FPS 流水实时到达 + 匹配引擎 3 分钟周期 + SBA 执行秒级 ≈ 3~5 分钟


入金之旅 II:一笔 HKD 20,000 的 eDDA 入金

场景:用户已绑定汇丰银行卡并完成 eDDA 授权,在 moomoo App 选择「eDDA 电子直接扣账」,入金 HKD 20,000。

eDDA 与 FPS 的根本区别

FPS 是用户主动转账(Push)——用户在银行 App 操作,钱到达后系统需要匹配引擎识别"这笔钱是谁的"。 eDDA 是系统主动扣款(Pull)——用户在 moomoo App 提交后,系统直接从用户银行账户扣钱。不需要匹配引擎,因为系统自己发起的扣款,天然知道钱属于谁。

Step 1: 前提——eDDA 授权

在发起 eDDA 入金之前,用户必须先完成一次性的 eDDA 授权,允许富途从其银行账户直接扣款。

授权状态在 setup_eddis 表中跟踪:

状态码含义说明
3WAITING等待发起授权
1PENDING授权进行中,等待银行确认
2EFFECT授权成功,可以入金
0FAIL授权失败

系统通过 SetupEddaCheckAuthorizationJob 定时检查授权进度(每 600 秒轮询一次),最长等待约 10 天(3000 次重试)。

常见授权失败原因:

错误码含义
MFISAC01银行账号错误
MPP01005~01008身份证/手机号/姓名不匹配
MPP06001银行账户状态异常

深入了解

汇丰 eDDA 与恒生 eDDA 的区别 → 汇丰 HSBC / 恒生 Hang Seng 哪些银行卡可以用 eDDA → eDDA 支持范围(汇丰通道 15 家、恒生通道 12 家)

Step 2: 用户发起 eDDA 入金

用户在 App 点击「入金」,选择入金方式 eddaHSBC(方式代码 9),输入金额 20,000 HKD。

系统创建 Apply 记录后,验证 eDDA 授权状态:

验证逻辑(verifyEddaBankCard):
  恒生 eDDA → 必须已预授权(status = EFFECT)
  汇丰 eDDA(同行)→ 必须已预授权
  汇丰 eDDA(跨行 + 线上开户)→ 允许后置授权

我们的场景:汇丰同行,授权已生效 → 验证通过。

Apply 记录:

字段与 FPS 的区别
status0(PENDING)
deposit_methodeddaHSBCFPS 是 fps
amount20000
currencyHKD

Step 3: 异步任务队列启动扣款

这是 eDDA 与 FPS 最大的不同——用户不需要去银行 App 操作

Apply 创建后,系统自动触发任务链:

ApplyFollowJob(检测到 method = eddaHSBC)
  → HsbcEddiCreateJob(发起扣款)
    → HsbcEddiResultJob(轮询扣款结果)

HsbcEddiCreateJob 调用 Eddi::applyHsbcEddi(),构建扣款请求:

参数说明
debtor_bank_code用户的银行代码(汇丰 3 位)
debtor_account_identification用户银行账号
debtor_name用户姓名
creditor_bank_code富途收款银行代码
creditor_account_identification富途收款账号
instructed_amount20000(扣款金额)
instructed_amount_currencyHKD

系统通过 SBA 服务将扣款指令发往汇丰。同时写入 hsbc_eddis 表,用 apply_id 的唯一索引防止重复扣款。

深入了解

入金方式对比 → 入金方式总览

Step 4: 银行执行扣款

汇丰收到 eDDI(Electronic Direct Debit Instruction)指令后:

  1. 验证用户账户余额
  2. 从用户账户扣除 HKD 20,000
  3. 将资金转入富途在汇丰的账户
  4. 通过 eDDA Report 回传执行结果

hsbc_edda_report 服务接收汇丰的执行报告,更新 Procedure 状态:

报告状态含义系统处理
finished扣款成功更新 Apply real_amount,标记入账
rejected扣款被拒记录 reject_reason_code,通知用户

Step 5: SBA 入账(跳过匹配引擎!)

关键区别:eDDA 入金完全跳过匹配引擎

在匹配服务的代码中,eDDA 被显式排除:

HsbcMatch 匹配逻辑:
  if (deposit_method == 'eddaHSBC') → return 不匹配(跳过)

HangSengMatch 匹配逻辑:
  if (deposit_method == 'edda') → return 不匹配(跳过)

因为系统自己发起的扣款,天然知道资金属于哪个用户、对应哪笔申请,不需要五维比对

扣款成功后,SBA 直接创建入金 Procedure 完成入账。

Step 6: 资金到账,用户收到通知

HsbcEddiResultJob 轮询到扣款成功 → Apply 状态更新为 2(DONE) → 推送通知。

从用户提交到到账时间:扣款指令发送秒级 + 银行处理通常 几分钟到几小时(取决于银行处理速度)。


FPS vs eDDA:两种入金模式对比

维度FPS(Push)eDDA(Pull)
资金方向用户主动转入系统从用户账户扣款
用户操作需切换到银行 App 操作在 moomoo App 内一键完成
前置条件需先完成 eDDA 授权
匹配引擎需要五维匹配完全跳过
到账确定性依赖匹配结果扣款即确认
支持银行渣打、广发、中银等汇丰通道 15 家、恒生通道 12 家(完整列表
用户体验步骤多,需跨 App体验最好,一键入金
数据表applys + flows + matchesapplys + hsbc_eddis/hs_eddis + setup_eddis
异步任务匹配引擎定时扫描(3 分钟)Job 队列主动推进
失败处理流水到了但匹配不上 → 人工银行拒绝扣款 → 通知用户

为什么 eDDA 是核心流程?

eDDA 实现了"用户在 App 内一键入金"的最佳体验——不需要切换银行 App、不需要等待匹配。eDDA 占入金总量约 78%(汇丰 eDDA 单通道占 72%,恒生 eDDA 约 6%),是绝对主力。汇丰通道支持 15 家银行的个人账户,恒生通道支持 12 家——并非只有汇丰和恒生自家银行卡才能用。理解 eDDA 的授权-扣款-入账链路,是理解入金产品设计的关键。详见 eDDA 支持范围


出金之旅:一笔 HKD 30,000 的银证出金

场景:用户在 moomoo App 发起出金,通过招行银证通道提取 HKD 30,000 到招行银行卡。

Step 1: 用户发起出金请求

用户在 App 点击「出金」,选择招行银行卡,输入金额 30,000 HKD。

系统调用出金服务的 WithdrawCreator.apply(),进行一系列前置检查:

检查项说明
出金限制检查用户是否被限制出金
黑名单调用 hk-withdraw-blacklist-go 检查出金黑名单
风控状态验证用户风控状态
币种-市场一致性HKD 属于 HK 市场,一致
可用出金方式检查用户银行卡支持的出金方式
手续费计算出金手续费
银行卡信息验证银行卡有效

检查通过后,系统执行原子事务,一次性完成:

  1. 创建 SBA List 记录
  2. 创建 Task 记录(出金任务)
  3. 创建 Apply 记录
  4. 添加 Flow 操作日志

深入了解

出金任务每个字段的含义 → 出金数据字典 § 核心字段 全部 12 种出金通道 → 出金方式总览

Step 2: 通道路由——系统选择出金方式

系统通过 calcMethod() 自动判断出金通道:

决策树:
  1. 用户银行卡支持 BST?
     ├─ 是 → 招行(CMBHK)支持银证 → method = auto_bs
     └─ 否 → 继续判断
  2. 银行在香港?
     ├─ 否 → method = tele_transfer(跨境电汇)
     └─ 是 → method = null(需人工选择)

招行银行卡支持 BST(银证转账),所以系统自动设置 method = auto_bs

Step 3: 确定审批流程模板

出金任务有三步审批,但并非每笔都要走全部三步:

步骤名称何时需要
Step 1: Audit高危审核仅高风险/OM 账户需要
Step 2: Confirm确认指示所有出金都需要
Step 3: Remittance汇出资金所有出金都需要

这笔不是高风险,流程模板为 [Confirm, Remittance],跳过 Audit。

Step 4: Confirm——确认指示

运营人员(或自动系统)在 Confirm 步骤:

  1. 验证银行卡 — 确认招行银行卡状态正常
  2. 确认出金方式auto_bs(银证转账)已自动设置

对于 auto_bs 通道,Confirm 步骤不会调用 SBA startTransfer()(这个动作留给 Remittance)。

操作:点击「提交到下一步」(NEXT) → 进入 Remittance。

Step 5: Remittance——汇出资金

这是关键步骤。对于 auto_bs(银证)通道,系统检查自动出金条件

#条件说明本笔情况
1通道是 auto_bs只有银证通道才支持自动出金是 → 通过
2非迁移数据排除从旧系统迁移的历史数据新数据 → 通过
3自动出金开关已开启auto_settings 表中对应币种 status = OPENHKD 已开启 → 通过
4金额在限额内amount ≤ max_amount30,000 ≤ 配置上限 → 通过
5余额充足amount ≤ available_balance余额足够 → 通过
6每日次数未超限当日同用户出金 < 10 笔首笔 → 通过

全部通过 → 系统调用 SBA startTransfer()异步),创建出金 Procedure。

深入了解

三步审批完整流程 → 出金生命周期 出金通道路由决策树 → 出金方式总览 § 通道怎么选

Step 6: 银证指令发往招行

SBA 出金编排向招行银证服务(cmb_stock_trans)发送出金指令:

出金指令处理链路:
  1. 出金服务 → SBA 出金编排 → 招行银证服务
  2. 招行银证服务用 SM2 国密算法加密请求
  3. 通过 Socket 发送到招行的 exit_server
  4. 招行处理后返回结果

SM2 加密流程

  1. 加载富途私钥
  2. 加载招行公钥证书
  3. 签名 + 加密请求数据
  4. Base64 编码后发送

Step 7: 银行回调 & 任务完成

招行处理完成后,通过银证双向链路回调系统:

回调结果处理
result = 0(成功)Task 状态 → 2(DONE)
result = -5(超时)自动切换到备用 exit_server 重试
result = -6(银行拒绝)Task 标记失败,需人工处理

我们这笔正常成功。Task 状态更新为 DONE,用户收到"出金成功"推送。

从提交到到账时间:银证通道是事件驱动的,通常 几秒到几分钟


入金 vs 出金:关键差异一览

维度入金出金
方向用户银行 → 证券账户证券账户 → 用户银行
方式数10 种12 种
核心机制自动匹配引擎(五维比对)三步审批工作流
自动化条件5 个自动入账条件6 个银证自动出金条件
每日限制10 笔/用户(自动入账)10 笔/用户(银证自动)
状态数6 个(PENDING→DONE)6 个(PENDING→DONE)
SBA 模式6 种入金编排模式统一出金编排
风控检查入金黑名单 + 白名单出金黑名单 + 高风险检测
量级分布eDDA 占 ~78%,工银 ~12%,其他 ~10%

读完之后,去哪里?

我想...去看
查一个术语是什么意思术语表
看 32 个服务的分层架构架构与数据流
查入金的 10 种方式入金方式总览
查出金的 12 种通道出金方式总览
看某家银行的完整规则银行能力矩阵
理解风控怎么拦截入金排障出金排障
了解退款和冲正机制退款与冲正
理解 SBA 编排SBA 概念与数据模型
这个页面有帮助吗?

内部业务文档 · 仅限 moomoo 团队使用