Skip to content

eDDA Direct Debit Deposit

About This Page

What: eDDA authorization lifecycle, eDDI debit execution flow, protocol differences between HSBC and Hang Seng, exception scenarios and error codes Audience: Product managers who need to understand the complete chain behind "user one-click deposit" Prerequisites: Deposit Methods OverviewReading time: 5 minutes Owner: Deposit Product Manager

Key Takeaways: eDDA is authorization, eDDI is the debit instruction — two separate steps enabling "user one-click deposit." HSBC uses OTP SMS + token bucket concurrency; Hang Seng uses digital certificate + pessimistic lock serialization. Protocol differences are the biggest distinction between the two banks.


Quick Navigation — What you might want to do:

What are eDDA and eDDI

eDDA (Electronic Direct Debit Authorization) and eDDI (Electronic Direct Debit Instruction) are two separate steps:

ConceptFull NamePurposeFrequency
eDDAElectronic Direct Debit AuthorizationUser authorizes moomoo to debit from their bank accountOne-time, valid long-term after authorization
eDDIElectronic Direct Debit Instructionmoomoo sends a specific debit instruction to the bankOnce per deposit

Why separate: Regulatory requirements mandate that banks must obtain explicit authorization from account holders before executing direct debits. eDDA solves "who is allowed to debit," eDDI solves "how much to debit."

Unrelated to withdrawals: eDDA/eDDI is only used for deposit direct debit. HSBC and Hang Seng withdrawal channels use corporate online banking transfers, not eDDI.

PM Perspective

eDDA deposit has the highest conversion rate among deposit methods — users don't need to switch to a banking app, completing everything with one click within moomoo. Understanding every link in this chain is the foundation for optimizing the deposit experience.


Authorization Lifecycle

Authorization State Machine

Status CodeConstantMeaningUser Perception
3EDDA_STATUS_WAITINGWaiting — request created, not yet sent to bank"Authorization processing"
1EDDA_STATUS_PENDINGPending — request sent, awaiting bank response"Authorization processing"
2EDDA_STATUS_EFFECTEffective — can initiate eDDI debit"Authorized"
0EDDA_STATUS_FAILFailed — bank rejectedShows specific failure reason

Data Table: setup_eddis, uniquely identified by uid + bank_card_number.

Authorization Polling Mechanism

After the authorization request is sent, the bank doesn't return results immediately. The system polls bank authorization status via SetupEddaCheckAuthorizationJob:

ParameterValueDescription
Polling interval600 seconds (10 minutes)Checks bank-side authorization status once per interval
Max retries~3,000 timesStops polling after about 20 days
Trigger timingEnqueued after user submits authorization requestSetupEddaCheckAuthorizationJob::enqueue()
Configuration Location
  • Polling interval: hard-coded in SetupEddaCheckAuthorizationJob enqueue delay
  • Max retries: Job framework max_attempts config
  • Code path: deposit/src/app/Business/Job/Deposit/SetupEddaCheckAuthorizationJob.php

Authorization Failure Error Codes

Error codes returned by the bank are stored in the setup_eddis.error_code field. Complete error code mapping:

Error CodeFailure ReasonUser PromptFailure Type
MFISAC01Incorrect account numberPlease enter the correct account numbereDDA Authorization
MPP01005Incorrect ID type/numberPlease verify ID type and numbereDDA Authorization
MPP01006Phone number doesn't match bank bindingPlease enter the correct phone numbereDDA Authorization
MPP01007Account and name don't matchPlease verify account and nameeDDA Authorization
MPP01008Bank has no phone number boundPlease contact bank to bind phone numbereDDA Authorization
MPP01023Incorrect phone number bound at bankPlease contact bank to update bound phoneeDDA Authorization
MPP02003Incorrect bank account numberPlease re-enter the correct account numbereDDA Authorization
MPP02011Incorrect bank account numberPlease re-enter the correct account numbereDDA Authorization
MPP02013Bank has no phone number boundPlease contact bank to bind phone numbereDDA Authorization
MPP02035Incorrect bank account numberPlease re-enter the correct account numbereDDA Authorization
MPP02040Incorrect bank account numberPlease re-enter the correct account numbereDDA Authorization
MPP03001Bank account type abnormalPlease contact bankeDDA Authorization
MPP04000Invalid verification codePlease request a new oneeDDA Authorization
MPP04003Incorrect verification codePlease re-entereDDA Authorization
MPP04004Verification code expiredPlease request a new oneeDDA Authorization
MPP06001Bank account status abnormalPlease contact bankeDDA Authorization
ECH09001Bank authorization failed (generic)Please verify info is correct and re-authorizeeDDA Authorization
Configuration Location

Code path: deposit/src/app/Business/SetupEddi.php:91-113errorCodeMessageDict()


Debit Execution Flow

Job Chain

After a user initiates an eDDA deposit, the system executes the debit through an async Job chain:

StepJob / MethodResponsibility
1ApplyFollowJobCheck application status, route to corresponding bank's eDDI creation logic
2Eddi::applyHsEddi() / Eddi::applyHsbcEddi()Get eDDA authorization info, mark Apply as used, create debit record
3SBA HsEddi/HsbcEddi.create()Send debit Procedure creation request to SBA service
4HsEddiResultJob / HsbcEddiResultJobPoll SBA Procedure status, get bank processing result
5Credit / Failure handlingSuccess: write bank statement + SBA executes credit; Failure: update setup_eddis status

Duplicate Debit Prevention

MechanismImplementationProtection Scenario
Apply occupation lockApply::setUsed() atomic updateSame application won't be processed by two Jobs simultaneously
apply_id unique indexUnique index on hsbc_eddis / hs_eddis tablesSame application only generates one debit record
request_id idempotencySBA deduplicates by request_idNetwork retries won't cause duplicate debits
SBA create retryHsbcEddiSBACreateRetryJob / HsEddiSBACreateRetryJobRetry after 60 seconds if SBA creation fails

eDDI Deposit Types

eDDI deposits are divided into 6 subtypes, determining whether funds are frozen after deposit:

CodeConstantMeaningFunds Frozen
1FOUNDING_AIPFund DCANo
2STOCK_MPStock DCANo
3FUND_PURCHASEFund purchaseNo
11FUND_HOLDFund DCA + freezeYes
21STOCK_HOLDStock DCA + freezeYes
31FUND_PURCHASE_HOLDFund purchase + freezeYes

Freeze meaning: Deposits with codes 11/21/31 have funds frozen after crediting, reserved for the corresponding investment operations (DCA debit, fund subscription). Freeze release timing is controlled by the investment-side system.

Corresponding DepositType is NORMAL_HOLD = 11 (deposit type reference -> Deposit Quick Reference - Deposit Type).

Configuration Location

Code path: deposit/src/app/Common/EddiDepositType.php

  • HOLD_LIST = [11, 21, 31] — list of types requiring freeze
  • ALL_LIST = [1, 2, 3, 11, 21, 31] — all types
If Requirements Change: eDDA/eDDI Related
ChangeLocationNotes
Add new eDDI deposit typeEddiDepositType.php + SBA orchestration configAdd enum value, configure whether to freeze
Modify debit currencysba_hsbc_eddi / sba_hase_eddi request parametersCurrently only supports HKD
Modify polling intervalsba_hsbc_eddi_worker.ini / sba_hase_eddi configAdjust rush/normal interval
Modify token bucket rate (HSBC)sba_hsbc_eddi token_bucket daemonAdjust frequency parameter
Replace Hang Seng digital certificatesba_hase_eddi/conf/Replace P12 file and password
Add new eDDA supported bankSee Deposit Change Guide - Scenario 8Involves commercial + technical + SBA, months-long cycle

eDDA Supported Scope

Banks Supported via HSBC Channel (15 banks)

eDDA initiated through the HSBC channel supports personal accounts at the following 15 banks:

BankBank CodeOnboard DateNotes
HSBC004InitialSame-bank debit
Hang Seng024InitialCross-bank debit
BOCHK0122021-06Cross-bank debit
Nanyang Commercial Bank0412021-07Cross-bank debit
Fusion Bank2021-09Virtual bank
ICBC(Asia)0722021-09Cross-bank debit
SCB0032021-12Cross-bank debit
ZA Bank2021-12Virtual bank
CNCBI0182021-12Cross-bank debit, card number requires 15-digit format (pad 0s in first 3 digits)
CMB Wing Lung2382021-12Cross-bank debit
Airstar Bank2022-09Virtual bank
CCB(Asia)0092023-10Cross-bank debit
LIVI BANK2024-01Virtual bank
CMB2024-03Cross-bank debit
Dah Sing Bank0402024-03Cross-bank debit

Banks Supported via Hang Seng Channel (12 banks)

eDDA initiated through the Hang Seng channel supports personal accounts at the following 12 banks:

Supported by both channels (7 banks) — these banks support both HSBC and Hang Seng channels; HSBC channel is recommended:

BankBank CodeNotes
Hang Seng024Same-bank debit
HSBC004Cross-bank debit
BOCHK012Cross-bank debit
Nanyang Commercial Bank041Cross-bank debit
ICBC(Asia)072Cross-bank debit
SCB003Cross-bank debit
CMB Wing Lung238Cross-bank debit

Hang Seng channel exclusive (5 banks) — these banks can only use eDDA through the Hang Seng channel, not supported by HSBC:

BankBank CodeNotes
Citibank250Cross-bank debit
BEA (Bank of East Asia)015Cross-bank debit, note "daily single" frequency limit
OCBC Wing HangCross-bank debit
Chiyu BankingCross-bank debit
Bank of Communications HK Branch382Requires counter application

Supported ID Types

eDDA authorization requires user ID verification; supported ID types vary by bank:

ID TypeHSBC ChannelHang Seng ChannelNotes
HKID (Hong Kong Identity Card)SupportedSupportedMost common, covers most users
PRC Identity CardSupportedSupportedMainland account opening users
PassportSupportedSupportedOverseas users

Unsupported Scenarios

The following scenarios do not support eDDA deposit; PMs and operations should note:

ScenarioReasonSuggested User Prompt
Corporate accountseDDA only supports personal accounts; bank side does not allow corporate account authorizationGuide to use online banking transfer or FPS
CNCBI card number not 15 digitsCNCBI bank card numbers must be padded to 15 digits (3 leading zeros), otherwise authorization failsGuide user to confirm correct card number format
Airstar Bank exceeds daily limitAirstar eDDA daily limit HKD 200,000, max 5 transactions per day (total HKD 1,000,000)Prompt user to split across multiple days or use another channel

HSBC vs Hang Seng Protocol Differences

DimensionHSBCHang Seng
TransType303 (HSBC_EDDI)302 (HASE_EDDI)
Deposit method codeeddaHSBC (code 9)edda (code 8)
Communication protocolHTTPS REST APISM2 signed HTTP POST
EncryptionTLS (standard HTTPS)HK Post e-Certificate SM2 digital signature
SBA Servicesba_hsbc_eddisba_hase_eddi
Data Tablehsbc_eddishs_eddis
Authorization requirement (same-bank)Must pre-authorizeMust pre-authorize
Authorization requirement (cross-bank + online opening)Allows post-authorizationNot allowed, must pre-authorize
Debit currencyHKD onlyHKD only
Debit result JobHsbcEddiResultJobHsEddiResultJob
SBA create retry JobHsbcEddiSBACreateRetryJobHsEddiSBACreateRetryJob

Pre-authorization vs Post-authorization

PM Focus: Hang Seng's "must pre-authorize" means new users have a longer first deposit flow (need to wait for authorization to take effect), while HSBC's cross-bank + online opening scenario allows "deposit first, authorize later," lowering the first deposit barrier.

Complete Debit Flow Comparison

The diagram below shows the complete chain differences between HSBC and Hang Seng from user click to fund crediting:

Key Differences:

  • Communication protocol: HSBC uses standard HTTPS REST API; Hang Seng uses SM2 signed HTTP POST (national encryption algorithm)
  • Data table: HSBC writes to hsbc_eddis; Hang Seng writes to hs_eddis
  • Polling Job: HSBC uses HsbcEddiResultJob; Hang Seng uses HsEddiResultJob
  • Debit callback time: Both banks have similar processing times (typically minutes), but Hang Seng has a shorter Sunday maintenance window (00:00~08:30)

Hang Seng Debit Rejection Error Codes

Error codes and meanings when Hang Seng eDDI debit fails:

Error CodeMeaningUser Prompt
BRC_8I1Insufficient balanceBank account has insufficient balance; bank may charge a fee and cancel authorization
BRC_8RZAccount abnormalBank account abnormal, please contact bank
BRC_8RW + FP2414Authorization not foundCannot debit, please contact bank
BRC_8RW + FP2415Authorization not effectivePlease activate eDDA at bank
BRC_8RW + FP2416Authorization expiredPlease re-authorize at bank
BRC_8RW + FP2417Exceeded authorization limitPlease reduce amount and retry
000Generic failurePlease contact bank to confirm reason

HSBC Debit Rejection Error Codes

Error CodeMeaningUser Prompt
MPP02020Authorization cancelled/does not existPlease contact bank to re-authorize
MPP02021Payment account closedPlease contact bank
MPP02022Exceeded eDDA debit limitPlease contact bank to adjust limit
MPP02023Authorization cancelled/does not existPlease contact bank to re-authorize
MPP02038Authorization dormantPlease contact bank to re-authorize
MPP02039Authorization expiredPlease contact bank to re-authorize
MPP05000Exceeded debit limitPlease contact bank to adjust limit
Configuration Location
  • Hang Seng error codes: deposit/src/app/Business/Eddi.php:341-377hsRejectMessage()
  • HSBC error codes: deposit/src/app/Business/Eddi.php:379-397hsbcRejectMessage()

Processing Hours & Maintenance Windows

DimensionHang SengHSBCNotes
Business hoursMon 07:00 ~ Sat 10:00Mon 07:00 ~ Sat 10:00SBA processes eDDI instructions during this window
Sunday maintenance00:00 ~ 08:3000:00 ~ 12:00Bank system maintenance, no requests accepted
Off-hours behaviorInstructions enter Blank status, auto-activated next business periodSameUsers won't perceive delay
Reconciliation pause16:05 ~ 16:1016:05 ~ 16:10Consistent with global 2412 rule

Processing of off-hours submissions: If a user submits an eDDA deposit after Saturday 10:00, the system creates Apply and setup_eddis records, but the SBA eDDI Procedure won't execute immediately. The Procedure enters Blank status, auto-activating Monday 07:00 to send the debit instruction to the bank.

Configuration Location
  • Hang Seng maintenance window: sba_hase_eddi service constant config
  • HSBC maintenance window: sba_hsbc_eddi service constant config
  • 2412 pause rule: deposit/src/app/Business/DepositConfigNew.php:603-641

setup_eddis Complete Status Flow

eDDA deposits involve setup_eddis table status transitions, covering the full process from authorization to deposit completion:

Status CodeConstantMeaningNext Action
0STATUS_PENDINGPending — record createdapplySetupEddi() triggers processing
1STATUS_PROCESSINGProcessing — debit instruction sentAwait bank callback
2STATUS_DEDUCTEDDeducted — bank has debitedSBA executes crediting
3STATUS_FAILFailed — authorization or debit failedNotify user, record error_code
4STATUS_FINISHComplete — funds creditedFlow ends

Special scenario: STATUS_DEDUCTED -> STATUS_FAIL (CRM rejection) — when the bank has completed debit but backend operations terminates the deposit, error_code is REJECT_BY_CRM, requiring manual refund processing.


eDDA Exception Quick Reference

ExceptionSymptomTroubleshooting PathHandling
Authorization not effective for long timeUser waiting over 24hCheck setup_eddis.edda_status, confirm if still PENDINGGuide user to contact bank for confirmation
Authorization failedUser sees error promptCheck setup_eddis.error_code, reference error code table aboveGuide user to correct info per error code
Debit failedApply status changed to rejectedCheck hsbc_eddis / hs_eddis table reject infoHandle per debit error code table
Debit succeeded but not creditedBank debited, balance not increasedCheck setup_eddis.status stuck at DEDUCTED(2)Check SBA Procedure status
Debit timeoutNo bank callbackCheck ResultJob polling statusWait for polling to complete or manually query bank
Authorization invalidatedPreviously authorized user suddenly can't depositCheck bank-side authorization status (may have been cancelled by user at bank)Guide user to re-authorize

Detailed troubleshooting flow -> Deposit Troubleshooting - eDDA Authorization Failure

Step-by-Step Runbook: eDDA Debit Succeeded but Not Credited (SBA Procedure Hung)

Symptom: Bank has debited (setup_eddis.status = 2 DEDUCTED), but user balance not increased.

Minute 1 — Locate the blocking point

  1. Check setup_eddis table: confirm status = 2 (Deducted)
  2. Check SBA Procedure status: Running / Pending / Failed?
  3. If Procedure is Running and over 10 minutes -> abnormal

Minutes 2~5 — Investigate SBA exception 4. Check SBA service logs: is the Procedure stuck at a particular Step? 5. Common stuck points:

  • CRM account locked (another operation in progress) -> wait for release
  • SBA balance calculation failed -> check account data consistency
  • SBA service itself abnormal -> check SBA service status

Minutes 5~15 — Handle 6. If Procedure status is Failed -> need manual re-execution trigger (contact technical support) 7. If Procedure status is Pending -> check if there are preceding Procedures queued 8. If SBA service is abnormal -> Procedure will auto-continue after service recovery

User communication: Inform user "Bank has debited successfully, funds are being processed" to avoid panic

Not resolved after 30 minutes -> Escalate to deposit technical lead

Insufficient Balance Auto-cancels Authorization

Hang Seng Bank has a special behavior: when eDDI debit is rejected due to insufficient balance (BRC_8I1), the bank may automatically cancel that user's eDDA authorization. This means:

  1. The user needs to top up their bank account first
  2. Then they also need to re-complete eDDA authorization before using eDDA deposit again
  3. Operations should proactively inform the user of this, otherwise the user will assume they can continue depositing after topping up

HSBC does not have this behavior — after rejection due to insufficient balance, authorization remains valid and the user can retry directly after topping up.

Handling suggestion: If a user reports "eDDA worked before but doesn't now," first check if it's a Hang Seng user + previously rejected for insufficient balance. If yes -> guide re-authorization.


Common Misconceptions

MisconceptionFact
"eDDA and eDDI are withdrawal channels"No. eDDA/eDDI is only used for deposit direct debit. HSBC/Hang Seng withdrawals go through corporate online banking transfers, unrelated to eDDA
"All banks can use eDDA"HSBC channel supports 15 banks' personal accounts, Hang Seng channel supports 12 (including 5 exclusive). Corporate accounts not supported. See Supported Scope
"eDDA authorization is permanent once completed"Authorization may be invalidated due to bank-side maintenance, user cancellation in banking app, or auto-cancellation due to insufficient balance (Hang Seng)
"eDDA deposit needs the matching engine"No. eDDA is a system-initiated debit; it inherently knows fund ownership and completely skips the matching engine
"HSBC and Hang Seng eDDA implementations are the same"Protocols are completely different. HSBC uses HTTPS REST API, Hang Seng uses SM2 signing. Data tables, Jobs, and SBA services are all independent
"eDDA can be used for deposits on weekends"Saturday after 10:00 through Sunday is off-hours. Submitted requests queue until Monday 07:00 for execution

After Reading

I want to...Go to
Understand how eDDA authorization enables deposit channelsCard Binding & Deposit Authorization - eDDA
Walk through a complete eDDA deposit end-to-endGetting Started Guide - eDDA Deposit
See how to handle eDDA authorization/debit failuresDeposit Troubleshooting
See operations-side eDDA troubleshooting guideeDDA Troubleshooting Guide
Look up eDDI type codes and status codesDeposit Quick Reference
Dive into HSBC eDDA implementationHSBC
Dive into Hang Seng eDDA implementationHang Seng
Understand how SBA orchestration executes creditingSBA Fund Orchestration
Was this page helpful?

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