199 lines
8.1 KiB
PHP
199 lines
8.1 KiB
PHP
<?php
|
||
|
||
/**
|
||
* ShippingService.php
|
||
*
|
||
* @copyright 2022 beikeshop.com - All Rights Reserved
|
||
* @link https://beikeshop.com
|
||
* @author Edward Yang <yangjin@guangda.work>
|
||
* @created 2022-07-22 17:58:14
|
||
* @modified 2022-07-22 17:58:14
|
||
*/
|
||
|
||
namespace Beike\Shop\Services\TotalServices;
|
||
|
||
use Beike\Libraries\Weight;
|
||
use Beike\Models\Logistics;
|
||
use Beike\Shop\Services\CheckoutService;
|
||
use Illuminate\Support\Str;
|
||
|
||
class ShippingService{
|
||
// 运费计算
|
||
public static function getTotal(CheckoutService $checkout): ?array{
|
||
$totalService = $checkout->totalService;
|
||
$shippingMethod = $totalService->getShippingMethod();
|
||
$amount = 0;
|
||
if($shippingMethod && !is_int($checkout->cart->shipping_method_code)){
|
||
// 通过插件(固定运费) 进行计算
|
||
if(empty($shippingMethod)) return NULL;
|
||
$shippingPluginCode = self::parseShippingPluginCode($shippingMethod);
|
||
$pluginCode = Str::studly($shippingPluginCode);
|
||
if(!app('plugin')->checkActive($shippingPluginCode)){
|
||
$cart = $checkout->cart;
|
||
$cart->shipping_method_code = '';
|
||
$cart->saveOrFail();
|
||
return [];
|
||
}
|
||
$className = "Plugin\\{$pluginCode}\\Bootstrap";
|
||
if(!method_exists($className,'getShippingFee')){
|
||
throw new \Exception("请在插件 {$className} 实现方法: public function getShippingFee(CheckoutService \$checkout)");
|
||
}
|
||
$amount = (float)(new $className)->getShippingFee($checkout);
|
||
}
|
||
else{
|
||
// 通过物流进行计算
|
||
$logisticsId = (int)$checkout->cart->shipping_method_code;
|
||
$logisticsInfo = self::getLogistics($logisticsId,$checkout->cart);
|
||
if($logisticsInfo) {
|
||
// 商品信息处理 获取同一个商品的数量
|
||
$products = $checkout->selectedProducts->toArray() ?? [];
|
||
$productsList = collect($products)->groupBy('product_id')->map(function($group){
|
||
$firstInfo = $group->first();
|
||
// 重量转换 - 物流重量单位为 千克;商品重量需要进行转换
|
||
$weight = $firstInfo['product']['weight'] ?? 0;
|
||
$sumQuantity = $group->sum('quantity');
|
||
$sumWeight = (float)sprintf("%.2f",($weight * $sumQuantity));
|
||
$weightClass = $firstInfo['product']['weight_class'];
|
||
$sumWeight = Weight::convert($sumWeight,$weightClass);// 总重量 单位:克
|
||
|
||
return [
|
||
'product_id' => $firstInfo['product_id'],
|
||
'sum_quantity' => $sumQuantity,
|
||
'sum_weight' => $sumWeight,
|
||
'weight' => $weight,
|
||
'weight_class' => $weightClass,
|
||
];
|
||
});
|
||
// weight:按重量计费,num:按数量计费,free:卖家包邮
|
||
$logisticsHandleFun = 'compute_'.$logisticsInfo['type'];
|
||
$amount = self::$logisticsHandleFun($logisticsInfo,$productsList);
|
||
}
|
||
}
|
||
|
||
$totalData = [
|
||
'code' => 'shipping',
|
||
'title' => trans('shop/carts.shipping_fee'),
|
||
'amount' => $amount,
|
||
'amount_format' => currency_format($amount),
|
||
];
|
||
$totalService->amount += $totalData['amount'];
|
||
$totalService->totals[] = $totalData;
|
||
|
||
return $totalData;
|
||
}
|
||
/**
|
||
* Common: 运费计算 - 物流运费 - 获取使用的物流
|
||
* Author: wu-hui
|
||
* Time: 2023/08/22 11:55
|
||
* @param $logisticsId
|
||
* @param $cart
|
||
* @return array|mixed|mixed[]
|
||
*/
|
||
private static function getLogistics($logisticsId,$cart){
|
||
if($logisticsId <= 0){
|
||
// 获取当前收货地址国家ID
|
||
$address = $cart->guest_shipping_address ?? $cart->guest_payment_address;
|
||
$countryId = $address['country_id'];
|
||
// 获取全部物流 返回第一个物流信息ID
|
||
$logisticsList = Logistics::getAll($countryId,['type','first_weight','first_weight_fee','continuation_weight_max','add_weight','continuation_weight_fee','num_fee']);
|
||
|
||
return $logisticsList[0] ?? [];
|
||
}else{
|
||
// 获取物流信息
|
||
$logisticsInfo = Logistics::query()
|
||
->select(['type','first_weight','first_weight_fee','continuation_weight_max','add_weight','continuation_weight_fee','num_fee'])
|
||
->find($logisticsId)
|
||
->toArray();
|
||
|
||
return $logisticsInfo;
|
||
}
|
||
}
|
||
/**
|
||
* Common: 运费计算 - 物流运费 - 运费计算(按重量计费)
|
||
* Author: wu-hui
|
||
* Time: 2023/08/22 15:34
|
||
* @param $logisticsInfo
|
||
* @param $productsList
|
||
* @return float|int
|
||
*/
|
||
private static function compute_weight($logisticsInfo,$productsList){
|
||
/**
|
||
* 计算规则:
|
||
* 总重量 - 低于首重;则运费 = 【首重运费】
|
||
* 总重量 - 高于首重;则运费 = 首重按照【首重运费】计算;(剩余重量 / 每增加重量 ) * 续重运费
|
||
*/
|
||
$amount = (int)0;
|
||
$firstWeight = (int)$logisticsInfo['first_weight'];// 首重
|
||
$firstWeightFee = (float)$logisticsInfo['first_weight_fee'];// 首重运费
|
||
$addWeight = (int)$logisticsInfo['add_weight'];// 每增加重量
|
||
$continuationWeightFee = (float)$logisticsInfo['continuation_weight_fee'];// 续重运费
|
||
// 循环处理商品
|
||
foreach($productsList as $productInfo){
|
||
// 首重运费
|
||
$amount += (float)sprintf("%.2f",$firstWeightFee);
|
||
// 判断:如果总重量超过首重 则计算续重运费
|
||
$surplus = (int)$productInfo['sum_weight'] - $firstWeight;
|
||
if($surplus > 0) $amount += (float)sprintf("%.2f",($surplus / $addWeight) * $continuationWeightFee);
|
||
}
|
||
|
||
return $amount;
|
||
}
|
||
/**
|
||
* Common: 运费计算 - 物流运费 - 运费计算(按数量计费)
|
||
* Author: wu-hui
|
||
* Time: 2023/08/22 14:47
|
||
* @param $logisticsInfo
|
||
* @param $productsList
|
||
* @return float|int
|
||
*/
|
||
private static function compute_num($logisticsInfo,$productsList){
|
||
/**
|
||
* 计算规则:
|
||
* 购买数量 - 低于首件数量;则运费 = 【首件运费】
|
||
* 购买数量 - 高于首件数量;则运费 = 首件数量按照【首件运费】计算;(剩余购买数量 / 每增加件数量 ) * 续件运费
|
||
*/
|
||
$amount = (int)0;
|
||
$firstWeight = (int)$logisticsInfo['first_weight'];// 首件数量
|
||
$firstWeightFee = (float)$logisticsInfo['first_weight_fee'];// 首件运费
|
||
$addWeight = (int)$logisticsInfo['add_weight'];// 每增加件
|
||
$continuationWeightFee = (float)$logisticsInfo['continuation_weight_fee'];// 续件运费
|
||
// 循环处理商品
|
||
foreach($productsList as $productInfo){
|
||
// 首件运费
|
||
$amount += (float)sprintf("%.2f",$firstWeightFee);
|
||
// 判断:如果数量超过首件数量 则计算续件运费
|
||
$surplus = (int)$productInfo['sum_quantity'] - $firstWeight;
|
||
if($surplus > 0) $amount += (float)sprintf("%.2f",($surplus / $addWeight) * $continuationWeightFee);
|
||
}
|
||
|
||
return $amount;
|
||
}
|
||
/**
|
||
* Common: 运费计算 - 物流运费 - 运费计算(卖家包邮)
|
||
* Author: wu-hui
|
||
* Time: 2023/08/22 11:59
|
||
* @param $logisticsInfo
|
||
* @param $productsList
|
||
* @return int
|
||
*/
|
||
private static function compute_free($logisticsInfo,$productsList){
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* 通过配送方式获取插件编码
|
||
*
|
||
* @param $shippingMethod
|
||
* @return string
|
||
*/
|
||
public static function parseShippingPluginCode($shippingMethod): string
|
||
{
|
||
$methodArray = explode('.', $shippingMethod);
|
||
|
||
return $methodArray[0];
|
||
}
|
||
}
|