Files
mpay_v2_webman/doc/order_table_design.md
2026-03-10 13:47:28 +08:00

7.5 KiB
Raw Blame History

支付订单表设计说明

一、订单表设计原因

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 退款相关字段

如果后续需要支持部分退款多次退款,可以考虑添加:

`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 结算相关字段

如果后续需要分账/结算功能,可以考虑添加:

`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 风控相关字段

如果需要风控功能,可以考虑添加:

`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_timeexpire_time 等时间字段使用 datetime 类型,便于查询和统计