You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
289 lines
11 KiB
289 lines
11 KiB
11 months ago
|
<?php
|
||
|
// +----------------------------------------------------------------------
|
||
|
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
|
||
|
// +----------------------------------------------------------------------
|
||
|
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
|
||
|
// +----------------------------------------------------------------------
|
||
|
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
|
||
|
// +----------------------------------------------------------------------
|
||
|
// | Author: 萤火科技 <admin@yiovo.com>
|
||
|
// +----------------------------------------------------------------------
|
||
|
declare (strict_types=1);
|
||
|
|
||
|
namespace app\store\service\order;
|
||
|
|
||
|
use think\facade\Db;
|
||
|
use app\store\model\eorder\Setting as SettingModel;
|
||
|
use app\store\model\store\Address as StoreAddressModel;
|
||
|
use app\store\model\eorder\Template as EOrderTemplateModel;
|
||
|
use app\store\service\order\Delivery as DeliveryService;
|
||
|
use app\common\service\BaseService;
|
||
|
use app\common\service\Order as OrderService;
|
||
|
use app\common\service\Goods as GoodsService;
|
||
|
use app\common\service\order\Shipping as ShippingService;
|
||
|
use app\common\library\helper;
|
||
|
use app\common\library\eOrder\Facade as EOrderFacade;
|
||
|
use app\store\model\Order as OrderModel;
|
||
|
use cores\exception\BaseException;
|
||
|
|
||
|
/**
|
||
|
* 服务层:电子面单发货事件
|
||
|
* Class EOrder
|
||
|
* @package app\store\service\order
|
||
|
*/
|
||
|
class EOrder extends BaseService
|
||
|
{
|
||
|
// 发货方式: 电子面单
|
||
|
const DELIVERY_METHOD_EORDER = 30;
|
||
|
|
||
|
// 电子面单模板
|
||
|
private string $eorderContent = '';
|
||
|
|
||
|
/**
|
||
|
* 电子面单发货
|
||
|
* @param int $orderId
|
||
|
* @param array $param
|
||
|
* @return bool
|
||
|
* @throws BaseException
|
||
|
* @throws \think\db\exception\DataNotFoundException
|
||
|
* @throws \think\db\exception\DbException
|
||
|
* @throws \think\db\exception\ModelNotFoundException
|
||
|
*/
|
||
|
public function eorder(int $orderId, array $param): bool
|
||
|
{
|
||
|
// 设置默认的参数
|
||
|
$param = helper::setQueryDefaultValue($param, [
|
||
|
// 发货方式: 电子面单
|
||
|
'deliveryMethod' => self::DELIVERY_METHOD_EORDER,
|
||
|
// 整单发货
|
||
|
'isAllPack' => false,
|
||
|
// 发货的商品
|
||
|
'packGoodsData' => [],
|
||
|
// 同步至微信小程序《发货信息录入》
|
||
|
'syncMpWeixinShipping' => 1,
|
||
|
]);
|
||
|
// 获取订单详情
|
||
|
$detail = OrderModel::detail($orderId);
|
||
|
// 验证订单是否满足发货条件
|
||
|
$DeliveryService = new DeliveryService;
|
||
|
if (!$DeliveryService->verifyDelivery([$detail])) {
|
||
|
$this->error = $DeliveryService->getError();
|
||
|
return false;
|
||
|
}
|
||
|
// 执行订单发货操作
|
||
|
Db::transaction(function () use ($DeliveryService, $orderId, $detail, $param) {
|
||
|
// 获取电子面单模板记录
|
||
|
$templateInfo = $this->getEOrderTemplateInfo($param['templateId']);
|
||
|
// 请求API获取电子面单内容
|
||
|
$eOrderTemplate = $this->getEOrderTemplate($orderId, $param['addressId'], $param['packGoodsData'], $templateInfo);
|
||
|
// 订单发货事件
|
||
|
$DeliveryService->deliveryEvent($detail, array_merge($param, [
|
||
|
// 物流公司ID
|
||
|
'expressId' => $templateInfo['express_id'],
|
||
|
// 物流单号
|
||
|
'expressNo' => $eOrderTemplate['expressNo'],
|
||
|
// 电子面单内容
|
||
|
'eorderHtml' => $this->getEOrderContent(),
|
||
|
]));
|
||
|
// 获取已发货的订单
|
||
|
$completed = OrderModel::detail($orderId, ['goods', 'trade']);
|
||
|
// 发货信息同步微信平台
|
||
|
(new ShippingService)->syncMpWeixinShipping($completed, [
|
||
|
// 同步至微信小程序《发货信息录入》
|
||
|
'syncMpWeixinShipping' => $param['syncMpWeixinShipping'],
|
||
|
// 物流模式:1物流配送 3虚拟商品 4用户自提
|
||
|
'logisticsType' => ShippingService::DELIVERY_EXPRESS,
|
||
|
// 物流公司ID
|
||
|
'expressId' => $templateInfo['express_id'],
|
||
|
// 物流单号
|
||
|
'expressNo' => $eOrderTemplate['expressNo'],
|
||
|
]);
|
||
|
});
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 电子面单发货
|
||
|
* @param int $orderId 订单ID
|
||
|
* @param int $addressId 收货地址ID
|
||
|
* @param array $packGoodsData 发货的商品
|
||
|
* @param $templateInfo
|
||
|
* @return array
|
||
|
* @throws BaseException
|
||
|
* @throws \think\db\exception\DataNotFoundException
|
||
|
* @throws \think\db\exception\DbException
|
||
|
* @throws \think\db\exception\ModelNotFoundException
|
||
|
*/
|
||
|
private function getEOrderTemplate(int $orderId, int $addressId, array $packGoodsData, $templateInfo): array
|
||
|
{
|
||
|
// 订单详情
|
||
|
$orderInfo = OrderModel::detail($orderId, ['goods', 'address']);
|
||
|
// 获取电子面单模板记录
|
||
|
$templateInfo = $this->getEOrderTemplateInfo($templateInfo['template_id']);
|
||
|
// 获取电子面单基础设置
|
||
|
$options = $this->getEOrderOption();
|
||
|
// 实例化电子面单API驱动
|
||
|
$EOrderApi = EOrderFacade::store($templateInfo['provider']);
|
||
|
// 设置API配置参数
|
||
|
$EOrderApi->setOptions($options['providerConfig']);
|
||
|
// 设置电子面单模板信息
|
||
|
$EOrderApi->setEleTemplate($this->getEleTemplate($templateInfo));
|
||
|
// 设置发货单信息
|
||
|
$EOrderApi->setDeliverOrder($this->getDeliverOrder($orderInfo, $packGoodsData));
|
||
|
// 设置发件人信息
|
||
|
$EOrderApi->setSender($this->getSender($addressId));
|
||
|
// 设置收件人信息
|
||
|
$EOrderApi->setReceiver($this->getReceiver($orderInfo));
|
||
|
// 获取电子面单
|
||
|
$result = $EOrderApi->handle();
|
||
|
// 记录电子面单的内容
|
||
|
$this->eorderContent = $result['content'];
|
||
|
return $result;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 获取收件人信息
|
||
|
* @param $orderInfo
|
||
|
* @return array
|
||
|
*/
|
||
|
private function getReceiver($orderInfo): array
|
||
|
{
|
||
|
$addressInfo = $orderInfo['address'];
|
||
|
return [
|
||
|
'name' => $addressInfo['name'],
|
||
|
'mobile' => $addressInfo['phone'],
|
||
|
'provinceName' => $addressInfo['region']['province'],
|
||
|
'cityName' => $addressInfo['region']['city'],
|
||
|
'expAreaName' => $addressInfo['region']['region'],
|
||
|
'address' => $addressInfo['detail']
|
||
|
];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 获取发件人信息
|
||
|
* @param int $addressId
|
||
|
* @return array
|
||
|
*/
|
||
|
private function getSender(int $addressId): array
|
||
|
{
|
||
|
$addressInfo = StoreAddressModel::detail($addressId);
|
||
|
return [
|
||
|
'name' => $addressInfo['name'],
|
||
|
'mobile' => $addressInfo['phone'],
|
||
|
'provinceName' => $addressInfo['region']['province'],
|
||
|
'cityName' => $addressInfo['region']['city'],
|
||
|
'expAreaName' => $addressInfo['region']['region'],
|
||
|
'address' => $addressInfo['detail']
|
||
|
];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 获取发货单信息
|
||
|
* @param $orderInfo
|
||
|
* @param array $packGoodsData 发货的商品
|
||
|
* @return array
|
||
|
*/
|
||
|
private function getDeliverOrder($orderInfo, array $packGoodsData): array
|
||
|
{
|
||
|
// 构建商品信息
|
||
|
$commodity = $this->buildCommodity($orderInfo, $packGoodsData);
|
||
|
return [
|
||
|
// 订单编号,不可重复提交
|
||
|
'orderCode' => OrderService::createOrderNo(),
|
||
|
// 包裹总重量kg
|
||
|
'weight' => helper::getArrayColumnSum($commodity, 'goodsWeight'),
|
||
|
// 包裹数
|
||
|
'quantity' => 1,
|
||
|
//是 否通知快递员上门揽件 0通知 1不通知
|
||
|
'isNotice' => 1,
|
||
|
// 商品信息
|
||
|
'commodity' => $commodity,
|
||
|
];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 构建商品信息
|
||
|
* @param $orderInfo
|
||
|
* @param array $packGoodsData 发货的商品
|
||
|
* @return array
|
||
|
*/
|
||
|
private function buildCommodity($orderInfo, array $packGoodsData): array
|
||
|
{
|
||
|
$commodity = [];
|
||
|
$orderGoodsIds = helper::getArrayColumn($packGoodsData, 'orderGoodsId');
|
||
|
foreach ($orderInfo['goods'] as $goods) {
|
||
|
if (in_array($goods['order_goods_id'], $orderGoodsIds)) {
|
||
|
$goodsProps = !empty($goods['goods_props']) ? GoodsService::goodsPropsToAttr($goods['goods_props']) : '';
|
||
|
$commodity[$goods['order_goods_id']] = [
|
||
|
'orderGoodsId' => $goods['order_goods_id'], // 订单商品ID
|
||
|
'goodsName' => $goods['goods_name'], // 商品名称
|
||
|
'goodsProps' => $goodsProps, // 商品规格
|
||
|
'goodsquantity' => $goods['total_num'], // 商品数量
|
||
|
'goodsWeight' => $goods['goods_weight'] // 商品重量kg
|
||
|
];
|
||
|
}
|
||
|
}
|
||
|
return $commodity;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 获取电子面单模板信息
|
||
|
* @param $templateInfo
|
||
|
* @return array
|
||
|
* @throws BaseException
|
||
|
*/
|
||
|
private function getEleTemplate($templateInfo): array
|
||
|
{
|
||
|
$shipperCodeKey = $templateInfo['provider'] === 'kdniao' ? 'kdniao_code' : 'kuaidi100_code';
|
||
|
$shipperCode = $templateInfo['express'][$shipperCodeKey] ?? null;
|
||
|
if (empty($shipperCode)) {
|
||
|
$codeEnum = ['kdniao' => '快递鸟', 'kd100' => '快递100'];
|
||
|
throwError("很抱歉,物流公司记录不存在{$codeEnum[$templateInfo['provider']]}编码,请先补充");
|
||
|
}
|
||
|
return [
|
||
|
'shipperCode' => $templateInfo['express'][$shipperCodeKey],
|
||
|
'customerName' => $templateInfo['config']['customerName'],
|
||
|
'customerPwd' => $templateInfo['config']['customerPwd'],
|
||
|
'sendSite' => $templateInfo['config']['sendSite'],
|
||
|
'monthCode' => $templateInfo['config']['monthCode'],
|
||
|
'payType' => $templateInfo['config']['payType'],
|
||
|
];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 获取电子面单模板记录
|
||
|
* @param int $templateId
|
||
|
* @return EOrderTemplateModel|false|\think\Model
|
||
|
* @throws BaseException
|
||
|
*/
|
||
|
private function getEOrderTemplateInfo(int $templateId)
|
||
|
{
|
||
|
$model = EOrderTemplateModel::detail($templateId);
|
||
|
empty($model) && throwError('未找到电子面单模板记录');
|
||
|
return EOrderTemplateModel::related($model, ['express']);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 获取电子面单基础设置
|
||
|
* @return array|mixed
|
||
|
* @throws BaseException
|
||
|
* @throws \think\db\exception\DataNotFoundException
|
||
|
* @throws \think\db\exception\DbException
|
||
|
* @throws \think\db\exception\ModelNotFoundException
|
||
|
*/
|
||
|
private function getEOrderOption()
|
||
|
{
|
||
|
$options = SettingModel::getBasic();
|
||
|
!$options['enable'] && throwError('很抱歉,电子面单功能尚未开启');
|
||
|
return $options;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 返回电子面单内容
|
||
|
* @return string
|
||
|
*/
|
||
|
public function getEOrderContent(): string
|
||
|
{
|
||
|
return $this->eorderContent;
|
||
|
}
|
||
|
}
|