current_tip_price 全链路(超详细版)

1. 业务定义(一句话)

⚡⚡⚡ 商家配置小费规则类型与档位,买家从可选档位中选择,系统按固定额/商品金额比例/订单金额比例三路分支计算小费并写入订单。

2. 后台配置到前台计算的关系

2.1 商家后台可控项(配置映射表)

后台配置项典型存储/来源前台读取点对计算的直接影响
小费开关/规则StoreTipSettingModelTipService::cartTipPriceList控制是否展示与计算
小费类型param.typeTipService::cartTipPrice决定走哪个算法分支
档位列表param.pricecartTipPriceList前台展示可选金额
买家选中档位请求参数 tipCheckedRulecartTipPrice决定最终小费额
比例基数(商品额/订单额)购物车字段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 值常量名含义公式
1TIP_TYPE_FIXED_PRICE固定额tip = tipCheckedRule
2TIP_TYPE_PRODUCT_RATE商品金额比例tip = items_subtotal_price × tipCheckedRule ÷ 100
3TIP_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_pricefloat小费金额(正数)5.00
cart.tip_pricefloat同上,会话级5.00
cart.tipCheckedRulefloat买家选中的档位值15

7. 边界场景说明

7.1 比例基数为 0

items_subtotal_price=0total_price=0 → 小费为 0。

7.2 比例模式下基数变动

买家选 10% 档位后,若购物车金额变化(改地址/改数量),total_priceitems_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. 关键代码索引

逻辑文件:行号
入口:cartTipPriceTipService.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