tangweijie 1460187516 docs: 添加完整技术文档体系
- 系统架构文档 (architecture/README.md)
- 6个领域文档:
  - 账户域 (01-account.md)
  - 账务域 (02-ledger.md)
  - 交易域 (03-transaction.md)
  - 对账域 (04-reconciliation.md)
  - 补偿域 (05-compensation.md)
  - 积分域 (06-points.md)
- API 参考文档 (api/README.md)
- 前后端对接清单 (integration/frontend-backend.md)
2026-01-05 18:12:37 +08:00

482 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 交易域 (Transaction Domain)
## 一、领域概述
交易域负责处理系统内的所有资金流转,包括转账、充值、提现等操作。该域实现了完整的交易状态机和三键幂等体系,确保交易的安全性和一致性。
## 二、核心概念
### 2.1 三键幂等体系
| 键名 | 字段 | 说明 | 唯一性 |
|------|------|------|--------|
| JZTxId | txn_no | 狱政交易号 | 系统全局唯一 |
| BankTxId | bank_ref_no | 银行交易号 | 银行返回,用于对账 |
| SourceKey | source_key | 来源幂等键 | 外部入账去重 |
**SourceKey 格式**
```
{银行流水号}_{金额}_{记账日}_{对方户名归一化}
```
### 2.2 交易状态机
```
┌──────────────────────────────────────┐
│ │
▼ │
┌─────────┐ ┌─────────┐ ┌──────────────┐ ┌───────┴───┐
│ Created │───►│ Pending │───►│ BankSubmitted│───►│ Success │
└─────────┘ └─────────┘ └──────────────┘ └───────────┘
│ │ │
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌──────────┐
│ Failed │ │ Timeout │──────►│ Reversed │
└─────────┘ └─────────┘ └──────────┘
```
**状态说明**
| 状态 | 说明 | 后续操作 |
|------|------|----------|
| Created | 已创建(初始状态) | 继续处理或取消 |
| Pending | 待处理(已建立在途) | 提交银行 |
| BankSubmitted | 已提交银行 | 等待回执 |
| Success | 成功(银行确认) | 结转在途 |
| Failed | 失败(银行拒绝) | 回退在途 |
| Timeout | 超时(无回执) | 等待对账或重试 |
| Reversed | 已冲正 | 终态 |
## 三、核心实体
### 3.1 系统交易 (SystemTransaction)
```rust
pub struct SystemTransaction {
pub id: i64,
pub txn_no: String, // 狱政交易号 (JZTxId)
pub txn_type: TransactionType, // 交易类型
pub from_account_id: Option<i64>, // 转出账户ID
pub to_account_id: Option<i64>, // 转入账户ID
pub amount: Decimal, // 金额
pub status: TransactionStatus, // 状态
pub bank_ref_no: Option<String>, // 银行交易号 (BankTxId)
pub source_key: Option<String>, // 来源幂等键 (SourceKey)
pub remark: Option<String>, // 备注
pub created_at: DateTime<Utc>, // 创建时间
pub confirmed_at: Option<DateTime<Utc>>, // 确认时间
pub submitted_at: Option<DateTime<Utc>>, // 提交银行时间
pub version: i32, // 乐观锁版本
}
```
**核心方法**
```rust
impl SystemTransaction {
// 检查是否可以提交到银行
pub fn can_submit(&self) -> bool {
matches!(self.status, TransactionStatus::Pending | TransactionStatus::Created)
}
// 检查是否需要对账
pub fn needs_reconciliation(&self) -> bool {
matches!(self.status,
TransactionStatus::BankSubmitted |
TransactionStatus::Timeout |
TransactionStatus::Processing
)
}
// 检查是否为终态
pub fn is_terminal(&self) -> bool {
self.status.is_terminal()
}
// 检查是否超时
pub fn is_timeout(&self, timeout_seconds: i64) -> bool {
if self.status != TransactionStatus::BankSubmitted {
return false;
}
if let Some(submitted_at) = self.submitted_at {
let elapsed = Utc::now().signed_duration_since(submitted_at);
return elapsed.num_seconds() > timeout_seconds;
}
false
}
// 尝试状态转移
pub fn try_transition(&mut self, target: TransactionStatus) -> Result<(), String> {
if self.status.can_transition_to(target) {
self.status = target;
self.version += 1;
Ok(())
} else {
Err(format!("无效的状态转移: {:?} -> {:?}", self.status, target))
}
}
}
```
### 3.2 银行交易 (BankTransaction)
从银行同步的交易流水。
```rust
pub struct BankTransaction {
pub id: i64,
pub bank_ref_no: String, // 银行参考号
pub physical_account_id: i64, // 实体账户ID
pub txn_type: String, // 交易类型
pub direction: TransactionDirection, // 交易方向
pub amount: Decimal, // 金额
pub counterparty_name: Option<String>,// 对手方名称
pub counterparty_account: Option<String>,// 对手方账号
pub txn_time: DateTime<Utc>, // 交易时间
pub sync_time: DateTime<Utc>, // 同步时间
pub match_status: MatchStatus, // 匹配状态
pub matched_txn_no: Option<String>, // 匹配的系统交易号
pub remark: Option<String>, // 摘要
}
```
## 四、枚举类型
### 4.1 交易状态 (TransactionStatus)
```rust
pub enum TransactionStatus {
Created, // 已创建
Pending, // 待处理
BankSubmitted, // 已提交银行
Success, // 成功
Failed, // 失败
Timeout, // 超时
Reversed, // 已冲正
// 兼容旧状态
Processing, // 处理中 → BankSubmitted
Confirmed, // 已确认 → Success
Mismatch, // 不匹配
}
```
**状态转移规则**
```rust
impl TransactionStatus {
pub fn can_transition_to(&self, target: Self) -> bool {
match (self, target) {
// Created -> Pending
(Self::Created, Self::Pending) => true,
// Pending -> BankSubmitted | Failed
(Self::Pending, Self::BankSubmitted) => true,
(Self::Pending, Self::Failed) => true,
// BankSubmitted -> Success | Failed | Timeout
(Self::BankSubmitted, Self::Success) => true,
(Self::BankSubmitted, Self::Failed) => true,
(Self::BankSubmitted, Self::Timeout) => true,
// Timeout -> Success | Failed (对账确认)
(Self::Timeout, Self::Success) => true,
(Self::Timeout, Self::Failed) => true,
// Success -> Reversed (冲正)
(Self::Success, Self::Reversed) => true,
_ => false,
}
}
}
```
### 4.2 交易类型 (TransactionType)
```rust
pub enum TransactionType {
Transfer, // 转账
Deposit, // 充值
Withdrawal, // 提现
Fee, // 手续费
Interest, // 利息
Adjustment, // 调整
Other(String), // 其他
}
```
### 4.3 交易方向 (TransactionDirection)
```rust
pub enum TransactionDirection {
Inbound, // 入账
Outbound, // 出账
}
```
### 4.4 匹配状态 (MatchStatus)
```rust
pub enum MatchStatus {
Unmatched, // 未匹配
Matched, // 已匹配
Mismatch, // 不匹配
}
```
## 五、交易处理流程
### 5.1 出金流程
```mermaid
sequenceDiagram
participant Client
participant TxnService
participant LedgerService
participant BankClient
participant CompService
Client->>TxnService: 1. 发起转账
TxnService->>TxnService: 2. 创建交易 (Created)
TxnService->>LedgerService: 3. 优先级扣款
LedgerService-->>TxnService: 扣款结果
TxnService->>LedgerService: 4. 建立在途
TxnService->>TxnService: 5. 更新状态 (Pending)
TxnService->>BankClient: 6. 提交银行
TxnService->>TxnService: 7. 更新状态 (BankSubmitted)
alt 银行成功
BankClient-->>TxnService: 成功回执
TxnService->>LedgerService: 8a. 结转在途
TxnService->>TxnService: 9a. 更新状态 (Success)
else 银行失败
BankClient-->>TxnService: 失败回执
TxnService->>LedgerService: 8b. 回退在途
TxnService->>TxnService: 9b. 更新状态 (Failed)
else 超时
Note over TxnService: 等待超时
TxnService->>CompService: 8c. 创建补偿任务
TxnService->>TxnService: 9c. 更新状态 (Timeout)
end
TxnService-->>Client: 返回结果
```
### 5.2 入金流程
```mermaid
sequenceDiagram
participant Bank
participant TxnService
participant LedgerService
Bank->>TxnService: 1. 银行入账通知
TxnService->>TxnService: 2. 检查 SourceKey 幂等
alt 重复入账
TxnService-->>Bank: 返回已处理
else 新入账
TxnService->>TxnService: 3. 创建交易 (Success)
TxnService->>LedgerService: 4. 增加个人余额
TxnService->>LedgerService: 5. 同步银行余额
TxnService-->>Bank: 处理成功
end
```
### 5.3 冲正流程
```mermaid
sequenceDiagram
participant Operator
participant TxnService
participant LedgerService
Operator->>TxnService: 1. 发起冲正
TxnService->>TxnService: 2. 检查是否可冲正
alt 可以冲正
TxnService->>LedgerService: 3. 反向记账
TxnService->>TxnService: 4. 更新状态 (Reversed)
TxnService-->>Operator: 冲正成功
else 不可冲正
TxnService-->>Operator: 冲正失败
end
```
## 六、领域服务
### 6.1 TransactionService
```rust
impl TransactionService {
// ========== 交易创建 ==========
// 创建转账交易
pub async fn transfer(&self, req: TransferRequest) -> Result<SystemTransaction>;
// 创建充值交易
pub async fn deposit(&self, req: DepositRequest) -> Result<SystemTransaction>;
// 创建提现交易
pub async fn withdraw(&self, req: WithdrawRequest) -> Result<SystemTransaction>;
// ========== 交易查询 ==========
// 获取交易详情
pub async fn get_transaction(&self, id: i64) -> Result<SystemTransaction>;
// 根据交易号查询
pub async fn get_by_txn_no(&self, txn_no: &str) -> Result<SystemTransaction>;
// 查询交易列表
pub async fn list_transactions(&self, query: TransactionQuery) -> Result<Vec<SystemTransaction>>;
// ========== 状态管理 ==========
// 提交到银行
pub async fn submit_to_bank(&self, id: i64) -> Result<String>;
// 确认交易
pub async fn confirm_transaction(&self, id: i64, bank_ref_no: &str) -> Result<()>;
// 标记失败
pub async fn mark_failed(&self, id: i64, reason: &str) -> Result<()>;
// 标记超时
pub async fn mark_timeout(&self, id: i64) -> Result<()>;
// 冲正交易
pub async fn reverse_transaction(&self, id: i64) -> Result<()>;
// ========== 幂等检查 ==========
// 检查 SourceKey 是否存在
pub async fn check_source_key(&self, source_key: &str) -> Result<Option<SystemTransaction>>;
}
```
## 七、仓储接口
### 7.1 SystemTransactionRepository
```rust
#[async_trait]
pub trait SystemTransactionRepository: Send + Sync {
async fn create(&self, req: &CreateSystemTransactionRequest) -> Result<SystemTransaction>;
async fn find_by_id(&self, id: i64) -> Result<Option<SystemTransaction>>;
async fn find_by_txn_no(&self, txn_no: &str) -> Result<Option<SystemTransaction>>;
async fn find_by_bank_ref_no(&self, bank_ref_no: &str) -> Result<Option<SystemTransaction>>;
async fn find_by_source_key(&self, source_key: &str) -> Result<Option<SystemTransaction>>;
async fn find_by_status(&self, status: TransactionStatus) -> Result<Vec<SystemTransaction>>;
async fn find_pending(&self) -> Result<Vec<SystemTransaction>>;
async fn find_needs_reconciliation(&self) -> Result<Vec<SystemTransaction>>;
async fn query(&self, query: &TransactionQuery) -> Result<Vec<SystemTransaction>>;
async fn update_status(&self, id: i64, status: TransactionStatus) -> Result<()>;
async fn set_bank_ref_no(&self, id: i64, bank_ref_no: &str) -> Result<()>;
async fn set_submitted_at(&self, id: i64) -> Result<()>;
async fn confirm(&self, id: i64, bank_ref_no: &str) -> Result<()>;
}
```
### 7.2 BankTransactionRepository
```rust
#[async_trait]
pub trait BankTransactionRepository: Send + Sync {
async fn create(&self, txn: &BankTransaction) -> Result<i64>;
async fn find_by_bank_ref_no(&self, bank_ref_no: &str) -> Result<Option<BankTransaction>>;
async fn find_unmatched(&self) -> Result<Vec<BankTransaction>>;
async fn update_match_status(&self, id: i64, status: MatchStatus, matched_txn_no: Option<&str>) -> Result<()>;
}
```
## 八、API 接口
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | /api/v1/transactions/transfer | 发起转账 |
| POST | /api/v1/transactions/deposit | 发起充值 |
| POST | /api/v1/transactions/withdraw | 发起提现 |
| GET | /api/v1/transactions/:id | 获取交易详情 |
| GET | /api/v1/transactions | 获取交易列表 |
## 九、数据库表结构
### 9.1 system_transaction 表
```sql
CREATE TABLE system_transaction (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
txn_no VARCHAR(64) NOT NULL UNIQUE,
txn_type VARCHAR(32) NOT NULL,
from_account_id BIGINT,
to_account_id BIGINT,
amount DECIMAL(20, 2) NOT NULL,
status VARCHAR(32) DEFAULT 'created',
bank_ref_no VARCHAR(64),
source_key VARCHAR(256),
remark TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
confirmed_at TIMESTAMP NULL,
submitted_at TIMESTAMP NULL,
version INT DEFAULT 0,
INDEX idx_status (status),
INDEX idx_from_account (from_account_id),
INDEX idx_to_account (to_account_id),
INDEX idx_bank_ref_no (bank_ref_no),
INDEX idx_source_key (source_key),
INDEX idx_created_at (created_at)
);
```
### 9.2 bank_transaction 表
```sql
CREATE TABLE bank_transaction (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
bank_ref_no VARCHAR(64) NOT NULL UNIQUE,
physical_account_id BIGINT NOT NULL,
txn_type VARCHAR(32) NOT NULL,
direction VARCHAR(16) NOT NULL,
amount DECIMAL(20, 2) NOT NULL,
counterparty_name VARCHAR(128),
counterparty_account VARCHAR(64),
txn_time TIMESTAMP NOT NULL,
sync_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
match_status VARCHAR(32) DEFAULT 'unmatched',
matched_txn_no VARCHAR(64),
remark TEXT,
INDEX idx_physical_account (physical_account_id),
INDEX idx_match_status (match_status),
INDEX idx_txn_time (txn_time)
);
```
## 十、并发控制
### 10.1 乐观锁
使用版本号防止并发更新冲突:
```rust
// 更新时检查版本
UPDATE system_transaction
SET status = ?, version = version + 1
WHERE id = ? AND version = ?
```
### 10.2 幂等性保证
1. **txn_no 唯一**:系统交易号全局唯一
2. **source_key 去重**:外部入账通过 SourceKey 去重
3. **状态机约束**:只允许合法的状态转移
## 十一、错误处理
| 错误类型 | 说明 | 处理方式 |
|----------|------|----------|
| InsufficientBalance | 余额不足 | 拒绝交易 |
| InvalidStateTransition | 非法状态转移 | 返回错误 |
| DuplicateTransaction | 重复交易 | 返回已有交易 |
| BankTimeout | 银行超时 | 创建补偿任务 |
| OptimisticLockFailed | 乐观锁冲突 | 重试 |