Skip to content

Channel Execution Manual

About This Page

What: The complete technical execution process for each withdrawal channel from Remittance through to bank confirmation Audience: Product managers who need to understand "how money gets from system to bank", and those evaluating the impact of channel modifications Prerequisites: Withdrawal LifecycleReading time: 5 minutes Owner: Withdrawal Product Manager

Key Takeaway: All withdrawal channels ultimately execute through SBA orchestration. BST channels are fully automated (seconds~minutes to arrive), non-BST channels require ops to manually operate in bank online banking and then confirm completion.


SBA Orchestration: The Central Hub for Funds

All withdrawal channels ultimately execute through SBA (Server Bank Account). SBA is the internal fund orchestration system — responsible for orchestrating freeze, deduction, transfer instructions, and tracking their status.

SBA Procedure State Machine

Each withdrawal corresponds to a Procedure (orchestration flow) in SBA:

SBA Sub-status (ext_status)

There are only 5 main statuses, but sub-statuses are the key to precisely tracking progress. Below are the most commonly used sub-statuses; for the complete list see Withdrawal Data Dictionary § SBA Sub-status.

Main StatusSub-statusPM Perspective
newwaitingUser can still cancel the withdrawal in the App at this point
newmanual_confirmRequires ops confirmation in CRM
pendingdeduct_doneFunds deducted, waiting to initiate transfer
pendingtransfer_autoBST: System is sending instruction to bank
pendingtransfer_manualNon-BST: Waiting for ops to operate in bank online banking
pendingtransfer_doneBank confirmed receipt of instruction
pendingtransfer_rejectBank rejected the withdrawal instruction
end_oktransfer_doneWithdrawal complete

User Cancellation Window

Users can only cancel the withdrawal in the App when ext_status = waiting. Once it enters deduct_done, funds have been deducted and the user cannot cancel on their own — only ops can initiate a reversal.

If requirements change: Extending SBA sub-statuses

Code location: withdraw/src/app/Business/SOA/Srpc/WithdrawRPC.php defines all EXT_STATUS_* constants

Sub-statuses are the protocol between SBA (Python service) and withdrawal service (PHP). Modifying sub-statuses requires both sides to update in sync.


BST Channel

BST is the only channel that takes the fully automated path.

BST Authorization Prerequisite

Users must first complete BST authorization (Mandate) before using BST:

BankAuthorization ModelCharacteristics
CMB/CMBCTraditional BST agreementOnly "signed/unsigned" two states
AirstarMandate authorization6 states; one authorization binds 3 markets (HK/US/HKCC)

Authorization status must be OPEN for deposit/withdrawal. The Confirm step validates this.

Execution Methods

BankServiceProtocolResult Retrieval
CMBcmb_stock_transSocket binaryReal-time push
CMBCms_stock_bank_transactionSocket binaryReal-time push
AirstarAirstar BST APIREST + JSONPolling

BST withdrawal follows a Freeze-Transfer-Release three-step process:

  1. SBA freezes an equivalent amount in the user's available balance
  2. Sends withdrawal instruction to bank
  3. Upon receiving result: success deducts and releases freeze; failure rolls back and releases

Result Retrieval Methods

CMB/CMBC and Airstar obtain bank results in completely different ways:

CMB/CMBC: Results are pushed in real-time via Socket bidirectional link, typically completing in seconds. On timeout (callback code -5), automatically switches to backup exit_server for retry.

Airstar: Results obtained via REST API in two-phase polling:

PhaseEventStrategyCumulative Duration
Fast pollingAsbBstTransferQuery every 5 seconds, max 10 times~50 seconds
Fallback syncSyncAsbBstWithdrawContinuously sync incomplete instructions within 2-hour windowUp to 2 hours
TimeoutMark abnormal, requires ops to manually query Airstar API

What is exit_server

exit_server is the Socket communication address for CMB/CMBC BST. Each bank is configured with primary and backup addresses; when the primary times out, the system automatically switches to the backup for retry.

Balance Deduction

When Remittance executes, it first calls autoOut() to deduct the withdrawal balance from the auto_settings table:

  • Below alarm_amount → Sends Feishu alert
  • Below stop_amountAutomatically closes auto-withdrawal for that currency; all subsequent degrade to manual

Deduction happens before the bank transfer — even if the bank rejects, the balance has been deducted. Ops must manually restore.

BST Exception Handling

ExceptionTriggerSystem BehaviorOps Action
CMB/CMBC timeout (-5)Socket timeoutSwitch to backup exit_server for retryUsually no intervention needed
CMB/CMBC rejection (-6)Bank rejectionMark as failedContact bank to confirm reason
Airstar polling timeoutStill PENDING after 10 pollsEnter 2-hour fallback syncWait, monitor alerts
Airstar sync timeoutStill PENDING after 2 hoursMark abnormalManually query Airstar API
Airstar instruction failureReturns FAILEDRelease frozen fundsCheck 140630xxx error code
Authorization exceptionMandate not OPENConfirm step blocks advancementGuide user to re-authorize

Online Banking Channel (HSBC / Hang Seng)

Ops transfers via bank corporate online banking, confirms completion in CRM.

eDDI ≠ Withdrawal

eDDA/eDDI is a deposit protocol (direct debit for deposit). HSBC/Hang Seng withdrawals go through corporate online banking, not eDDI.

Flow:

  1. Confirm step calls startTransfer() → SBA returns transfer_manual
  2. Ops sees "pending remittance" task in CRM
  3. Ops logs into bank corporate online banking and executes transfer
  4. After successful transfer, clicks confirm at CRM Remittance step
  5. Task → DONE

FPS Channel

BOC / Standard Chartered FPS

Standard semi-auto flow, similar to the online banking channel — ops triggers then confirms in CRM.

FPS limit: HKD / CNH amounts < 1 million use FPS. >= 1 million upgrades to CHATS/RTGS.

Payee name requirement: FPS channel must use full name (unlike CHATS/TT which can use abbreviated names).

CGB FPS (Batch Submission + Async Polling)

CGB FPS is the closest to fully automated among semi-auto channels — it has an API interface but requires ops to trigger:

Polling interval (increasing):

Attempt RangeInterval
1~10010 seconds
101~20020 seconds
201~30030 seconds
301~100040 seconds

Maximum polling can reach hours. Data stored in task_cgb_fps table.

If requirements change: Connecting a new FPS channel
  1. Create Go service to interface with bank FPS API
  2. Create new XxxFpsBiz.php in PHP (reference CgbFpsBiz.php)
  3. Create new polling event SyncXxxFpsResult
  4. Add channel constant in Method.php
  5. Create new task_xxx_fps table for API status storage

Traditional Channels

CHATS/RTGS (File Export)

Withdrawal through Hong Kong interbank clearing system; ops exports file then uploads to bank system.

Trigger conditions:

  • Virtual bank + USD withdrawal
  • Virtual bank + HKD/CNH amount >= 1 million
  • Fall-through when non-BST bank + FPS unavailable

Fee: USD $8 / HKD $25 / CNY $25 (user prompted with popup when confirming withdrawal, requires explicit user consent).

Flow:

  1. Ops selects pending remittance tasks in CRM
  2. System generates RTGS/CHATS format file
  3. Ops uploads file to bank system (offline operation)
  4. Bank completes processing, confirm in CRM

File notes:

  • Payee name: Can use abbreviated name FUTU SECURITIES INTL (HK) LTD (full name not required)
  • Payee name limited to 140 characters (truncated with warning if exceeded)
  • Amount unit is cents (multiplied by 100)
  • Name obtained from nick_list table, English name preferred
If requirements change: Adjusting file format

Code location: withdraw/src/app/Business/Withdraw/ExportRTGSCHATSFile.php

The file format is a fixed format required by the bank; modifications need bank confirmation.

Cross-border Wire Transfer (tele_transfer / ewb)

Purely manual channel. Ops operates cross-border remittance in bank online banking, then confirms in CRM. setTransferDone() passes method = null (SBA routes by configuration).

NSS Name Screening: Cross-border wire transfers require passing NSS (Name Screening Service) to check the payee name before execution, confirming it's not on sanctions lists. Withdrawals failing NSS require manual escalation, with ops contacting the compliance team.

Payee name rule: Cross-border wire/TT can use abbreviated name FUTU SECURITIES INTL (HK) LTD.

Cheque (check)

The most traditional channel with the slowest arrival time.

Operational flow:

  1. Ops issues cheque based on withdrawal task information
  2. Requires 2 authorized signatories (dual-signature policy)
  3. Delivered to bank daily in the afternoon by designated staff
  4. Record cheque number (check_extra table)
  5. Confirm in CRM

Applicable scenario: Final fall-through option when same-bank transfer, FPS, and CHATS/RTGS are all unavailable.


Channel Comparison Summary

DimensionBSTCGB FPSOther FPS/Online BankingTraditional
startTransfer timingRemittanceConfirmConfirmConfirm
SBA ext_statustransfer_autotransfer_manualtransfer_manualtransfer_manual
Result retrievalPush (CMB/CMBC) / Polling (Airstar)Polling (1000 times)CRM manual confirmCRM manual confirm
Completion triggerAuto-completePolling auto-completeOps confirmationOps confirmation
Maximum waitSeconds (CMB/CMBC) / ~2 hours (Airstar)HoursDepends on opsDepends on ops
Requires opsNo (fully automated)Trigger submissionBank operation + confirmBank operation + confirm
If requirements change: Making a manual channel semi-automated

Core transformation: Replace CRM manual confirmation with API polling. Reference the CGB FPS pattern:

  1. Interface with bank API (submit transfer + query status)
  2. Create polling queue event
  3. Remittance step takes async path for that channel
  4. startTransfer() timing and SBA ext_status do not need changes

Channel Method Groups

Method groups in the code determine CRM display and operation patterns:

GroupIncluded ChannelsPurpose
allEBankMethod()manual, boc, hase, hsbc, boc_fps, cgb_fps_api, chats_rtgs, scOnline banking class (8 types)
allTeleMethod()tele_transfer, ewbCross-border wire class (2 types)
allSetMethod()Online banking class + check (9 types)Confirm step selectable channels
allTabMethod()allSetMethod + ewb + tele_transfer (11 types)CRM Tab pages
all()All 12 typesAll withdrawal channels

Why auto_bs is not in allSetMethod

BST is automatically routed by the system and does not require ops manual selection. Only when method = null does ops need to select a channel from allSetMethod.


Common Misconceptions

MisconceptionFact
"SBA is a bank"No. SBA (Server Bank Account) is the internal fund orchestration system, responsible for freeze, deduction, transfer instruction orchestration and status tracking. All withdrawal channels ultimately execute through SBA
"All BST banks use the same technology"No. CMB/CMBC use Socket bidirectional link (SM2 encryption, real-time result push); Airstar uses REST API (JSON, polling for results). Timeout handling and polling strategies are completely different
"HSBC/Hang Seng withdrawals use eDDA"They do not. eDDA/eDDI is only for deposit direct debit. HSBC/Hang Seng withdrawals go through corporate online banking transfer, unrelated to eDDA
"FPS withdrawal is fully automated"No. CGB FPS has an API interface but still requires ops to trigger submission; BOC/SCB FPS is entirely manually operated. Only BST is fully automated

I want to...Go to
Understand the complete flow from approval to executionWithdrawal Lifecycle
See auto-withdrawal conditions and limit rulesWithdrawal Rules Manual
Troubleshoot a channel exceptionWithdrawal Troubleshooting
Push a channel-related requirement changeWithdrawal Change Guide
Look up SBA status codes, callback codesWithdrawal Data Dictionary
Deep dive into the three BST banksBST Overview
Was this page helpful?

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