refund_price 全链路(超详细版)
1. 业务定义(一句话)
⚡⚡⚡ 汇总订单所有「退款中 + 退款完成」状态的退款单金额,形成退款口径,用于展示和可退额度计算;独立于 total_price 体系,不参与订单应付金额汇总。
2. 后台配置到前台计算的关系
2.1 商家后台可控项(配置映射表)
| 后台配置项 | 典型存储/来源 | 前台读取点 | 对计算的直接影响 |
|---|---|---|---|
| 退款状态流转 | 退款流程 | updateRefundStatus | 决定是否计入累计 |
| 退款单金额 | o_order_refund.price | getRefundPrice | 参与求和 |
| 退款状态 | o_order_refund.status | getRefundPrice 过滤 | 仅 IN_PROGRESS + FINISH 计入 |
| 订单应付价保护 | total_price | updateRefundStatus | 用于计算可退额度 |
2.2 全链路时序图(配置 → 计算 → 落库)
flowchart TD A[退款申请/退款完成] --> B[写 o_order_refund 退款单] B --> C[updateRefundStatus 更新退款状态] C --> D{退款状态} D -->|退款中| E[getRefundPrice: IN_PROGRESS+FINISH 求和] D -->|退款完成| F[getRefundPrice: IN_PROGRESS+FINISH 求和] D -->|退款失败| G[不计入 refund_price] E --> H[写 o_order.refund_price] F --> H H --> I[计算 refund_status: 200=部分退款/300=全额退款]
3. 核心入口与数据结构
3.1 核心方法链路
OrderRefundService.php
└─ getRefundPrice(OrderModel $orderInfo) SQL SUM,退款口径
└─ updateRefundStatus(...) 写 refund_price + refund_status
3.2 退款状态常量
| 常量值 | 常量名 | 含义 | 是否计入 refund_price |
|---|---|---|---|
| 1 | REFUND_STATUS_IN_PROGRESS | 退款中 | ✅ 是 |
| 2 | REFUND_STATUS_FINISH | 退款完成 | ✅ 是 |
| 3 | REFUND_STATUS_ERROR | 退款失败 | ❌ 否 |
⚡ 只有状态为「退款中」和「退款完成」的退款单才会被计入 refund_price。
4. 完整计算逻辑
4.1 getRefundPrice(查询统计)
public function getRefundPrice(OrderModel $orderInfo) : float
{
return OrderRefundModel::master()->where([
'store_id' => $this->storeId,
'order_id' => $orderInfo->getId(),
])->whereIn('status', [
OrderRefundModel::REFUND_STATUS_IN_PROGRESS,
OrderRefundModel::REFUND_STATUS_FINISH,
])->sum('price');
}特点:直接 SQL SUM,不走 PHP 循环,高效。
⚡⚡⚡ refund_price 的语义是「已申请退款的金额(无论是否到账)」,而不是「已实际退款到账的金额」。
4.2 updateRefundStatus(状态与金额联动)
// 当 status == 退款中 (REFUND_STATUS_IN_PROGRESS)
$refundPrice = $this->getRefundPrice($orderInfo);
$refundStatus = bcsub($orderInfo['total_price'], $refundPrice, 2) <= 0 ? '300' : '200';
$save = [
'refund_price' => $refundPrice,
'refund_status' => $refundStatus, // 200=部分退款, 300=全额退款
];refund_status 语义:
| refund_status | 含义 | 触发条件 |
|---|---|---|
| 200 | 部分退款 | total_price - refund_price > 0(还有余款未退) |
| 300 | 全额退款 | total_price - refund_price <= 0(退够了) |
4.3 refund_price 与 total_price 的关系
o_order.refund_price = Σ(退款单.price),仅含 IN_PROGRESS + FINISH 状态
o_order.total_price = Σ(9个current_字段),订单应付金额
两者完全独立:
- total_price 是「订单应收多少钱」
- refund_price 是「已经申请退了多少」
- total_price - refund_price = 「还需退多少 / 已退够否」
⚡ 重要澄清:refund_price 不参与 total_price 的9字段汇总,total_price 的9字段中没有 refund_price。两者是独立的平行指标。
5. 字段输出结构
| 字段 | 类型 | 含义 | 示例 |
|---|---|---|---|
o_order.refund_price | float | 累计退款金额(正数) | 80.00 |
o_order.refund_status | string | 退款状态(200/300等) | 200 |
o_order_refund[].price | float | 单笔退款金额 | 50.00 |
o_order_refund[].status | int | 单笔退款状态 | 2 |
6. 边界场景说明
6.1 退款失败(status=3)不计入
失败退款单有独立的回滚逻辑(dec('refund_price', price)),不会长期占用 refund_price 累计。
6.2 多笔退款单并存
同时存在 IN_PROGRESS(50) + FINISH(30) → refund_price = 80,refund_status 由总额判断。
6.3 退款中变为退款完成
status 从 1→2,getRefundPrice 的条件仍然包含两者,结果不变——refund_price 保持,但 refund_status 可能从200变为300(取决于总金额)。
6.4 退款完成后又申请新退款
第二次退款中,新增的金额会叠加,refund_status 重新判断。
6.5 total_price 被修改后退款金额未同步
若退款时 total_price 因优惠等原因已变化,已计入的退款仍按原金额算(退款单 price 字段是固定值)。可能出现「退款金额 > total_price」(会触发 refund_status=300 全额判断)。
7. 关键代码索引
| 逻辑 | 文件:行号 |
|---|---|
| getRefundPrice SQL SUM | OrderRefundService.php:566-572 |
| updateRefundStatus 写回 | OrderRefundService.php:263-409 |
| 退款状态常量 | OrderRefundModel.php:35-37 |
| 退款完成回滚逻辑 | OrderRefundService.php 退款完成分支 |
| total_price 9字段汇总(无 refund_price) | OrderService.php:2282-2290 |