mirror of
https://gitee.com/technical-laohu/mpay_v2_webman.git
synced 2026-03-26 12:44:28 +08:00
215 lines
7.5 KiB
Markdown
215 lines
7.5 KiB
Markdown
# 支付订单表设计说明
|
||
|
||
## 一、订单表设计原因
|
||
|
||
### 1.1 订单号设计(双重订单号)
|
||
|
||
**系统订单号 (`pay_order_id`)**
|
||
- **作用**:系统内部唯一标识,用于查询、对账、退款等操作
|
||
- **生成规则**:`P` + `YYYYMMDDHHmmss` + `6位随机数`(如:P20240101120000123456)
|
||
- **唯一性**:通过 `uk_pay_order_id` 唯一索引保证
|
||
- **优势**:
|
||
- 全局唯一,不受商户影响
|
||
- 便于系统内部查询和关联
|
||
- 对账时作为主键
|
||
|
||
**商户订单号 (`mch_order_no`)**
|
||
- **作用**:商户传入的订单号,用于幂等性校验
|
||
- **唯一性**:通过 `uk_mch_order_no(merchant_id, mch_order_no)` 联合唯一索引保证
|
||
- **优势**:
|
||
- 同一商户下订单号唯一,防止重复提交
|
||
- 商户侧可以自定义订单号规则
|
||
- 支持商户订单号查询订单
|
||
|
||
**为什么需要两个订单号?**
|
||
- 系统订单号:保证全局唯一,便于系统内部管理
|
||
- 商户订单号:保证商户侧唯一,防止重复支付(幂等性)
|
||
|
||
### 1.2 关联关系设计
|
||
|
||
**商户与应用关联 (`merchant_id` + `app_id`)**
|
||
- **作用**:标识订单所属商户和应用
|
||
- **用途**:
|
||
- 权限控制(商户只能查询自己的订单)
|
||
- 对账统计(按商户/应用维度)
|
||
- 通知路由(根据应用配置的通知地址)
|
||
|
||
**支付通道关联 (`channel_id`)**
|
||
- **作用**:记录实际使用的支付通道
|
||
- **用途**:
|
||
- 退款时找到对应的插件和配置
|
||
- 对账时关联通道信息
|
||
- 统计通道使用情况
|
||
|
||
**支付方式与产品 (`method_code` + `product_code`)**
|
||
- **method_code**:支付方式(alipay/wechat/unionpay)
|
||
- 用于统计、筛选、报表
|
||
- **product_code**:支付产品(alipay_h5/alipay_life/wechat_jsapi等)
|
||
- 由插件根据用户环境自动选择
|
||
- 用于记录实际使用的支付产品
|
||
|
||
### 1.3 金额字段设计
|
||
|
||
**订单金额 (`amount`)**
|
||
- 商户实际收款金额(扣除手续费前)
|
||
- 用于退款金额校验、对账
|
||
|
||
**手续费 (`fee`)**
|
||
- 可选字段,记录通道手续费
|
||
- 用于对账、结算、利润统计
|
||
- 如果不需要详细记录手续费,可以留空或通过 `extra` 存储
|
||
|
||
**币种 (`currency`)**
|
||
- 默认 CNY,支持国际化扩展
|
||
- 预留字段,便于后续支持多币种
|
||
|
||
### 1.4 状态流转设计
|
||
|
||
```
|
||
PENDING(待支付)
|
||
├─> SUCCESS(支付成功)← 收到渠道回调并验签通过
|
||
├─> FAIL(支付失败)← 用户取消、超时、渠道返回失败
|
||
└─> CLOSED(已关闭)← 全额退款后
|
||
```
|
||
|
||
**状态说明**:
|
||
- **PENDING**:订单创建后,等待用户支付
|
||
- **SUCCESS**:支付成功,已收到渠道回调并验签通过
|
||
- **FAIL**:支付失败(用户取消、订单超时、渠道返回失败等)
|
||
- **CLOSED**:已关闭(全额退款后)
|
||
|
||
### 1.5 渠道信息设计
|
||
|
||
**渠道订单号 (`channel_order_no`)**
|
||
- 渠道返回的订单号
|
||
- 用于查询订单状态、退款等操作
|
||
|
||
**渠道交易号 (`channel_trade_no`)**
|
||
- 部分渠道有交易号概念(如支付宝的 trade_no)
|
||
- 用于对账、查询等
|
||
|
||
### 1.6 通知机制设计
|
||
|
||
**通知状态 (`notify_status`)**
|
||
- 0:未通知
|
||
- 1:已通知成功
|
||
|
||
**通知次数 (`notify_count`)**
|
||
- 记录通知次数,用于重试控制
|
||
- 配合 `ma_notify_task` 表实现异步通知
|
||
|
||
### 1.7 扩展性设计
|
||
|
||
**扩展字段 (`extra`)**
|
||
- JSON 格式,存储:
|
||
- 支付参数(`pay_params`):前端支付所需的参数
|
||
- 退款信息(`refund_info`):退款结果
|
||
- 自定义字段:业务扩展字段
|
||
|
||
**订单过期时间 (`expire_time`)**
|
||
- 用于自动关闭超时订单
|
||
- 默认 30 分钟,可配置
|
||
|
||
## 二、索引设计说明
|
||
|
||
### 2.1 唯一索引
|
||
|
||
- **`uk_pay_order_id`**:保证系统订单号唯一
|
||
- **`uk_mch_order_no(merchant_id, mch_order_no)`**:保证同一商户下商户订单号唯一(幂等性)
|
||
|
||
### 2.2 普通索引
|
||
|
||
- **`idx_merchant_app(merchant_id, app_id)`**:商户/应用维度查询
|
||
- **`idx_channel_id`**:通道维度查询
|
||
- **`idx_method_code`**:支付方式维度统计
|
||
- **`idx_status`**:状态筛选
|
||
- **`idx_pay_time`**:按支付时间查询(对账、统计)
|
||
- **`idx_created_at`**:按创建时间查询(分页、统计)
|
||
|
||
## 三、可能遗漏的字段(后续扩展)
|
||
|
||
### 3.1 退款相关字段
|
||
|
||
如果后续需要支持**部分退款**或**多次退款**,可以考虑添加:
|
||
|
||
```sql
|
||
`refund_amount` decimal(10,2) NOT NULL DEFAULT 0.00 COMMENT '已退款金额(累计)',
|
||
`refund_status` varchar(20) NOT NULL DEFAULT '' COMMENT '退款状态:PENDING-退款中, SUCCESS-退款成功, FAIL-退款失败',
|
||
`refund_time` datetime DEFAULT NULL COMMENT '最后退款时间',
|
||
```
|
||
|
||
**当前设计**:
|
||
- 退款信息存储在 `extra['refund_info']` 中
|
||
- 全额退款后订单状态改为 `CLOSED`
|
||
- 如果只需要全额退款,当前设计已足够
|
||
|
||
### 3.2 结算相关字段
|
||
|
||
如果后续需要**分账/结算**功能,可以考虑添加:
|
||
|
||
```sql
|
||
`settlement_status` varchar(20) NOT NULL DEFAULT '' COMMENT '结算状态:PENDING-待结算, SUCCESS-已结算, FAIL-结算失败',
|
||
`settlement_time` datetime DEFAULT NULL COMMENT '结算时间',
|
||
`settlement_amount` decimal(10,2) NOT NULL DEFAULT 0.00 COMMENT '结算金额',
|
||
```
|
||
|
||
**当前设计**:
|
||
- 结算信息可以通过 `extra` 存储
|
||
- 如果不需要复杂的结算流程,当前设计已足够
|
||
|
||
### 3.3 风控相关字段
|
||
|
||
如果需要**风控功能**,可以考虑添加:
|
||
|
||
```sql
|
||
`risk_level` varchar(20) NOT NULL DEFAULT '' COMMENT '风险等级:LOW-低, MEDIUM-中, HIGH-高',
|
||
`risk_score` int(11) NOT NULL DEFAULT 0 COMMENT '风险评分',
|
||
`risk_reason` varchar(255) NOT NULL DEFAULT '' COMMENT '风险原因',
|
||
```
|
||
|
||
**当前设计**:
|
||
- 风控信息可以通过 `extra` 存储
|
||
- 如果不需要复杂的风控系统,当前设计已足够
|
||
|
||
### 3.4 其他扩展字段
|
||
|
||
- **`user_id`**:用户ID(如果需要关联用户)
|
||
- **`device_info`**:设备信息(用于风控)
|
||
- **`remark`**:备注(管理员备注)
|
||
- **`close_reason`**:关闭原因(用户取消/超时/管理员关闭等)
|
||
|
||
## 四、设计原则总结
|
||
|
||
1. **幂等性**:通过 `uk_mch_order_no` 保证同一商户下订单号唯一
|
||
2. **可追溯性**:记录完整的订单信息、渠道信息、时间信息
|
||
3. **可扩展性**:通过 `extra` JSON 字段存储扩展信息
|
||
4. **性能优化**:合理的索引设计,支持常见查询场景
|
||
5. **业务完整性**:覆盖订单全生命周期(创建→支付→退款→关闭)
|
||
|
||
## 五、与代码的对应关系
|
||
|
||
| SQL 字段 | 代码字段 | 说明 |
|
||
|---------|---------|------|
|
||
| `pay_order_id` | `pay_order_id` | 系统订单号 |
|
||
| `merchant_id` | `merchant_id` | 商户ID |
|
||
| `app_id` | `app_id` | 应用ID |
|
||
| `mch_order_no` | `mch_order_no` | 商户订单号 |
|
||
| `method_code` | `method_code` | 支付方式 |
|
||
| `product_code` | `product_code` | 支付产品 |
|
||
| `channel_id` | `channel_id` | 通道ID |
|
||
| `amount` | `amount` | 订单金额 |
|
||
| `currency` | `currency` | 币种 |
|
||
| `status` | `status` | 订单状态 |
|
||
| `channel_order_no` | `channel_order_no` | 渠道订单号 |
|
||
| `channel_trade_no` | `channel_trade_no` | 渠道交易号 |
|
||
| `extra` | `extra` | 扩展字段(JSON) |
|
||
|
||
## 六、注意事项
|
||
|
||
1. **字段命名统一**:SQL 和代码中的字段名必须一致
|
||
2. **索引维护**:定期检查索引使用情况,优化慢查询
|
||
3. **数据归档**:历史订单数据量大时,考虑归档策略
|
||
4. **JSON 字段**:`extra` 字段使用 JSON 类型,便于扩展但查询性能略低
|
||
5. **时间字段**:`pay_time`、`expire_time` 等时间字段使用 `datetime` 类型,便于查询和统计
|
||
|