- 实现账户管理改进设计文档中的所有核心功能 - 三科目余额管理 (个人余额、劳动报酬、冻结余额) - 交易状态机 (created → pending → bank_submitted → success/failed/timeout → reversed) - 三键幂等体系 (JZTxId/BankTxId/SourceKey) - 优先级扣款规则 (先个人后劳动) - 在途资金管理 (可用→在途→结转/回退) - 三账对账闭环 (总账 = 银行账 + 在途净额) - 补偿服务域 (超时检测、重试、死信队列) - 虚拟银行模拟器用于业务测试 - 完整的集成测试套件 (133 个测试全部通过) - Docker 容器化部署配置 - 前端 Vue3 + TypeScript 项目结构
197 lines
7.4 KiB
Markdown
197 lines
7.4 KiB
Markdown
|
||
|
||
## 一、概述与目标
|
||
- 标准化账户域三科目:个人余额、劳动报酬、冻结余额;以银行余额为对照。
|
||
- 以“狱政交易对象”统一编排冻结/在途/银行交互/补偿,实现端到端一致性与可追溯。
|
||
- 覆盖成功、失败、超时、退回、外部入账等全链路场景,形成对账闭环与治理体系。
|
||
|
||
## 二、账户模型与不变量
|
||
- 科目:个人(可用)、劳动(可用)、冻结(不可用)、银行余额(对照)。
|
||
- 不变量:每次动账后校验`个人 + 劳动 + 冻结 = 银行余额(账面)`。
|
||
|
||
## 三、交易与状态机
|
||
- 对象分工:
|
||
- 狱政交易:余额校验、冻结/解冻、在途划转、状态机与补偿。
|
||
- 银行交易:通道调用与回执。
|
||
- 幂等键:JZTxId / BankTxId / SourceKey。
|
||
- 状态机:`created → pending → bank_submitted → success | failed | timeout → reversed`
|
||
|
||
```mermaid
|
||
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 --> [*]
|
||
```
|
||
|
||
## 四、资金规则与在途
|
||
- 扣款优先级:先个人,后劳动;不足则失败或先冻结。
|
||
- 冻结/解冻:仅账户内流转,不触发银行。
|
||
- 在途:可用→在途原子划转;成功从在途结转对外,失败/取消在途回退。
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
A[创建狱政交易] --> B{余额充足?}
|
||
B -- 否 --> X[拒绝]
|
||
B -- 是 --> C[可用→在途 划转]
|
||
C --> D[发起银行交易]
|
||
D --> E{结果}
|
||
E -- 成功 --> F[在途→对外 结转]
|
||
E -- 失败 --> G[在途→可用 回退]
|
||
E -- 超时 --> H[进入补偿/对账]
|
||
```
|
||
|
||
## 五、外部入账与退回
|
||
- 外部入账:对账单生成SourceKey(流水号+记账日+金额+户名归一化),幂等入账。
|
||
- 退回/冲正:success则生成reversed对冲;在途则回退并关闭。
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
A[对账单项] --> B[生成SourceKey]
|
||
B --> C{已处理?}
|
||
C -- 是 --> D[幂等返回]
|
||
C -- 否 --> E[入账 指定科目]
|
||
E --> F[来源型交易 success]
|
||
```
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
A[收到银行退回] --> B{原交易状态}
|
||
B -- success --> C[生成逆向交易reversed]
|
||
C --> D[可用↑或恢复冻结]
|
||
B -- 在途/未完成 --> E[在途回退]
|
||
E --> F[关闭原交易]
|
||
```
|
||
|
||
## 六、对账与补偿闭环
|
||
- 三账:银行账、在途账、总账;目标:`总账 = 银行账 + 在途净额`。
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
A[拉取银行对账单] --> B[汇总银行账]
|
||
B --> C[汇总总账]
|
||
C --> D[汇总在途净额]
|
||
D --> E{等式是否成立?}
|
||
E -- 是 --> F[对账通过]
|
||
E -- 否 --> G[差异分类入队]
|
||
G --> H[自动纠错]
|
||
G --> I[人工复核]
|
||
H --> J[更新账务/关闭差异]
|
||
I --> J
|
||
```
|
||
|
||
```mermaid
|
||
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),队列去重。
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
A[写入请求] --> B{账户是否持锁?}
|
||
B -- 否 --> C[获取分片锁]
|
||
B -- 是 --> D[排队/快速失败]
|
||
C --> E[读取version]
|
||
E --> F{期望状态匹配?}
|
||
F -- 否 --> R[幂等返回]
|
||
F -- 是 --> G[更新状态 version+1]
|
||
G --> H[释放锁]
|
||
```
|
||
|
||
## 八、银行余额同步减少分配
|
||
- 以Δ<0为驱动,顺序:个人→劳动→冻结;逐步非负校验,不足则回滚/人工。
|
||
|
||
```mermaid
|
||
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:已对成功交易完成逆向冲正(银行退回或业务冲正)。
|
||
|
||
### 状态机
|
||
```mermaid
|
||
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占比。
|
||
- 告警阈值:单笔在途超时、批量超时率、补偿失败率、对账差异未关闭时延。
|
||
|