current_tip_price 全链路(超详细版)
1. 业务定义(一句话)
⚡⚡⚡ 商家配置小费规则类型与档位,买家从可选档位中选择,系统按固定额/商品金额比例/订单金额比例三路分支计算小费并写入订单。
2. 后台配置到前台计算的关系
2.1 商家后台可控项(配置映射表)
| 后台配置项 | 典型存储/来源 | 前台读取点 | 对计算的直接影响 |
|---|---|---|---|
| 小费开关/规则 | StoreTipSettingModel | TipService::cartTipPriceList | 控制是否展示与计算 |
| 小费类型 | param.type | TipService::cartTipPrice | 决定走哪个算法分支 |
| 档位列表 | param.price | cartTipPriceList | 前台展示可选金额 |
| 买家选中档位 | 请求参数 tipCheckedRule | cartTipPrice | 决定最终小费额 |
| 比例基数(商品额/订单额) | 购物车字段 | cartTipPrice | 比例模式下参与乘算 |
2.2 全链路时序图(配置 → 计算 → 落库)
flowchart TD A[商家配置小费规则] --> B[TipService.cartTipPriceList 读取配置与档位] B --> C[前台展示可选档位给买家] D[买家选择 tipCheckedRule] --> E["TipService.cartTipPrice($cart, $tipCheckedRule)"] F[购物车金额] --> E E --> G{type 判断} G -->|type=1 固定额| H[tip = tipCheckedRule 直接取值] G -->|type=2 商品比例| I[tip = items_subtotal_price × tipCheckedRule ÷ 100] G -->|type=3 订单比例| J[tip = total_price × tipCheckedRule ÷ 100] H --> K[写 current_tip_price] I --> K J --> K K --> L[renew 重算 total_price]
3. 核心入口与数据结构
3.1 核心方法链路
OrderService::saveTipPrice / saveOtherInformation
└─ TipService::cartTipPrice($cart, $tipCheckedRule) 入口
└─ TipService::detail() 读取店铺小费配置
└─ switch($tipType) 三分支计算
3.2 type 常量对照
| type 值 | 常量名 | 含义 | 公式 |
|---|---|---|---|
| 1 | TIP_TYPE_FIXED_PRICE | 固定额 | tip = tipCheckedRule |
| 2 | TIP_TYPE_PRODUCT_RATE | 商品金额比例 | tip = items_subtotal_price × tipCheckedRule ÷ 100 |
| 3 | TIP_TYPE_ORDER_RATE | 订单金额比例 | tip = total_price × tipCheckedRule ÷ 100 |
4. 完整计算逻辑
4.1 type=1 固定额(最简单)
case StoreTipSettingModel::TIP_TYPE_FIXED_PRICE:
$tipPrice = $tipCheckedRule ?? 0;
break;买哪个档位就是哪个金额,无中间计算。
4.2 type=2 商品金额比例
case StoreTipSettingModel::TIP_TYPE_PRODUCT_RATE:
$tipPrice = ($cart['items_subtotal_price'] * $tipCheckedRule) / 100;
break;- 基数:
items_subtotal_price(商品小计,不含运费/税等) - tipCheckedRule:买家选中的百分比值(如 15 表示 15%)
- 含义:按商品小计的 X% 作为小费
4.3 type=3 订单金额比例
case StoreTipSettingModel::TIP_TYPE_ORDER_RATE:
$tipPrice = ($cart['total_price'] * $tipCheckedRule) / 100;
break;- 基数:
total_price(当前应付总价,已含运费/税等) - 含义:按当前订单应付金额的 X% 作为小费
⚠️ 注意:type=3 存在自引用风险——小费会影响 total_price,而 total_price 又参与计算小费。系统设计为:档位值 tipCheckedRule 固定,小费计算时读的是当前 total_price,下单后若小费变化则 total_price 会通过 renew 更新,但此时小费值已锁定,不会再循环更新。
4.4 无配置时的默认值
if (empty($tipSetting)) {
return $tipPrice; // 返回初始值 0
}小费配置不存在或为空时,直接返回 0,不展示小费。
5. 档位值的含义
5.1 固定额模式
tipCheckedRule 的值就是小费金额本身,如买家选 5 元档 → 小费 = 5 元。
5.2 比例模式
tipCheckedRule 的值是百分比数字(如 15 表示 15%),再乘以对应基数得出实际小费金额。配置后台通常显示为”15%“而非”15”,最终计算时再除以 100。
6. 字段输出结构
| 字段 | 类型 | 含义 | 示例 |
|---|---|---|---|
o_order.current_tip_price | float | 小费金额(正数) | 5.00 |
cart.tip_price | float | 同上,会话级 | 5.00 |
cart.tipCheckedRule | float | 买家选中的档位值 | 15 |
7. 边界场景说明
7.1 比例基数为 0
items_subtotal_price=0 或 total_price=0 → 小费为 0。
7.2 比例模式下基数变动
买家选 10% 档位后,若购物车金额变化(改地址/改数量),total_price 或 items_subtotal_price 随之变化,同一档位的小费金额也会变化(动态档位)。
7.3 买家未选小费
tipCheckedRule 为 0 或空 → 小费为 0。
7.4 type 配置值非法
非 1/2/3 的 type 值,switch 无匹配分支,$tipPrice 保持初始值 0。
8. 与总价 total_price 的关系
total_price 的组成(9字段):
subtotal_price = Σ(final_line_price) 商品行小计
discount_price = 整单折扣(负数)
refund_price = 退款口径独立
current_total_price = subtotal + shipping 仅展示
total_price = subtotal - promotion - coupon + shipping + tax + tip + payment + insurance + offer
└─ tip_price 在此处被加(正数)
⚡⚡⚡ tip_price 是正数,在 total_price 公式中做加法(买家自愿支付的额外小费)。
9. 关键代码索引
| 逻辑 | 文件:行号 |
|---|---|
| 入口:cartTipPrice | TipService.php:382-406 |
| 三类型 switch 分支 | TipService.php:392-402 |
| 固定额分支 | TipService.php:393-395 |
| 商品比例分支 | TipService.php:396-398 |
| 订单比例分支 | TipService.php:399-401 |
| 档位列表读取 | TipService.php:cartTipPriceList |
| type 常量定义 | StoreTipSettingModel.php:25-27 |
| 小费保存 | OrderService::saveTipPrice |
| 总价重算 | OrderService::renew |