- 实现账户管理改进设计文档中的所有核心功能 - 三科目余额管理 (个人余额、劳动报酬、冻结余额) - 交易状态机 (created → pending → bank_submitted → success/failed/timeout → reversed) - 三键幂等体系 (JZTxId/BankTxId/SourceKey) - 优先级扣款规则 (先个人后劳动) - 在途资金管理 (可用→在途→结转/回退) - 三账对账闭环 (总账 = 银行账 + 在途净额) - 补偿服务域 (超时检测、重试、死信队列) - 虚拟银行模拟器用于业务测试 - 完整的集成测试套件 (133 个测试全部通过) - Docker 容器化部署配置 - 前端 Vue3 + TypeScript 项目结构
7.4 KiB
7.4 KiB
一、概述与目标
- 标准化账户域三科目:个人余额、劳动报酬、冻结余额;以银行余额为对照。
- 以“狱政交易对象”统一编排冻结/在途/银行交互/补偿,实现端到端一致性与可追溯。
- 覆盖成功、失败、超时、退回、外部入账等全链路场景,形成对账闭环与治理体系。
二、账户模型与不变量
- 科目:个人(可用)、劳动(可用)、冻结(不可用)、银行余额(对照)。
- 不变量:每次动账后校验
个人 + 劳动 + 冻结 = 银行余额(账面)。
三、交易与状态机
- 对象分工:
- 狱政交易:余额校验、冻结/解冻、在途划转、状态机与补偿。
- 银行交易:通道调用与回执。
- 幂等键:JZTxId / BankTxId / SourceKey。
- 状态机:
created → pending → bank_submitted → success | failed | timeout → reversed
stateDiagram-v2
[*] --> created
created --> pending: 校验余额/建立在途
pending --> bank_submitted: 发起银行交易
bank_submitted --> success: 银行成功
bank_submitted --> failed: 银行失败
bank_submitted --> timeout: 超时无回执
success --> reversed: 银行退回/业务冲正
failed --> [*]
timeout --> success: 对账识别成功
timeout --> failed: 对账识别失败
reversed --> [*]
四、资金规则与在途
- 扣款优先级:先个人,后劳动;不足则失败或先冻结。
- 冻结/解冻:仅账户内流转,不触发银行。
- 在途:可用→在途原子划转;成功从在途结转对外,失败/取消在途回退。
flowchart TD
A[创建狱政交易] --> B{余额充足?}
B -- 否 --> X[拒绝]
B -- 是 --> C[可用→在途 划转]
C --> D[发起银行交易]
D --> E{结果}
E -- 成功 --> F[在途→对外 结转]
E -- 失败 --> G[在途→可用 回退]
E -- 超时 --> H[进入补偿/对账]
五、外部入账与退回
- 外部入账:对账单生成SourceKey(流水号+记账日+金额+户名归一化),幂等入账。
- 退回/冲正:success则生成reversed对冲;在途则回退并关闭。
flowchart TD
A[对账单项] --> B[生成SourceKey]
B --> C{已处理?}
C -- 是 --> D[幂等返回]
C -- 否 --> E[入账 指定科目]
E --> F[来源型交易 success]
flowchart TD
A[收到银行退回] --> B{原交易状态}
B -- success --> C[生成逆向交易reversed]
C --> D[可用↑或恢复冻结]
B -- 在途/未完成 --> E[在途回退]
E --> F[关闭原交易]
六、对账与补偿闭环
- 三账:银行账、在途账、总账;目标:
总账 = 银行账 + 在途净额。
flowchart TD
A[拉取银行对账单] --> B[汇总银行账]
B --> C[汇总总账]
C --> D[汇总在途净额]
D --> E{等式是否成立?}
E -- 是 --> F[对账通过]
E -- 否 --> G[差异分类入队]
G --> H[自动纠错]
G --> I[人工复核]
H --> J[更新账务/关闭差异]
I --> J
sequenceDiagram
participant TO as 狱政交易
participant Bank as 银行
participant RC as 对账服务
TO->>Bank: 发起交易
Bank-->>TO: 无回执(超时)
TO->>TO: 标记timeout/入补偿
RC->>Bank: 拉取对账单
Bank-->>RC: 返回明细
RC->>TO: 匹配并更新
TO->>TO: success则在途结转,failed则在途回退
七、并发与幂等
- 同账户串行化/分片锁;状态机转移携带期望状态+version,首次落地为准。
- 全链路重试幂等(JZTxId/BankTxId/SourceKey),队列去重。
flowchart TD
A[写入请求] --> B{账户是否持锁?}
B -- 否 --> C[获取分片锁]
B -- 是 --> D[排队/快速失败]
C --> E[读取version]
E --> F{期望状态匹配?}
F -- 否 --> R[幂等返回]
F -- 是 --> G[更新状态 version+1]
G --> H[释放锁]
八、银行余额同步减少分配
- 以Δ<0为驱动,顺序:个人→劳动→冻结;逐步非负校验,不足则回滚/人工。
flowchart TD
A[银行差额Δ<0] --> B["扣个人 min(abs(Δ), 个人可用)"]
B --> C{Δ已抵消?}
C -- 是 --> Z[结束 校验不变量]
C -- 否 --> D["扣劳动 min(剩余Δ, 劳动可用)"]
D --> E{Δ已抵消?}
E -- 是 --> Z
E -- 否 --> F["扣冻结 min(剩余Δ, 冻结余额)"]
F --> G{Δ已抵消?}
G -- 否 --> X[失败 回滚/人工]
G -- 是 --> Z
九、治理与运行
- 参数化:通道级超时/重试/退避、扣减优先级、退回归属、冻结期限;配置审计。
- 监控SLA:在途老化、超时率、退回率、差异关闭时延、补偿成功率;限流/熔断/降级。
- 审计与合规:输入/幂等键/状态转移/操作者/签名;关键记录WORM。
- RBAC:角色矩阵与双人复核;敏感操作留痕。
十、日切与迁移
- 账务日与自然日边界;跨日入账与T+1补账归属;错账回滚口径统一。
- 演进:灰度、双写/对比、回滚预案、存量修复脚本与验收标准。
附:在途的状态管理
状态定义
- pending:可用→在途划转已完成,待发起银行或已排队。
- bank_submitted:银行调用已发出,等待回执或对账裁决。
- timeout:超过通道超时阈值未获回执,进入补偿与对账判定。
- success:银行成功,已从在途结转对外(在途余额归零)。
- failed:银行失败,已将在途回退至可用(在途余额归零)。
- reversed:已对成功交易完成逆向冲正(银行退回或业务冲正)。
状态机
stateDiagram-v2
[*] --> pending: 可用→在途
pending --> bank_submitted: 发起银行
bank_submitted --> success: 银行成功
bank_submitted --> failed: 银行失败
bank_submitted --> timeout: 超时无回执
timeout --> success: 对账识别成功
timeout --> failed: 对账识别失败
success --> reversed: 退回/业务冲正
failed --> [*]
reversed --> [*]
触发事件与转移规则
- submit_bank:从pending到bank_submitted。
- bank_ack_success / bank_ack_fail:从bank_submitted到success/failed。
- timer_expired:从bank_submitted到timeout(由定时器驱动)。
- reconcile_match_success / reconcile_match_fail:从timeout到success/failed(由对账作业驱动)。
- reverse_requested:从success到reversed(银行退回或业务冲正)。****
并发与幂等裁决
- 每次转移携带期望状态与version,服务端校验后version自增;首个成功落地为准,其余并发幂等返回。
- 同账户加分片锁或串行化,避免同一账户在途与可用并发修改冲突。
超时与补偿
- 定时器:通道级超时阈值(可配置),到时触发timer_expired进入timeout。
- 补偿:对账作业周期拉取银行明细,匹配后触发reconcile_match_*事件推进结论。
- 死信:超过最大补偿次数进入死信队列并告警,需人工复核。
回收与审计
- 在途余额只能存在于pending、bank_submitted、timeout三态;进入success/failed/reversed即归零。
- 全链路审计:记录输入参数、幂等键、状态变更、操作者/系统ID、签名与时间戳。
指标与告警
- 在途老化分布、各状态停留时长、timeout占比、补偿成功率、reversed占比。
- 告警阈值:单笔在途超时、批量超时率、补偿失败率、对账差异未关闭时延。