Skip to content

04 · 提现系统

0. 文档说明

内容
版本V1.0

资金出口 = 风险出口。锁定/扣减/回滚走 02WITHDRAW_LOCK / CONFIRM / ROLLBACK(账户恒本位币 baseCurrency);风控前置归 14;审核工作台归 15。本篇是 02 §3.2「提现边界锁价」的落地。


一、定位与职责

  • 定义提现申请的校验链(KYC / 余额 / 打码门槛 / 限额 / 收款账户);
  • 定义提现订单状态机(锁定 → 风控 → 审核 → 打款 → 终态)与资金一致性;
  • 落地提现边界换算:本位币按提现时点锁价 lockedRate 折出到目标通道币种 channelCurrency(02 §3.2),提交前明示到账数、快照进提现单;
  • 定义收款账户管理(法币银行卡 / 加密地址簿);
  • 定义自动通过、双人复核、手续费规则。

术语(照 02):baseCurrency 本位币(账户口径)、channelCurrency 通道币种(到账方式对外付出币种,可 ≠ 本位币)、lockedRate 锁价(提现时点快照汇率)。

边界:余额三桶语义归 02(账户恒本位币,站内单账户);打码进度计算归 10;风控规则归 14;审核界面归 15。


二、核心概念与数据模型

2.1 提现订单 WithdrawOrder

字段说明
withdrawId / tenantId / userId单号(幂等键)、归属
currency / amount / fee / actualAmount本位币 baseCurrency(扣款口径)、申请额、手续费、实扣额(= amount)
channelCurrency / payoutAmount / lockedRate目标通道币种(可 ≠ 本位币)、到账数(通道币种)、提现时点锁价快照(同币种=1,→ §3.3bis)。到账数 = (amount − fee) × lockedRate
accountRef收款账户(银行卡 ID / 地址簿 ID)
riskResult / reviewerId / ticketId风控结论、审核人、关联工单(大额双审)
channelId / txHash / externalRef打款通道、链上哈希/通道单号
state + 时间戳组见状态机
 申请(校验链通过,WITHDRAW_LOCK)
 ● ──► RISK_SCREENING(风控) ──► PENDING_REVIEW(待审核) ──► APPROVED ──► PAYING(打款中) ──► SUCCESS
            │                        │        ▲                              │              (WITHDRAW_CONFIRM)
            │自动拒                   │驳回     │小额低风险自动通过              │打款失败
            ▼                        ▼        │(跳过人工)                     ▼
         REJECTED ◄──────────────────┘        │                            FAILED ──重试──► PAYING
      (WITHDRAW_ROLLBACK)                     │                               │终止(回滚)
                                              │                               ▼
                                              └───────────────────────────  REJECTED
流转触发资金动作
申请 → RISK_SCREENING校验链全过WITHDRAW_LOCK(available → locked)
→ REJECTED(任意阶段)风控拒 / 人工驳回 / 打款终止WITHDRAW_ROLLBACK(locked → available),记拒因
PAYING → SUCCESS通道回执 / 链上确认WITHDRAW_CONFIRM(locked −),发 WithdrawCompleted
FAILED → PAYING可重试:打款失败次数 < payout.maxRetry 且非致命错误(通道超时/临时不可用等) → 换通道重试(幂等:同 withdrawId 仅一笔在途)
FAILED → REJECTED终止:达最大重试次数 payout.maxRetry(默认 3),或致命错误(账户/地址无效、通道永久拒付),或财务人工判定不可打款WITHDRAW_ROLLBACK(locked → available),记拒因(PAYOUT_EXHAUSTED / PAYOUT_FATAL / MANUAL_TERMINATE)

FAILED 双出边判定:每次打款失败先判错误类别与已重试次数——可重试类且未超上限走 PAYING(自动或财务手动换通道);致命类、超上限、或财务终止走 REJECTED 并原额回滚,locked 资金不滞留 FAILED 态。payout.maxRetry 为租户可配上限(→ §四)。

2.2 收款账户(账户化)

用户从已存账户中选择到账方式,一次保存长期复用。四类 payoutKind,手续费挂在方式上:

kind二级渠道字段校验(保存时,失败 toast)手续费
ewallet 数字钱包GOPAY/OKPAY/VIPPAY/波币/K豆/万币/TOPAY/808钱包…渠道 + 姓名 + 账号账号 ≥6 位字母数字;姓名必填
crypto 虚拟货币USDT × 链(TRC-20/ERC-20)链 + 地址(+备注)TRC:^T[1-9A-HJ-NP-Za-km-z]{33}$;ERC:^0x[0-9a-fA-F]{40}$
bank 银行卡—(开户行为字段)开户行 + 持卡人 + 卡号卡号 16–19 位数字;持卡人/开户行必填2%
alipay 支付宝姓名 + 账号11 位手机号或邮箱5%

账户管理规则:默认账户自动带入(用户在 ⋮ 菜单「设为默认」,组内置顶+标);编辑仅可改账号(渠道/链/姓名/开户行锁定 🔒,变更须删除重加);删除即移出(默认/选中随之清空);姓名一致性——新增带实名账户时姓名须与已有账户一致(脱敏比对提示);账户行不展示「已验证/待验证」类标注。


三、业务规则

3.1 申请校验链(按序,任一失败即拦)

① 账户状态(05:非冻结)
→ ② KYC:默认不要求;后台对该账户下发 kycRequired 时,点「确认提现」直接打开实名认证页(05 §2.4),
     认证通过后自动继续本次提现(PENDING 中提示等待)
→ ③ 收款账户有效(账户化,见 §2.2)
→ ④ 可提现金额校验:打码门槛已折入「可提现金额」口径——彩金打码达标(02)与 `WITHDRAW_GATE` 义务缺口(充值时按 `withdraw.wageringCheck` 生成、10 推进)达标后**自动计入可提现额,不单列缺口提示**(唯一实现口径,与 §四 `wageringCheck`、10 §七对齐)
→ ⑤ 彩金处置(存在未完成 BonusGrant 时按配置:拒绝 或 没收后放行)
→ ⑥ 限额:单笔 min/max(按币种);**次数不限(无日次数/日累计)**
→ ⑦ 余额充足 → WITHDRAW_LOCK

展示层拦截三连即 ④⑥ 的可视化:低于最低 / 超上限 / 可提现金额不足。

3.2 审核与自动通过

  • 风控(14)同步评分:高危自动拒;可疑 → 强制人工。
  • 自动通过:amount ≤ autoApprove.maxAmount 且风控 PASS → 跳过人工直达 APPROVED。
  • 双人复核:amount ≥ dualThreshold → 走 15 审批工单(申请人≠复核人)。
  • 其余进入商户财务审核队列(15 工作台)。

3.3 手续费(按到账方式收,不按来源/次数)

fee = amount × payoutKinds[kind].fee(数字钱包/虚拟货币 0、银行卡 2%、支付宝 5%,租户可配);actualAmount = amount − fee。选中有费方式时展示省费引导:「改用数字钱包/虚拟货币可免手续费,本笔省 ¥x」。

3.3bis 提现边界锁价(跨币种出金,落地 02 §3.2)

目标到账方式的通道币种可 ≠ 本位币:本位币账户按提现时点锁价 lockedRate 折出到通道币种。到账数 = (amount − fee) × lockedRate;lockedRate 于提现提交时点取平台汇率源(withdraw.fxSource,与 03 deposit.fx 同一「平台汇率源」实体,→ 02 §3.2)快照,方向 = 本位币 → 通道币种,非直连币对经 USDT 中转(与 03 §四 fx 一致),取整/精度同 03(round2 防浮点);提交前在费用明细卡明示到账数,并快照进提现单(存 channelCurrency/payoutAmount/lockedRate),后续打款以此为准。该快照仅记本单、不构成站内牌价(→ 02 §3.1 无汇率铁律)。例:USDT 站账户提到 CNY 方式,费用卡显「预计到账 ¥x(锁价快照)」,反向(CNY 站提到 USDT)同理;同币种(通道币种 = 本位币)lockedRate = 1,无汇率行。crossCurrencyPayout 租户可关(关则仅允许提到本位币通道)。站内不做币币兑换——改变持币结构只经此边界(02 §3.3)。

3.4 打款

  • 法币:代付通道出款,回执驱动终态;
  • 加密:热钱包签名广播,txHash 回填,确认数达标 → SUCCESS;
  • 在途唯一:同一订单同一时刻仅一笔打款在途(通道单号幂等)。

四、★ 租户可配置项(withdraw 命名空间)

jsonc
"withdraw": {
  "payoutKinds": {                     // 到账方式(手续费挂方式,→ §2.2/§3.3)
    "ewallet": { "fee": 0,    "channels": ["GOPAY", "OKPAY", "VIPPAY", "波币", "K豆", "万币", "TOPAY", "808钱包"] },
    "crypto":  { "fee": 0,    "nets": ["TRC-20", "ERC-20"] },
    "bank":    { "fee": 0.02 },
    "alipay":  { "fee": 0.05 }
  },
  "limits": { "CNY": { "min": 100, "max": 100000 }, "USDT": { "min": 20, "max": 20000 } },   // 按通道币种,仅单笔;次数不限
  "crossCurrencyPayout": true,         // 跨币种出金(提现时点锁价折出);关=仅允许提到本位币通道
                                       // 可付的通道币种集 = wallet.withdrawChannelCurrencies(→ 02 §四)
  "fxSource": "platform-rate-svc",     // 提现锁价所用汇率源引用(平台汇率源,与 03 deposit.fx 同源、同「平台汇率源」实体,→ 02 §3.2);
                                       // 方向 = 本位币 → 通道币种,非直连币对经 USDT 中转;仅边界询价用,lockedRate 提交锁定、非站内牌价(→ 02 §3.1)
  "wageringCheck": {                   // 提现打码门槛(充值时由 03 生成 WITHDRAW_GATE 义务,10 消费推进;唯一实现,见 §3.1④)
    "enabled": true,                   // 关=不生成 WITHDRAW_GATE 义务、提现不看打码缺口
    "multiple": 1,                     // required = 本次充值入账额(本位币)× multiple;10 §3.3 据此建义务
    "applyScope": "allDeposit"         // allDeposit(每笔成功充值)| withPromoOnly(仅带充值活动的订单)
  },
  "autoApprove": { "enabled": true, "maxAmount": { "CNY": "1000", "USDT": "200" } },
  "dualThreshold": { "CNY": "10000", "USDT": "2000" },   // 双人复核线(→ 15 工单)
  "bonusPolicy": "reject",             // 未完成彩金:reject | forfeit
  "payout": { "maxRetry": 3 },         // 打款失败重试上限;达上限 FAILED→REJECTED 原额回滚(→ §2.1 FAILED 双出边判定)
  "account": { "nameConsistency": true, "editOnlyAccountNo": true, "addressCooldownHours": 24 }
}

KYC 触发不在本命名空间:默认关闭,由后台按账户下发(→ 05 auth.kycRequired 语义,风控/合规触发 → 14/15)。

wageringCheck 说明:提现打码门槛的唯一权威实现——enabled 时,03 在 DepositSucceeded 生成 source=WITHDRAW_GATE 打码义务(required = 入账额 × multiple,本位币),由 10 订阅 BetSettled 推进;提现校验链第 ④ 步据其未达标缺口折入「可提现金额」口径(达标即自动计入,不单列缺口提示,→ §3.1④、10 §七对齐)。multiple=0enabled=false 即无提现打码门槛。

五、与其他系统的关系 / 接口

接口调用方幂等键说明
applyWithdraw(userId, amount, accountRef)展示层客户端单号amount 为本位币扣款额;目标通道币种由 accountRef 决定;跑校验链 → 锁价折出到账数 → 锁定 → 建单(快照 lockedRate/payoutAmount)
review(withdrawId, decision, reviewerId)15 后台withdrawId+决定通过/驳回(大额经工单)
payoutCallback(payload, sign)通道商externalRef打款回执 → 终态
listWithdraws / bindCard / addAddress / verifyAddress展示层记录与收款账户管理

事件:产 WithdrawCompleted(→ 16/17);风控交互 riskCheck(14,同步)。


六、运营后台能力(→ 15)

能力
平台控制台代付通道目录与接入、平台级出款风控线、热钱包管理
商户控制台提现审核工作台(队列、用户画像/风控信息、通过/驳回、批量);限额/手续费/自动通过阈值配置;收款账户管理(异常卡/地址标记);出款统计

七、展示契约(→ 原型映射)

UI 元素数据原型载体系统契约
提现页 #sub-withdraw.sub-head.center;头部居中「提现」+ 右上「提现记录」推入页形态(隐藏底导);资金出口入口
金额渐变卡可提现额 / 输入额#wd-amt(大字输入,默认带入全额)+ 全部 pill;#wd-inline 内联金色提示提示随态:超出可提现金额 / 还差 ¥x 起提;金额恒本位币;可提现额 = 04 §3.1④ 折入口径
「提现到」卡选中账户#wd-acct:未选=引导态(请选择提现账户/四方式副题),已选=头像 + 提现到 xxx + 更换 ›账户化(§2.2);目标通道币种由所选账户决定
账户选择器payoutKinds + 已存账户renderWdSheet:底部弹层,按方式分组(组头=方式 + 免手续费绿/费率灰),组内账户行(默认标 + ⋮ 设默认/编辑/删除 + radio),每组「+添加xxx」手续费挂方式(§3.3);分组=四类 payoutKind
添加/编辑账户渠道/链 + 动态字段waShowForm / wa2Save:二级弹层,主色胶囊 → 动态字段 →「保存并使用」(禁用 40%)校验失败 toast;姓名一致性(§2.2);编辑仅账号可改(🔒);保存即选中关闭双层
省费提示条手续费率#wd-savetip:选中有费方式且金额有效时显示文案「改用数字钱包/虚拟货币可免手续费,本笔省 ¥x」(§3.3)
费用明细卡金额 / 手续费 / lockedRate / 到账数#wd-feecard:未选=金额(本位币)+ ⓘ「选择到账方式后计算」;已选=金额 / 手续费(红 −x 或绿 免费)/(跨币种)参考汇率行 / 预计到账(绿 19px,跨币种双行)手续费=amount×方式费率;跨币种参考汇率行明示本单锁价快照(非站内牌价,§3.3bis);到账数=(amount−fee)×lockedRate
底部状态按钮校验链结论#wd-go:文案随态(确认提现 / 请选择提现账户 / 请添加提现账户 / 超出可提现金额 / 单笔最低 ¥100 / 请输入提现金额,禁用 40%)资金密码触发点:开启资金密码时点击「确认提现」先弹资金密码校验(→ 05 §七触发清单);未选账户但有金额时点击=拉起选择器
KYC 门KYC 状态wdPending:后台对该账户开启且未认证 → 打开实名认证页(05)通过后自动继续本次提现直达结果页(§3.1②)
结果页 #sub-wd-result提现单快照wdSubmit:84px 绿勾 + 金额大字 + 明细卡(到账账户/处理中/预计到账/流水号)+「查看提现记录 / 完成」= WITHDRAW_LOCK 建单语义;跨币种明细展到账数 + 锁价快照
提现记录页 #sub-wtxnWXREC.wd三下拉(方式 × 状态[已到账/处理中/已驳回/已撤销] × 时间[今日默认/昨日/近7日]);新单实时置顶金额恒本位币扣款口径(跨币种单据可展开到账数=通道币种 + 锁价快照);详情页:处理中可撤销(原路退回,撤销为资金密码触发点 → 05 §七)、已驳回重新提交 + 联系客服

演示钩子:?kyc=1(该账户被要求实名)&kycst=pending|approved|reject;launcher 第六机位「多态图 · 提现触发KYC」= ?kyc=1&go=withdraw 直达本页。

八、数据库设计(全表含 tenant_id;金额 DECIMAL(32,8))

关键字段约束/索引
withdraw_orderswithdraw_id PK, tenant_id, user_id, currency(本位币,扣款币种), amount(本位币申请额), fee, actual_amount(本位币实扣=amount), channel_currency(通道币种,可 ≠ 本位币), payout_amount(到账数,通道币种), locked_rate(提现时点锁价,同币种=1), account_ref, risk_result, reviewer_id, ticket_id, channel_id, tx_hash, external_ref, state, created_at, decided_at, paid_atUK(tenant_id,withdraw_id);IDX(tenant_id,state);IDX(tenant_id,user_id,created_at)
user_bank_cardscard_id PK, tenant_id, user_id, bank, card_no_cipher, card_no_tail, holder_name, status, created_atUK(tenant_id,user_id,card_no_hash)
user_crypto_addressesaddr_id PK, tenant_id, user_id, currency, network, address, remark, verify_state, cooldown_until, created_atUK(tenant_id,user_id,currency,network,address)
payout_attemptsid PK, tenant_id, withdraw_id, channel_id, external_ref, result, created_atUK(tenant_id,channel_id,external_ref);IDX(withdraw_id)

九、扩展点

  • 未打码先提现:bonusPolicy 默认 reject;forfeit 模式附用户告知与确认交互。
  • 地址白名单模式:高安全租户可配「仅允许提现至已验证白名单地址」开关。
  • 加密找零/矿工费:链上手续费(fee 之外的网络费)由平台或用户承担,按币种配置。
  • 批量出款:商户侧批量审核已含;批量打款(合并签名)属基建优化。

十、验收要点

  • [ ] 申请即锁定:available 减少、locked 等额增加;驳回后原额回滚,三桶总和不变;
  • [ ] 拦截三连可视(低于最低/超上限/可提现不足);打码折入可提现口径、无次数限制文案;
  • [ ] 手续费按到账方式(切支付宝 1,000 → 费 50 → 到账 950 换算正确);省费提示出现;
  • [ ] 跨币种到账按提现时点锁价 lockedRate 折出、提交前明示到账数、快照进提现单(如 USDT 站账户提到 CNY 方式 显 ¥ 到账数,双行 + 本位币扣款额);锁价仅记本单、非站内牌价;
  • [ ] 账户口径恒本位币;crossCurrencyPayout=false 时仅允许提到本位币通道;站内无币币兑换入口;
  • [ ] KYC 门:后台开启时确认提现弹实名页,通过自动续提直达结果页;已认证后二次提现直接放行;
  • [ ] 账户管理:设默认置顶、编辑仅账号、删除清引用、姓名一致性拦截、添加即选用;
  • [ ] 撤销闭环:处理中 → 详情撤销 → 列表变已撤销(原路退回提示);
  • [ ] 自动通过仅发生在阈值内且风控 PASS;≥ 双审阈值必产生审批工单且申请人≠复核人;
  • [ ] 同一订单不可能产生两笔在途打款(通道单号唯一约束);
  • [ ] WithdrawCompleted 仅在 SUCCESS 发一次;手续费在账变中单列可对账;
  • [ ] bonusPolicy=reject 时带未完成彩金的提现被拒并提示;forfeit 时有 BONUS_FORFEIT 账变留痕。