简介
本文件面向电商平台,提供 DouPHP 系统中“交易记录”相关的数据模型设计与实现说明。重点覆盖以下三张核心表:
- 支付流水表(dou_order_payment):记录每笔订单的支付分腿、渠道、金额、状态、第三方交易号、原始报文等,支撑混合支付、幂等与对账。
- 退款记录表(dou_order_refund):记录退款申请、分腿退款、渠道处理结果、审核与完成时间,支撑售后退款流程。
- 订单状态日志表(dou_order_status_log):记录订单状态变更轨迹,用于审计追踪。
同时结合代码中的支付服务与售后流程,给出交易完整性保证、异常处理、幂等设计、对账思路与最佳实践,帮助构建稳健的交易数据模型。
项目结构与范围
围绕交易与退款的核心实现位于支付服务与售后流程中,数据库定义集中在模块备份 SQL 与系统表结构文档中。本文件聚焦于:
- 支付流水表(dou_order_payment)
- 退款记录表(dou_order_refund)
- 订单状态日志表(dou_order_status_log)
- 与订单主表(dou_order)及地址快照(dou_order_address)的关联
graph TB
A["订单表<br/>dou_order"] --> B["支付流水表<br/>dou_order_payment"]
A --> C["退款记录表<br/>dou_order_refund"]
A --> D["订单状态日志表<br/>dou_order_status_log"]
A --> E["订单地址快照<br/>dou_order_address"]
B --> C
核心数据模型
本节以代码与SQL为依据,梳理三张关键表的字段含义、约束与用途。
-
支付流水表(dou_order_payment)
- 关键字段:支付流水号、订单ID/单号、支付网关、支付金额、支付状态、第三方交易号、支付凭证、请求/回调原始报文、支付完成时间、过期时间、创建时间。
- 作用:记录每一笔支付“腿”,支持多通道/钱包+网关混合支付;通过唯一键保障幂等;通过原始报文便于对账与排障。
- 索引:按订单、网关、状态与时间建立查询索引,提升对账与超时关闭效率。
-
退款记录表(dou_order_refund)
- 关键字段:退款流水号、订单ID、售后单ID、关联支付流水ID、渠道、退款金额、退款状态、回调原始报文、退款完成时间、创建时间。
- 作用:记录退款申请与执行结果,区分“待处理/成功/部分退款/已退款”等状态;支持分腿退款与多渠道差异处理。
- 索引:按订单ID建立查询索引,便于统计与报表。
-
订单状态日志表(dou_order_status_log)
- 关键字段:订单ID、原状态、新状态、原因、操作者类型、操作者ID、IP、创建时间。
- 作用:完整记录订单生命周期状态变更,满足审计与合规要求。
架构总览
支付与退款在业务层由支付服务统一编排,涉及订单、钱包余额、第三方支付网关与售后流程。整体流程如下:
sequenceDiagram
participant U as "用户"
participant O as "订单服务"
participant P as "支付服务"
participant W as "钱包服务"
participant G as "支付网关"
participant DB as "数据库"
U->>O : 提交订单
O->>DB : 锁定订单行(防并发)
O->>P : 发起支付(可能含钱包+网关)
alt 钱包支付
P->>W : 扣款(createMoney)
W-->>P : 扣款结果
P->>DB : 写入支付流水(leg)
end
alt 网关支付
P->>G : 下单/预授权
G-->>P : 回调通知
P->>DB : 更新支付流水状态
end
P->>O : 标记订单已支付/部分支付
O-->>U : 返回支付结果
详细组件分析
支付流水表(dou_order_payment)设计要点
- 幂等性:通过 payment_sn 唯一键与 gateway + transaction_id 唯一键,避免重复入账。
- 分腿支付:同一订单可有多条支付流水(钱包、不同网关),便于混合支付与分渠道对账。
- 原始报文:raw_request/raw_callback 保留三方交互原文,便于问题定位与对账核对。
- 状态机:pending/succeeded/partial_refunded/refunded/expired 等状态驱动后续流程。
- 索引策略:order_id、status+gateway+created_at、status+expired_at 等复合索引优化查询与定时任务。
退款记录表(dou_order_refund)设计要点
- 退款分腿:按 dou_order_payment 的成功支付腿进行拆分退款,支持部分退款与多次补退。
- 渠道差异:钱包渠道同步退回余额并置 succeeded;网关渠道登记 pending,待人工或回调收尾。
- 幂等与容差:使用金额容差(AMOUNT_EPSILON)避免浮点误差导致的状态误判。
- 审计字段:aftersale_id、channel、raw_callback、refunded_at 等字段支撑售后与对账。
flowchart TD
Start(["开始退款"]) --> LoadLegs["加载成功支付腿"]
LoadLegs --> ForEach{"遍历每条腿"}
ForEach --> |钱包| WalletRefund["调用钱包退回(createMoney)"]
WalletRefund --> MarkRefunded["写退款记录(succeeded)<br/>更新支付腿状态"]
ForEach --> |网关| PendingRefund["写退款记录(pending)<br/>等待人工/回调"]
MarkRefunded --> Next{"是否还有腿"}
PendingRefund --> Next
Next --> |是| ForEach
Next --> |否| End(["结束"])
订单状态日志表(dou_order_status_log)设计要点
- 全链路审计:记录 from_status/to_status/reason/operator_type/operator_id/ip,满足合规与排障需求。
- 触发点:订单创建、支付成功、发货、签收、取消、退款完成等关键节点均需落盘。
- 查询优化:order_id + created_at 复合索引,便于按订单拉取时间线。
售后退款与订单状态联动
- 售后完成时,汇总该订单所有 succeeded 的退款金额,计算整单或部分退款状态,并回写订单退款状态。
- 同时更新售后单已退款金额与处理时间,形成闭环。
sequenceDiagram
participant AS as "售后流程"
participant DB as "数据库"
AS->>DB : 汇总 succeeded 退款金额
DB-->>AS : 退款合计
AS->>DB : 更新订单退款状态(全部/部分)
AS->>DB : 更新售后单已退款金额与处理时间
与订单地址快照的关系
- 邮件与通知中需要收货人信息,系统从 dou_order_address 快照补齐联系人、电话、地址等字段,确保历史订单展示一致。
依赖关系分析
- 支付服务依赖:
- 订单服务:读取/锁定订单、更新订单状态与累计支付金额。
- 钱包服务:扣款与退款(createMoney)。
- 支付网关:下单、回调、退款(部分渠道需人工处理)。
- 数据依赖:
- dou_order_payment 与 dou_order_refund 均依赖 dou_order 的主键与单号。
- 售后流程依赖 dou_order_refund 的汇总结果来更新订单退款状态。
graph LR
O["订单(dou_order)"] --> P["支付流水(dou_order_payment)"]
O --> R["退款记录(dou_order_refund)"]
P --> R
O --> L["状态日志(dou_order_status_log)"]
性能与一致性
- 事务与锁:
- 支付与退款关键路径使用数据库事务,并在必要时对订单行加锁(FOR UPDATE),防止并发竞态。
- 幂等设计:
- 支付流水与退款流水通过唯一键保障幂等;钱包退款前再次校验状态,避免重复退款。
- 金额精度:
- 使用 decimal 存储金额,并通过 AMOUNT_EPSILON 容差比较,避免浮点误差导致状态误判。
- 索引优化:
- 针对高频查询(按订单、按状态+时间、按过期清理)建立复合索引,降低慢查询风险。
- 异步与重试:
- 对网关回调失败场景,建议引入重试队列与补偿任务,确保最终一致性。
故障排查指南
- 支付未到账:
- 检查 dou_order_payment 是否存在对应 leg,确认 status 是否为 succeeded;核对 raw_callback 与 transaction_id。
- 重复支付:
- 核查 payment_sn 与 gateway+transaction_id 唯一约束是否生效;检查幂等逻辑是否被绕过。
- 退款未生效:
- 钱包渠道:确认 createMoney 是否成功,退款记录是否为 succeeded;网关渠道:确认是否已人工处理并完成回调。
- 订单状态不一致:
- 查看 dou_order_status_log 时间线,定位状态变更点;核对支付/退款汇总逻辑是否正确更新订单状态。
结论
DouPHP 的交易记录体系以 dou_order_payment、dou_order_refund 与 dou_order_status_log 为核心,配合订单主表与地址快照,形成了完整的支付、退款与审计闭环。通过事务、行锁、唯一键与原始报文留存,实现了高可靠性的交易数据处理能力。建议在扩展中对账模块(如 dou_reconciliation)基于现有流水与退款记录进行聚合比对,进一步提升财务准确性与可追溯性。
附录:字段字典与索引建议
- 支付流水表(dou_order_payment)
- 字段:id、payment_sn、order_id、order_sn、gateway、amount、status、transaction_id、pay_evidence、raw_request、raw_callback、paid_at、expired_at、created_at
- 索引:payment_sn 唯一、gateway+transaction_id 唯一、order_id、status+expired_at、status+gateway+created_at
- 退款记录表(dou_order_refund)
- 字段:id、refund_sn、order_id、aftersale_id、order_payment_id、channel、amount、status、raw_callback、refunded_at、created_at
- 索引:refund_sn 唯一、order_id
- 订单状态日志表(dou_order_status_log)
- 字段:id、order_id、from_status、to_status、reason、operator_type、operator_id、ip、created_at
- 索引:order_id+created_at