eDDA 代扣入金
本頁說明
講什麼:eDDA 授權生命週期、eDDI 扣款執行流程、匯豐與恒生的協議差異、異常場景與錯誤碼 適合誰:需要理解"用戶一鍵入金"背後完整鏈路的產品經理 前置閱讀:入金方式總覽預計閱讀:5 分鐘 負責人:入金產品經理
核心要點:eDDA 是授權,eDDI 是扣款——兩個分離步驟實現"用戶一鍵入金"。匯豐用 OTP 短信 + 令牌桶並發,恒生用數字證書 + 悲觀鎖串行,協議差異是兩家銀行最大的區別。
快速跳轉 — 你可能想做的事:
- 用戶 eDDA 授權失敗,怎麼辦?→ 授權失敗錯誤碼 + 排障 § 場景七
- 用戶 eDDA 扣款被拒,怎麼辦?→ 恒生扣款被拒 / 匯豐扣款被拒
- 匯豐和恒生有什麼區別?→ 匯豐 vs 恒生協議差異
- 想給新銀行加 eDDA?→ 變更指南 § 新增 eDDA
- 週末/維護時段能用 eDDA 嗎?→ 處理時段與維護窗口
eDDA 與 eDDI 是什麼
eDDA(Electronic Direct Debit Authorization)和 eDDI(Electronic Direct Debit Instruction)是兩個分離的步驟:
| 概念 | 全稱 | 作用 | 頻率 |
|---|---|---|---|
| eDDA | 電子直接付款授權 | 用戶授權 moomoo 從其銀行帳戶扣款 | 一次性,授權後長期有效 |
| eDDI | 電子直接付款指令 | moomoo 向銀行發送具體的扣款指令 | 每次入金一次 |
為什麼分離:監管要求銀行在執行代扣前,必須先獲得帳戶持有人的明確授權。eDDA 解決"誰允許扣",eDDI 解決"扣多少"。
與出金無關:eDDA/eDDI 僅用於入金代扣。匯豐和恒生的出金通道是企業網銀轉賬,不是 eDDI。
PM 視角
eDDA 入金是轉化率最高的入金方式——用戶無需切換到銀行 App,在 moomoo 內一鍵完成。理解這條鏈路的每個環節,是優化入金體驗的基礎。
授權生命週期
授權狀態機
| 狀態碼 | 常量 | 含義 | 用戶感知 |
|---|---|---|---|
| 3 | EDDA_STATUS_WAITING | 等待授權——申請已創建,尚未發送到銀行 | "授權處理中" |
| 1 | EDDA_STATUS_PENDING | 授權中——請求已發送,等待銀行回覆 | "授權處理中" |
| 2 | EDDA_STATUS_EFFECT | 授權成功——可以發起 eDDI 扣款 | "已授權" |
| 0 | EDDA_STATUS_FAIL | 授權失敗——銀行拒絕 | 顯示具體失敗原因 |
數據表:setup_eddis,按 uid + bank_card_number 唯一標識一條授權記錄。
授權輪詢機制
授權請求發送後,銀行不會立即返回結果。系統通過 SetupEddaCheckAuthorizationJob 定時輪詢銀行授權狀態:
| 參數 | 值 | 說明 |
|---|---|---|
| 輪詢間隔 | 600 秒(10 分鐘) | 每次檢查一次銀行端授權狀態 |
| 最大重試 | ~3,000 次 | 約 20 天後停止輪詢 |
| 觸發時機 | 用戶提交授權申請後入隊 | SetupEddaCheckAuthorizationJob::enqueue() |
配置位置
- 輪詢間隔:硬編碼於
SetupEddaCheckAuthorizationJob的 enqueue delay - 最大重試:Job 框架的 max_attempts 配置
- 代碼路徑:
deposit/src/app/Business/Job/Deposit/SetupEddaCheckAuthorizationJob.php
授權失敗錯誤碼
銀行返回的錯誤碼存儲在 setup_eddis.error_code 字段。以下是完整的錯誤碼映射:
| 錯誤碼 | 失敗原因 | 用戶提示 | 失敗類型 |
|---|---|---|---|
MFISAC01 | 帳戶號碼錯誤 | 請輸入正確的帳戶號碼 | eDDA 授權 |
MPP01005 | 證件類型/號碼錯誤 | 請核對證件類型和號碼 | eDDA 授權 |
MPP01006 | 與銀行綁定手機號不一致 | 請輸入正確的手機號 | eDDA 授權 |
MPP01007 | 授權帳戶與姓名不匹配 | 請核對帳戶與姓名 | eDDA 授權 |
MPP01008 | 銀行未綁定手機號碼 | 請聯繫銀行綁定手機號 | eDDA 授權 |
MPP01023 | 銀行綁定手機號碼錯誤 | 請聯繫銀行修改綁定手機號 | eDDA 授權 |
MPP02003 | 銀行帳戶號碼錯誤 | 請重新輸入正確的帳戶號碼 | eDDA 授權 |
MPP02011 | 銀行帳戶號碼錯誤 | 請重新輸入正確的帳戶號碼 | eDDA 授權 |
MPP02013 | 銀行未綁定手機號碼 | 請聯繫銀行綁定手機號 | eDDA 授權 |
MPP02035 | 銀行帳戶號碼錯誤 | 請重新輸入正確的帳戶號碼 | eDDA 授權 |
MPP02040 | 銀行帳戶號碼錯誤 | 請重新輸入正確的帳戶號碼 | eDDA 授權 |
MPP03001 | 銀行帳戶類型異常 | 請聯繫銀行處理 | eDDA 授權 |
MPP04000 | 驗證碼無效 | 請重新獲取 | eDDA 授權 |
MPP04003 | 驗證碼錯誤 | 請重新輸入 | eDDA 授權 |
MPP04004 | 驗證碼已過期 | 請重新獲取 | eDDA 授權 |
MPP06001 | 銀行帳戶狀態異常 | 請聯繫銀行處理 | eDDA 授權 |
ECH09001 | 銀行授權失敗(通用) | 請確認資訊正確後重新授權 | eDDA 授權 |
配置位置
代碼路徑:deposit/src/app/Business/SetupEddi.php:91-113 — errorCodeMessageDict()
扣款執行流程
任務鏈
用戶發起 eDDA 入金後,系統通過異步 Job 鏈執行扣款:
| 步驟 | Job / 方法 | 職責 |
|---|---|---|
| 1 | ApplyFollowJob | 檢查申請狀態,路由到對應銀行的 eDDI 創建邏輯 |
| 2 | Eddi::applyHsEddi() / Eddi::applyHsbcEddi() | 獲取 eDDA 授權資訊,標記 Apply 為已使用,創建扣款記錄 |
| 3 | SBA HsEddi/HsbcEddi.create() | 向 SBA 服務發送扣款 Procedure 創建請求 |
| 4 | HsEddiResultJob / HsbcEddiResultJob | 輪詢 SBA Procedure 狀態,獲取銀行處理結果 |
| 5 | 入賬 / 失敗處理 | 成功:寫入銀行流水 + SBA 執行入賬;失敗:更新 setup_eddis 狀態 |
防重複扣款機制
| 機制 | 實現方式 | 防護場景 |
|---|---|---|
| Apply 佔用鎖 | Apply::setUsed() 原子更新 | 同一申請不會被兩個 Job 同時處理 |
| apply_id 唯一索引 | hsbc_eddis / hs_eddis 表的 unique index | 同一申請只生成一條扣款記錄 |
| request_id 冪等 | SBA 端按 request_id 去重 | 網絡重試不會導致重複扣款 |
| SBA 創建重試 | HsbcEddiSBACreateRetryJob / HsEddiSBACreateRetryJob | SBA 創建失敗時延遲 60 秒重試 |
eDDI 入金類型
eDDI 入金區分為 6 種子類型,決定入金後資金是否被凍結:
| 代碼 | 常量 | 含義 | 資金是否凍結 |
|---|---|---|---|
| 1 | FOUNDING_AIP | 基金定投 | 否 |
| 2 | STOCK_MP | 股票定投 | 否 |
| 3 | FUND_PURCHASE | 購買基金 | 否 |
| 11 | FUND_HOLD | 基金定投 + 凍結 | 是 |
| 21 | STOCK_HOLD | 股票定投 + 凍結 | 是 |
| 31 | FUND_PURCHASE_HOLD | 購買基金 + 凍結 | 是 |
凍結的含義:代碼 11/21/31 的入金,資金到賬後會被系統凍結,預留給對應的投資操作(定投扣款、基金申購)。凍結釋放時機由投資側系統控制。
對應的 DepositType 為 NORMAL_HOLD = 11(入金類型速查 → 入金規則速查 § 入金類型)。
配置位置
代碼路徑:deposit/src/app/Common/EddiDepositType.php
HOLD_LIST = [11, 21, 31]— 需要凍結的類型列表ALL_LIST = [1, 2, 3, 11, 21, 31]— 全部類型
如果需求變更:eDDA/eDDI 相關
| 變更 | 改動位置 | 說明 |
|---|---|---|
| 新增 eDDI 入金類型 | EddiDepositType.php + SBA 編排配置 | 加枚舉值,配置是否凍結 |
| 修改扣款幣種 | sba_hsbc_eddi / sba_hase_eddi 請求參數 | 當前僅支持 HKD |
| 修改輪詢間隔 | sba_hsbc_eddi_worker.ini / sba_hase_eddi 配置 | 調整 rush/normal 間隔 |
| 修改令牌桶速率(匯豐) | sba_hsbc_eddi token_bucket 守護進程 | 調整 frequency 參數 |
| 更換恒生數字證書 | sba_hase_eddi/conf/ | 替換 P12 文件和密碼 |
| 新增 eDDA 支持銀行 | 見 入金變更指南 § 場景八 | 涉及商務+技術+SBA,數月週期 |
eDDA 支持範圍
匯豐通道支持的銀行(15 家)
通過匯豐通道發起的 eDDA,支持以下 15 家銀行的個人帳戶:
| 銀行 | 銀行代碼 | 接入日期 | 備註 |
|---|---|---|---|
| 匯豐 HSBC | 004 | 初始 | 同行扣款 |
| 恒生 Hang Seng | 024 | 初始 | 跨行扣款 |
| 中銀 BOCHK | 012 | 2021-06 | 跨行扣款 |
| 南洋商業銀行 | 041 | 2021-07 | 跨行扣款 |
| 富融銀行 Fusion Bank | — | 2021-09 | 虛擬銀行 |
| 工銀亞洲 ICBC(Asia) | 072 | 2021-09 | 跨行扣款 |
| 渣打 SCB | 003 | 2021-12 | 跨行扣款 |
| 眾安銀行 ZA Bank | — | 2021-12 | 虛擬銀行 |
| 中信銀行國際 CNCBI | 018 | 2021-12 | 跨行扣款,卡號需 15 位格式(前 3 位補 0) |
| 永隆銀行 CMB Wing Lung | 238 | 2021-12 | 跨行扣款 |
| 天星銀行 Airstar | — | 2022-09 | 虛擬銀行 |
| 建銀亞洲 CCB(Asia) | 009 | 2023-10 | 跨行扣款 |
| LIVI BANK | — | 2024-01 | 虛擬銀行 |
| 招商銀行 | — | 2024-03 | 跨行扣款 |
| 大新銀行 Dah Sing | 040 | 2024-03 | 跨行扣款 |
恒生通道支持的銀行(12 家)
通過恒生通道發起的 eDDA,支持以下 12 家銀行的個人帳戶:
兩條通道均支持(7 家)——這些銀行同時支持匯豐通道和恒生通道,優先推薦匯豐通道:
| 銀行 | 銀行代碼 | 備註 |
|---|---|---|
| 恒生 Hang Seng | 024 | 同行扣款 |
| 匯豐 HSBC | 004 | 跨行扣款 |
| 中銀 BOCHK | 012 | 跨行扣款 |
| 南洋商業銀行 | 041 | 跨行扣款 |
| 工銀亞洲 ICBC(Asia) | 072 | 跨行扣款 |
| 渣打 SCB | 003 | 跨行扣款 |
| 永隆銀行 CMB Wing Lung | 238 | 跨行扣款 |
恒生通道專屬(5 家)——以下銀行僅能通過恒生通道使用 eDDA,不支持匯豐通道:
| 銀行 | 銀行代碼 | 備註 |
|---|---|---|
| 花旗銀行 Citibank | 250 | 跨行扣款 |
| 東亞銀行 BEA | 015 | 跨行扣款,注意"每日單筆"頻率限制 |
| 華僑永亨銀行 OCBC Wing Hang | — | 跨行扣款 |
| 集友銀行 Chiyu Banking | — | 跨行扣款 |
| 交通銀行香港分行 BANKCOMM | 382 | 需櫃台申請 |
支持的證件類型
eDDA 授權時需驗證用戶證件資訊,支持的證件類型因銀行而異:
| 證件類型 | 匯豐通道 | 恒生通道 | 說明 |
|---|---|---|---|
| 香港身份證(HKID) | 支持 | 支持 | 最常見,覆蓋大部分用戶 |
| 中國居民身份證 | 支持 | 支持 | 大陸開戶用戶 |
| 護照 | 支持 | 支持 | 海外用戶 |
不支持的場景
以下場景不支持 eDDA 入金,PM 和運營需注意:
| 場景 | 原因 | 用戶提示建議 |
|---|---|---|
| 企業帳戶 | eDDA 僅支持個人帳戶,銀行側不允許企業帳戶授權 | 引導使用網銀轉賬或 FPS |
| 信銀國際卡號非 15 位 | 信銀國際銀行卡號需補齊至 15 位(前 3 位補 0),否則授權失敗 | 引導用戶確認正確的卡號格式 |
| 天星銀行超日限 | 天星 eDDA 單日限額 HKD 200,000,每日累計不超過 5 筆(合計 HKD 1,000,000) | 提示用戶分多日入金或使用其他通道 |
匯豐 vs 恒生協議差異
| 維度 | 匯豐 HSBC | 恒生 Hang Seng |
|---|---|---|
| TransType | 303 (HSBC_EDDI) | 302 (HASE_EDDI) |
| 入金方式碼 | eddaHSBC(代碼 9) | edda(代碼 8) |
| 通信協議 | HTTPS REST API | SM2 簽名 HTTP POST |
| 加密方式 | TLS(標準 HTTPS) | 香港郵政電子證書 SM2 數字簽名 |
| SBA 服務 | sba_hsbc_eddi | sba_hase_eddi |
| 數據表 | hsbc_eddis | hs_eddis |
| 授權要求(同行) | 必須預授權 | 必須預授權 |
| 授權要求(跨行+線上開戶) | 允許後置授權 | 不允許,必須預授權 |
| 扣款幣種 | 僅 HKD | 僅 HKD |
| 扣款結果 Job | HsbcEddiResultJob | HsEddiResultJob |
| SBA 創建重試 Job | HsbcEddiSBACreateRetryJob | HsEddiSBACreateRetryJob |
授權前置 vs 後置
PM 關注點:恒生的"必須預授權"意味著新用戶首次入金的流程更長(需等待授權生效),而匯豐跨行+線上開戶場景允許"先入金後授權",降低了首次入金門檻。
完整扣款流程對比
下圖並排展示匯豐和恒生從用戶點擊到資金到賬的完整鏈路差異:
關鍵差異點:
- 通信協議:匯豐用標準 HTTPS REST API;恒生用 SM2 簽名 HTTP POST(國密算法)
- 數據表:匯豐寫
hsbc_eddis;恒生寫hs_eddis - 輪詢 Job:匯豐用
HsbcEddiResultJob;恒生用HsEddiResultJob - 扣款回調時間:兩家銀行的處理時間相近(通常幾分鐘),但恒生在週日維護窗口(00:00~08:30)更短
恒生扣款被拒錯誤碼
恒生 eDDI 扣款失敗時,銀行返回的錯誤碼和對應含義:
| 錯誤碼 | 含義 | 用戶提示 |
|---|---|---|
BRC_8I1 | 餘額不足 | 銀行帳戶餘額不足,銀行可能收取手續費且取消授權 |
BRC_8RZ | 帳戶異常 | 銀行帳戶異常,請聯繫銀行 |
BRC_8RW + FP2414 | 未查詢到授權 | 無法扣款,請聯繫銀行 |
BRC_8RW + FP2415 | 授權未生效 | 請至銀行激活 eDDA |
BRC_8RW + FP2416 | 授權已過期 | 請至銀行重新授權 |
BRC_8RW + FP2417 | 超過授權限額 | 請減少金額後重新發起 |
000 | 通用失敗 | 請聯繫銀行確認原因 |
匯豐扣款被拒錯誤碼
| 錯誤碼 | 含義 | 用戶提示 |
|---|---|---|
MPP02020 | 授權已取消/不存在 | 請聯繫銀行重新授權 |
MPP02021 | 付款帳戶已關閉 | 請聯繫銀行 |
MPP02022 | 超過 eDDA 扣款上限 | 請聯繫銀行調整限額 |
MPP02023 | 授權已取消/不存在 | 請聯繫銀行重新授權 |
MPP02038 | 授權已休眠 | 請聯繫銀行重新授權 |
MPP02039 | 授權已過期 | 請聯繫銀行重新授權 |
MPP05000 | 超過扣款上限 | 請聯繫銀行調整限額 |
配置位置
- 恒生錯誤碼:
deposit/src/app/Business/Eddi.php:341-377—hsRejectMessage() - 匯豐錯誤碼:
deposit/src/app/Business/Eddi.php:379-397—hsbcRejectMessage()
處理時段與維護窗口
| 維度 | 恒生 | 匯豐 | 說明 |
|---|---|---|---|
| 工作時段 | 週一 07:00 ~ 週六 10:00 | 週一 07:00 ~ 週六 10:00 | 此時段內 SBA 會處理 eDDI 指令 |
| 週日維護 | 00:00 ~ 08:30 | 00:00 ~ 12:00 | 銀行系統維護,不接受請求 |
| 非工作時段行為 | 指令進入 Blank 狀態,下個工作時段自動激活 | 同左 | 用戶不會感知延遲 |
| 對賬暫停 | 16:05 ~ 16:10 | 16:05 ~ 16:10 | 與全局 2412 規則一致 |
非工作時段提交的處理:如果用戶在週六 10:00 之後提交 eDDA 入金,系統會創建 Apply 和 setup_eddis 記錄,但 SBA 的 eDDI Procedure 不會立即執行。Procedure 進入 Blank 狀態,等到下週一 07:00 自動激活並發送扣款指令到銀行。
配置位置
- 恒生維護窗口:
sba_hase_eddi服務常量配置 - 匯豐維護窗口:
sba_hsbc_eddi服務常量配置 - 2412 暫停規則:
deposit/src/app/Business/DepositConfigNew.php:603-641
setup_eddis 完整狀態流轉
eDDA 入金涉及 setup_eddis 表的狀態流轉,覆蓋從授權到入金完成的全過程:
| 狀態碼 | 常量 | 含義 | 後續動作 |
|---|---|---|---|
| 0 | STATUS_PENDING | 待處理——記錄已創建 | applySetupEddi() 觸發處理 |
| 1 | STATUS_PROCESSING | 處理中——扣款指令已發送 | 等待銀行回調 |
| 2 | STATUS_DEDUCTED | 扣款完成——銀行已扣款 | SBA 執行入賬 |
| 3 | STATUS_FAIL | 失敗——授權失敗或扣款失敗 | 通知用戶,記錄 error_code |
| 4 | STATUS_FINISH | 入金完成——資金已到賬 | 流程結束 |
特殊場景:STATUS_DEDUCTED → STATUS_FAIL(CRM 駁回)——當銀行已完成扣款但後台運營終止入金時,error_code 為 REJECT_BY_CRM,此時需要人工處理退款。
eDDA 異常場景速查
| 異常 | 現象 | 排查路徑 | 處理方式 |
|---|---|---|---|
| 授權長時間未生效 | 用戶等待超過 24h | 查 setup_eddis.edda_status,確認是否仍在 PENDING | 引導用戶聯繫銀行確認 |
| 授權失敗 | 用戶看到錯誤提示 | 查 setup_eddis.error_code,對照上方錯誤碼表 | 按錯誤碼引導用戶修正資訊 |
| 扣款失敗 | Apply 狀態變為已駁回 | 查 hsbc_eddis / hs_eddis 表的 reject 資訊 | 對照扣款錯誤碼表處理 |
| 扣款成功但未入賬 | 銀行已扣款,餘額未增加 | 查 setup_eddis.status 是否卡在 DEDUCTED(2) | 檢查 SBA Procedure 狀態 |
| 扣款超時 | 銀行無回調 | 查 ResultJob 輪詢狀態 | 等待輪詢完成或人工查詢銀行 |
| 授權失效 | 歷史已授權用戶突然無法入金 | 查銀行端授權狀態(可能被用戶在銀行側取消) | 引導用戶重新授權 |
詳細的排障流程 → 入金排障 § eDDA 授權失敗
分步 Runbook:eDDA 扣款成功但未入賬(SBA Procedure 掛起)
現象:銀行已扣款(setup_eddis.status = 2 DEDUCTED),但用戶餘額未增加。
第 1 分鐘 — 定位阻塞點
- 查
setup_eddis表:確認status = 2(已扣款) - 查 SBA Procedure 狀態:是 Running / Pending / Failed?
- 如果 Procedure 是 Running 且超過 10 分鐘 → 異常
第 2~5 分鐘 — 排查 SBA 異常 4. 查 SBA 服務日誌:Procedure 是否卡在某個 Step? 5. 常見卡點:
- CRM 帳戶鎖定(正在執行其他操作)→ 等待釋放
- SBA 餘額計算失敗 → 檢查帳戶數據一致性
- SBA 服務本身異常 → 檢查 SBA 服務狀態
第 5~15 分鐘 — 處理 6. 如果 Procedure 狀態是 Failed → 需要手動觸發重新執行(聯繫技術支持) 7. 如果 Procedure 狀態是 Pending → 檢查是否有前置 Procedure 在排隊 8. 如果 SBA 服務異常 → 等服務恢復後 Procedure 會自動繼續
用戶溝通:告知用戶"銀行已扣款成功,資金正在處理中",避免用戶恐慌
超過 30 分鐘未解決 → 升級到入金技術負責人
餘額不足自動取消授權
恒生銀行有一個特殊行為:當 eDDI 扣款因餘額不足(BRC_8I1)被拒時,銀行可能自動取消該用戶的 eDDA 授權。這意味著:
- 用戶需要先往銀行帳戶充值
- 然後還需要重新完成 eDDA 授權才能再次使用 eDDA 入金
- 運營需要主動告知用戶這個情況,否則用戶會以為充值後就能繼續入金
匯豐沒有這個行為——餘額不足被拒後,授權仍然有效,充值後可直接重試。
處理建議:如果用戶反饋"之前可以用 eDDA,現在不行了",先檢查是否是恒生用戶 + 曾經因餘額不足被拒。如果是 → 引導重新授權。
常見誤解
| 誤解 | 事實 |
|---|---|
| "eDDA 和 eDDI 是出金通道" | 不是。eDDA/eDDI 僅用於入金代扣。匯豐/恒生的出金走企業網銀轉賬,與 eDDA 無關 |
| "所有銀行都能用 eDDA" | 匯豐通道支持 15 家銀行的個人帳戶,恒生通道支持 12 家(含 5 家專屬)。企業帳戶不支持。詳見 支持範圍 |
| "eDDA 授權一次就永久有效" | 授權可能因為銀行側維護、用戶在銀行 App 取消、餘額不足自動取消(恒生)而失效 |
| "eDDA 入金需要匹配引擎" | 不需要。eDDA 是系統主動發起扣款,天然知道資金歸屬,完全跳過匹配引擎 |
| "匯豐和恒生的 eDDA 實現是一樣的" | 協議完全不同。匯豐用 HTTPS REST API,恒生用 SM2 簽名。數據表、Job、SBA 服務都是獨立的 |
| "週末可以用 eDDA 入金" | 週六 10:00 後到週日結束是非工作時段。提交的請求會排隊到週一 07:00 才執行 |
讀完之後
| 我想... | 去看 |
|---|---|
| 了解 eDDA 授權如何開啟入金通道 | 銀行卡綁定與入金授權 § eDDA |
| 跟著一筆 eDDA 入金走全程 | 新人導讀 § eDDA 入金 |
| 看 eDDA 授權/扣款失敗怎麼處理 | 入金排障 |
| 看運營側 eDDA 排障操作指引 | eDDA 排障指引 |
| 查 eDDI 類型碼和狀態碼 | 入金規則速查 |
| 深入了解匯豐 eDDA 實現 | 匯豐 HSBC |
| 深入了解恒生 eDDA 實現 | 恒生 Hang Seng |
| 了解 SBA 編排如何執行入賬 | SBA 資金編排 |