2023-07-27 21:28:00 +08:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace App\Services\Ship;
|
|
|
|
|
|
|
|
|
|
use App\Models\GoodsSku;
|
|
|
|
|
use App\Models\ShopShip;
|
2023-07-28 15:35:47 +08:00
|
|
|
use App\Models\Waybill;
|
2023-07-27 21:28:00 +08:00
|
|
|
use App\Services\Business\KuaiTuanTuan\FaceSheet;
|
|
|
|
|
|
2023-07-28 15:35:47 +08:00
|
|
|
class WayBillService
|
2023-07-27 21:28:00 +08:00
|
|
|
{
|
|
|
|
|
public $orders;
|
|
|
|
|
public $objectId;
|
2023-08-16 13:42:29 +08:00
|
|
|
// 快递便携式一联单
|
|
|
|
|
public $sfOne = 'https://file-link.pinduoduo.com/sf_one';
|
|
|
|
|
public $sfOneTemplate = 'sf_one1688973997895.xml';
|
|
|
|
|
// 快递三联面单
|
|
|
|
|
public $sfThree = 'https://file-link.pinduoduo.com/sf_three';
|
|
|
|
|
public $sfThreeTemplate = 'sf_three1677381064344.xml';
|
|
|
|
|
// 标准模板
|
|
|
|
|
public $sfStd = 'https://file-link.pinduoduo.com/sf_std';
|
|
|
|
|
public $sfStdTemplate = 'sf_std1677380804913.xml';
|
2023-08-18 16:54:04 +08:00
|
|
|
// 时效类型
|
|
|
|
|
public $timedDeliveryCode;
|
2023-07-27 21:28:00 +08:00
|
|
|
|
2023-07-28 19:13:51 +08:00
|
|
|
public function getContents()
|
2023-07-27 21:28:00 +08:00
|
|
|
{
|
2023-07-29 17:57:36 +08:00
|
|
|
// 已下单过的订单不再下单
|
2023-07-28 19:13:51 +08:00
|
|
|
$contents = [];
|
2023-07-27 21:28:00 +08:00
|
|
|
foreach ($this->orders as $shopId => $order) {
|
2023-07-28 15:35:47 +08:00
|
|
|
// 订单取消的情况暂不处理
|
2023-08-26 11:07:58 +08:00
|
|
|
$shopShip = $this->getShopShip($shopId);
|
2023-07-27 21:28:00 +08:00
|
|
|
$faceSheet = new FaceSheet();
|
2023-08-25 18:38:07 +08:00
|
|
|
$faceSheet->setShop($shopShip);
|
2023-07-27 21:28:00 +08:00
|
|
|
foreach ($order as $item) {
|
2023-08-25 18:38:07 +08:00
|
|
|
[$sender, $orderInfo, $wpCode] = $this->prepareRequest($item, $shopShip);
|
2023-08-26 11:07:58 +08:00
|
|
|
$waybill = $this->saveWayBill($item, $shopShip, $sender);
|
2023-08-09 15:31:29 +08:00
|
|
|
|
2023-07-29 17:57:36 +08:00
|
|
|
if (empty($waybill->id)) {
|
|
|
|
|
$resp = $faceSheet->getWayBill($sender, $orderInfo, $wpCode);
|
|
|
|
|
if (isset($resp['pdd_waybill_get_response'])) {
|
|
|
|
|
$data = $resp['pdd_waybill_get_response']['modules'][0];
|
|
|
|
|
$printData = json_decode($data['print_data'], true);
|
|
|
|
|
$waybill->request_id = $resp['pdd_waybill_get_response']['request_id'];
|
|
|
|
|
$waybill->encryptedData = $printData['encryptedData'];
|
|
|
|
|
$waybill->signature = $printData['signature'];
|
|
|
|
|
$waybill->templateUrl = $printData['templateUrl'];
|
|
|
|
|
$waybill->ver = $printData['ver'];
|
|
|
|
|
$waybill->waybill_code = $data['waybill_code'];
|
|
|
|
|
$waybill->save();
|
|
|
|
|
// 返回待打印内容
|
|
|
|
|
$contents[$waybill->id] = [
|
|
|
|
|
'addData' => [
|
|
|
|
|
'sender' => $sender,
|
|
|
|
|
],
|
|
|
|
|
'encryptedData' => $printData['encryptedData'],
|
|
|
|
|
'signature' => $printData['signature'],
|
2023-08-17 14:01:32 +08:00
|
|
|
'templateUrl' => env('APP_URL') . '/ktt/' . $this->sfOneTemplate, // 电子面单模板
|
2023-07-29 17:57:36 +08:00
|
|
|
'ver' => $printData['ver'],
|
|
|
|
|
'userid' => $waybill->user_id,
|
|
|
|
|
'items' => $item['items'],
|
|
|
|
|
'documentID' => $waybill->id,
|
2023-08-15 16:33:36 +08:00
|
|
|
'order_id' => $item['id'],
|
|
|
|
|
'participate_no' => $waybill->participate_no,
|
|
|
|
|
'note' => $waybill->note,
|
2023-07-29 17:57:36 +08:00
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-07-28 19:13:51 +08:00
|
|
|
$contents[$waybill->id] = [
|
|
|
|
|
'addData' => [
|
|
|
|
|
'sender' => $sender,
|
|
|
|
|
],
|
2023-07-29 17:57:36 +08:00
|
|
|
'encryptedData' => $waybill->encryptedData,
|
|
|
|
|
'signature' => $waybill->signature,
|
2023-08-17 14:01:32 +08:00
|
|
|
'templateUrl' => env('APP_URL') . '/ktt/' . $this->sfOneTemplate, // 电子面单模板
|
2023-07-29 17:57:36 +08:00
|
|
|
'ver' => $waybill->ver,
|
2023-07-28 19:13:51 +08:00
|
|
|
'userid' => $waybill->user_id,
|
2023-07-29 17:57:36 +08:00
|
|
|
'items' => json_decode($waybill->items, true),
|
2023-07-28 19:13:51 +08:00
|
|
|
'documentID' => $waybill->id,
|
2023-08-15 16:33:36 +08:00
|
|
|
'order_id' => $item['id'],
|
|
|
|
|
'participate_no' => $waybill->participate_no,
|
|
|
|
|
'note' => $waybill->note,
|
2023-07-28 19:13:51 +08:00
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $contents;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function getDocumentsAndOrderIds($contents)
|
|
|
|
|
{
|
|
|
|
|
// 打印单,根据商品排序
|
|
|
|
|
$items = [];
|
|
|
|
|
foreach ($contents as $docId => $content) {
|
|
|
|
|
foreach ($content['items'] as $item) {
|
|
|
|
|
if ($item['is_single']) {
|
|
|
|
|
$items[$item['external_sku_id']][] = $docId;
|
2023-07-27 21:28:00 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-07-28 19:13:51 +08:00
|
|
|
ksort($items);
|
|
|
|
|
$documents = $orderIds = $hasIds = [];
|
|
|
|
|
foreach ($items as $docIds) {
|
|
|
|
|
$docIds = array_unique($docIds);
|
|
|
|
|
$docIds = array_diff($docIds, $hasIds);
|
|
|
|
|
$hasIds = array_merge($hasIds, $docIds);
|
|
|
|
|
foreach ($docIds as $docId) {
|
|
|
|
|
$orderIds[] = $contents[$docId]['order_id'];
|
|
|
|
|
$documents[] = $contents[$docId];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return [$documents, $orderIds];
|
2023-07-27 21:28:00 +08:00
|
|
|
}
|
|
|
|
|
|
2023-08-26 11:07:58 +08:00
|
|
|
private function saveWayBill($order, $shop, $senderConfig)
|
2023-07-27 21:28:00 +08:00
|
|
|
{
|
2023-07-29 17:57:36 +08:00
|
|
|
$waybill = Waybill::query()->firstOrNew(
|
|
|
|
|
['order_sn' => $order['order_sn']]
|
|
|
|
|
);
|
|
|
|
|
|
2023-07-28 15:35:47 +08:00
|
|
|
$waybill->shop_id = $shop->shop_id;
|
2023-07-27 21:28:00 +08:00
|
|
|
$waybill->object_id = $this->objectId;
|
|
|
|
|
|
|
|
|
|
$waybill->sender_country = $senderConfig['country'];
|
|
|
|
|
$waybill->sender_province = $senderConfig['province'];
|
|
|
|
|
$waybill->sender_city = $senderConfig['city'];
|
|
|
|
|
$waybill->sender_district = $senderConfig['district'];
|
|
|
|
|
$waybill->sender_detail = $senderConfig['detail'];
|
|
|
|
|
$waybill->sender_name = $senderConfig['name'];
|
|
|
|
|
$waybill->sender_mobile = $senderConfig['mobile'];
|
|
|
|
|
|
|
|
|
|
$waybill->recipient_province = $order['recipient_province'];
|
|
|
|
|
$waybill->recipient_city = $order['recipient_city'];
|
|
|
|
|
$waybill->recipient_district = $order['recipient_district'];
|
|
|
|
|
$waybill->recipient_detail = $order['recipient_detail'];
|
|
|
|
|
$waybill->recipient_name = $order['recipient_name'];
|
|
|
|
|
$waybill->recipient_mobile = $order['recipient_mobile'];
|
|
|
|
|
|
|
|
|
|
$waybill->user_id = $shop->owner_id;
|
|
|
|
|
$waybill->wp_code = $senderConfig['wp_code'];
|
|
|
|
|
$waybill->order_sn = $order['order_sn'];
|
2023-07-29 17:57:36 +08:00
|
|
|
$waybill->order_id = $order['id'];
|
2023-08-15 16:33:36 +08:00
|
|
|
$waybill->participate_no = $order['participate_no'];
|
|
|
|
|
$waybill->note = $order['note'];
|
2023-07-27 21:28:00 +08:00
|
|
|
$waybill->items = json_encode($order['items'], 256);
|
|
|
|
|
|
|
|
|
|
return $waybill;
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-25 18:38:07 +08:00
|
|
|
private function getTimedDelivery($orderItem)
|
2023-08-18 16:54:04 +08:00
|
|
|
{
|
|
|
|
|
$this->timedDeliveryCode = Waybill::$BUSINESS_EXPRESS_CODE;
|
|
|
|
|
$address = [
|
|
|
|
|
'辽宁省' => [],
|
|
|
|
|
'吉林省' => [],
|
|
|
|
|
'黑龙江省' => [],
|
|
|
|
|
'甘肃省' => [],
|
|
|
|
|
'海南省' => [],
|
|
|
|
|
'宁夏回族自治区' => [
|
|
|
|
|
'银川市', '石嘴山市', '吴忠市', '固原市'
|
|
|
|
|
],
|
|
|
|
|
'青海省' => [
|
|
|
|
|
'西宁市', '海东市', '海北藏族自治州', '黄南藏族自治州', '海南藏族自治州', '玉树藏族自治州'
|
|
|
|
|
],
|
|
|
|
|
];
|
2023-08-25 18:38:07 +08:00
|
|
|
if (isset($address[$orderItem['recipient_province']])) {
|
|
|
|
|
if (empty($address[$orderItem['recipient_province']])) {
|
2023-08-18 16:54:04 +08:00
|
|
|
$this->timedDeliveryCode = Waybill::$AIR_FREIGHT_CODE;
|
|
|
|
|
}
|
2023-08-25 18:38:07 +08:00
|
|
|
if ($address[$orderItem['recipient_province']] && in_array($orderItem['recipient_city'], $address[$orderItem['recipient_province']], true)) {
|
2023-08-18 16:54:04 +08:00
|
|
|
$this->timedDeliveryCode = Waybill::$AIR_FREIGHT_CODE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-25 18:38:07 +08:00
|
|
|
private function prepareRequest($order, $shopShip)
|
2023-07-27 21:28:00 +08:00
|
|
|
{
|
2023-08-25 18:38:07 +08:00
|
|
|
$this->getTimedDelivery($order);
|
2023-07-27 21:28:00 +08:00
|
|
|
|
|
|
|
|
$this->setObjectId();
|
|
|
|
|
|
|
|
|
|
$items = [];
|
|
|
|
|
foreach ($order['items'] as $item) {
|
|
|
|
|
if ($item['should_print']) {
|
2023-08-18 16:54:04 +08:00
|
|
|
// 使用规格编码后删除,此处暂时使用空运名字判断兼容
|
|
|
|
|
if (false !== strpos($item['name'], '空运')) {
|
|
|
|
|
$this->timedDeliveryCode = Waybill::$AIR_FREIGHT_CODE;
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-27 21:28:00 +08:00
|
|
|
$items[] = [
|
|
|
|
|
'name' => $item['name'],
|
|
|
|
|
'count' => $item['count'],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-26 11:07:58 +08:00
|
|
|
$senderConfig = [];
|
|
|
|
|
foreach ($shopShip->senders as $sender) {
|
|
|
|
|
if ($sender['timed_delivery_code'] === $this->timedDeliveryCode) {
|
|
|
|
|
$senderConfig = $sender;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (empty($senderConfig)) {
|
|
|
|
|
abort(404, '发货人信息未匹配');
|
|
|
|
|
}
|
|
|
|
|
$sender = [
|
|
|
|
|
'address' => [
|
|
|
|
|
'city' => $senderConfig['city'],
|
|
|
|
|
'country' => $senderConfig['country'],
|
|
|
|
|
'detail' => $senderConfig['detail'],
|
|
|
|
|
'district' => $senderConfig['district'],
|
|
|
|
|
'province' => $senderConfig['province'],
|
|
|
|
|
],
|
|
|
|
|
'name' => $senderConfig['name'],
|
|
|
|
|
'mobile' => $senderConfig['mobile'],
|
|
|
|
|
];
|
|
|
|
|
|
2023-07-27 21:28:00 +08:00
|
|
|
$orderInfo = [
|
2023-08-18 16:54:04 +08:00
|
|
|
'logistics_services' => [
|
|
|
|
|
'TIMED-DELIVERY' => [
|
|
|
|
|
'value' => $this->timedDeliveryCode
|
|
|
|
|
],
|
|
|
|
|
],
|
2023-07-27 21:28:00 +08:00
|
|
|
'object_id' => $this->objectId,
|
|
|
|
|
'order_info' => [
|
|
|
|
|
'order_channels_type' => 'PDD',
|
|
|
|
|
'trade_order_list' => [$order['order_sn']],
|
|
|
|
|
],
|
|
|
|
|
'package_info' => [
|
|
|
|
|
'items' => $items,
|
|
|
|
|
],
|
|
|
|
|
'recipient' => [
|
|
|
|
|
'address' => [
|
|
|
|
|
'city' => $order['recipient_city'],
|
|
|
|
|
'detail' => $order['recipient_detail'],
|
|
|
|
|
'district' => $order['recipient_district'],
|
|
|
|
|
'province' => $order['recipient_province'],
|
|
|
|
|
],
|
|
|
|
|
'name' => $order['recipient_name'],
|
|
|
|
|
'mobile' => $order['recipient_mobile'],
|
|
|
|
|
],
|
2023-08-17 14:01:32 +08:00
|
|
|
'template_url' => $this->sfOne,
|
2023-08-25 18:38:07 +08:00
|
|
|
'user_id' => $shopShip->owner_id,
|
2023-07-27 21:28:00 +08:00
|
|
|
];
|
|
|
|
|
|
|
|
|
|
return [$sender, $orderInfo, $senderConfig['wp_code']];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function setObjectId()
|
|
|
|
|
{
|
|
|
|
|
$this->objectId = date('YmdHis') . str_pad(mt_rand(1, 9999999), 7, '0', STR_PAD_LEFT);
|
|
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function setOrders($orders)
|
|
|
|
|
{
|
|
|
|
|
$orders = $orders->toArray();
|
|
|
|
|
// 取出所有组合商品编码
|
|
|
|
|
$combinationExternalIds = [];
|
|
|
|
|
foreach ($orders as $order) {
|
|
|
|
|
foreach ($order['items'] as $item) {
|
|
|
|
|
if (false !== strpos($item['external_sku_id'], 'Z')) {
|
|
|
|
|
$combinationExternalIds[] = $item['external_sku_id'];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 获取组合商品详情
|
|
|
|
|
$combinations = [];
|
|
|
|
|
if ($combinationExternalIds) {
|
|
|
|
|
$goodsSkus = GoodsSku::query()
|
|
|
|
|
->select(['id', 'external_sku_id'])
|
|
|
|
|
->with([
|
|
|
|
|
'combinationGoods:id,goods_sku_id,item_id,item_num',
|
|
|
|
|
'combinationGoods.goodsSkuItem:id,external_sku_id',
|
|
|
|
|
])
|
|
|
|
|
->whereIn('external_sku_id', $combinationExternalIds)
|
2023-07-28 15:35:47 +08:00
|
|
|
->get()
|
|
|
|
|
->toArray();
|
2023-07-27 21:28:00 +08:00
|
|
|
foreach ($goodsSkus as $goodsSku) {
|
|
|
|
|
foreach ($goodsSku['combination_goods'] as $item) {
|
|
|
|
|
$combinations[$goodsSku['external_sku_id']][] = [
|
|
|
|
|
'count' => $item['item_num'],
|
|
|
|
|
'external_sku_id' => $item['goods_sku_item']['external_sku_id'],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 订单拆分组合
|
|
|
|
|
foreach ($orders as $order) {
|
|
|
|
|
$info = [
|
2023-07-29 17:57:36 +08:00
|
|
|
'id' => $order['id'],
|
2023-07-27 21:28:00 +08:00
|
|
|
'order_sn' => $order['order_sn'],
|
|
|
|
|
'recipient_province' => $order['receiver_address_province'],
|
|
|
|
|
'recipient_city' => $order['receiver_address_city'],
|
|
|
|
|
'recipient_district' => $order['receiver_address_district'],
|
|
|
|
|
'recipient_detail' => $order['receiver_address_detail'],
|
|
|
|
|
'recipient_name' => $order['receiver_name'],
|
|
|
|
|
'recipient_mobile' => $order['receiver_mobile'],
|
2023-08-15 16:33:36 +08:00
|
|
|
'participate_no' => $order['is_supplier'] ? $order['participate_no'] : $order['supply_participate_no'],
|
|
|
|
|
'note' => $order['business_note'] ? $order['business_note'] . ',' . $order['buyer_memo'] : $order['buyer_memo'],
|
2023-07-27 21:28:00 +08:00
|
|
|
'items' => []
|
|
|
|
|
];
|
|
|
|
|
foreach ($order['items'] as $item) {
|
|
|
|
|
$count = $item['goods_number'] - $item['already_cancel_number'];
|
|
|
|
|
if (isset($combinations[$item['external_sku_id']])) {
|
|
|
|
|
$info['items'][] = [
|
|
|
|
|
'is_single' => false,
|
|
|
|
|
'should_print' => true,
|
|
|
|
|
'name' => $item['goods_name'],
|
|
|
|
|
'count' => $count,
|
|
|
|
|
'external_sku_id' => $item['external_sku_id'],
|
|
|
|
|
];
|
|
|
|
|
foreach ($combinations[$item['external_sku_id']] as $combinationItem) {
|
|
|
|
|
$info['items'][] = [
|
|
|
|
|
'is_single' => true,
|
|
|
|
|
'should_print' => false,
|
|
|
|
|
'count' => $count * $combinationItem['count'],
|
|
|
|
|
'external_sku_id' => $combinationItem['external_sku_id'],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
$info['items'][] = [
|
|
|
|
|
'is_single' => true,
|
|
|
|
|
'should_print' => true,
|
|
|
|
|
'name' => $item['goods_name'],
|
|
|
|
|
'count' => $count,
|
|
|
|
|
'external_sku_id' => $item['external_sku_id'],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
$this->orders[$order['shop_id']][] = $info;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-25 18:38:07 +08:00
|
|
|
private function getShopShip($shopId)
|
2023-07-27 21:28:00 +08:00
|
|
|
{
|
|
|
|
|
return ShopShip::query()
|
|
|
|
|
->select(['id', 'shop_id', 'access_token', 'owner_id'])
|
|
|
|
|
->where('shop_id', $shopId)
|
|
|
|
|
->with([
|
|
|
|
|
'senders' => function ($query) {
|
2023-08-26 11:07:58 +08:00
|
|
|
$query->where('status', 1)->orderBy('sort');
|
2023-07-27 21:28:00 +08:00
|
|
|
}
|
|
|
|
|
])
|
2023-07-28 15:35:47 +08:00
|
|
|
->first();
|
2023-07-27 21:28:00 +08:00
|
|
|
}
|
|
|
|
|
}
|