| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334 |
- <?php
- namespace App\Services;
- use App\OrderPackage;
- use App\Traits\ServiceAppAop;
- use Carbon\Carbon;
- use Illuminate\Support\Facades\Http;
- class LogisticYDService
- {
- use ServiceAppAop;
- private $app_key;
- private $app_secret;
- private $url;
- /**
- * 批量订阅接口
- * @param $logistic_numbers array
- * @return mixed
- */
- public function registerApi(array $logistic_numbers)
- {
- $this->app_key = config('api_logistic.YD.prod.app-key', '999999');
- $this->app_secret = config('api_logistic.YD.prod.app-secret', '04d4ad40eeec11e9bad2d962f53dda9d');
- $this->url = config('api_logistic.YD.prod.register.url');
- $sender = [
- "address" => "上海市松江区泗泾镇泗砖公路351号",
- "city" => "上海市",
- "county" => "松江区",
- "name" => "施尧",
- "phone" => '13761413262',
- "province" => "上海市"
- ];
- $body = [
- "orders" => [],
- ];
- $order_packages = OrderPackage::query()
- ->with('order')
- ->whereIn('logistic_number', $logistic_numbers)->get();
- foreach ($order_packages as $order_package) {
- $order = $order_package->order;
- $body['orders'][] = [
- 'orderid' => $order->client_code,
- "mailno" => $order_package->logistic_number,
- "receiver" => [
- "address" => $order->address,
- "city" => $order->city,
- "county" => $order->district,
- "name" => $order->consignee_name,
- "phone" => $order->consignee_phone,
- "province" => $order->province
- ],
- "sender" => $sender
- ];
- }
- $json_body = json_encode($body, JSON_UNESCAPED_UNICODE);
- $sign = md5($json_body . '_' . $this->app_secret);
- $headers = [
- 'app-key' => $this->app_key,
- 'sign' => $sign,
- 'req-time' => now()->timestamp,
- "Content-Type" => "application/json"
- ];
- $response = Http::withHeaders($headers)->withBody($json_body, 'application/json')->post($this->url);
- return json_decode($response);
- }
- public function query($logistic_number)
- {
- $this->app_key = config('api_logistic.YD.prod.app-key', '999999');
- $this->app_secret = config('api_logistic.YD.prod.app-secret', '04d4ad40eeec11e9bad2d962f53dda9d');
- $this->url = config('api_logistic.YD.prod.search.url');
- $body = [
- "mailno" => $logistic_number
- ];
- $sign = md5(json_encode($body, JSON_UNESCAPED_UNICODE) . '_' . $this->app_secret);
- $headers = [
- 'app-key' => $this->app_key,
- 'sign' => $sign,
- 'req-time' => now()->timestamp,
- "Content-Type" => "application/json"
- ];
- $response = Http::withHeaders($headers)->withBody(json_encode($body, JSON_UNESCAPED_UNICODE), 'application/json')->post($this->url);
- return json_decode($response->body());
- }
- public function format($nativeResponse)
- {
- $result = [];
- if ($nativeResponse->code != '0000') {
- return [];
- } else {
- $nativeData = $nativeResponse->data;
- $result['logistic_number'] = $nativeData->mailno;
- $nativeRoutes = $nativeData->steps;
- if (!empty($nativeRoutes)) {
- $lastNativeRoute = $nativeRoutes[count($nativeRoutes) - 1];
- $result['status'] = $this->getStatus($nativeData);
- if ($result['status'] == '已收件') {
- $result['received_at'] = $lastNativeRoute->time;
- }
- $result['transfer_status'] = $this->getTransferStatus($nativeRoutes);
- $exceptionData = $this->setExceptionType($result, $lastNativeRoute ? $lastNativeRoute->time : null);
- $result['exception_type'] = $exceptionData['exception_type'];
- $result['exception'] = $exceptionData['exception'];
- } else {
- $result['status'] = null;
- $result['transfer_status'] = [];
- }
- if (!array_key_exists('status', $result)) {
- $result['status'] = null;
- $result['transfer_status'] = [];
- }
- //如果没有发现额外的异常,且查询到物流轨迹,将异常置为无
- if (!array_key_exists('exception', $result)
- && !array_key_exists('exception_type', $result)
- && array_key_exists('transfer_status', $result)
- ) {
- $result['exception_type'] = '无';
- $result['exception'] = '否';
- }
- return $result;
- }
- }
- /**
- * @param array $data
- * @param $lastRouteDate
- * @return array
- */
- private function setExceptionType(array $data, $lastRouteDate): array
- {
- $logistic_number = $data['logistic_number'];
- /** @var OrderPackage $orderPackage */
- $orderPackage = OrderPackage::query()->with('order')->where('logistic_number', $logistic_number)->first();
- $delivered_duration = now()->diffInHours(Carbon::parse($orderPackage['sent_at']));
- $last_routed_duration = now()->diffInHours(Carbon::parse($lastRouteDate));
- $VALID_HOURS = 4;
- $SHORT_RESPONSE_HOURS = (function ($province) {
- switch ($province) {
- case '浙江省':
- case '江苏省':
- case '上海':
- case '安徽省':
- return 24;
- case '北京':
- case '天津':
- case '江西省':
- case '湖北省':
- case '湖南省':
- case '广东省':
- case '福建省':
- case '山东省':
- case '河北省':
- case '河南省':
- case '山西省':
- case '四川省':
- case '陕西省':
- case '重庆':
- case '广西壮族自治区':
- case '贵州省':
- case '云南省':
- case '海南省':
- case '吉林省':
- case '黑龙江省':
- case '辽宁省':
- return 72;
- case '青海省':
- case '宁夏回族自治区':
- case '甘肃省':
- case '内蒙古自治区':
- case '新疆维吾尔自治区':
- case '西藏自治区':
- return 120;
- default:
- return 24;
- }
- })($orderPackage->order->province);
- $LONG_RESPONSE_HOURS = (function ($province) {
- switch ($province) {
- case '浙江省':
- case '江苏省':
- case '上海':
- case '安徽省':
- return 72;
- case '北京':
- case '天津':
- case '江西省':
- case '湖北省':
- case '湖南省':
- case '广东省':
- case '福建省':
- case '山东省':
- case '河北省':
- case '河南省':
- case '山西省':
- case '四川省':
- case '陕西省':
- case '重庆':
- case '广西壮族自治区':
- case '贵州省':
- case '云南省':
- case '海南省':
- case '吉林省':
- case '黑龙江省':
- case '辽宁省':
- return 120;
- case '青海省':
- case '宁夏回族自治区':
- case '甘肃省':
- case '内蒙古自治区':
- case '新疆维吾尔自治区':
- case '西藏自治区':
- return 168;
- default:
- return 72;
- }
- })($orderPackage->order->province);
- $SENDING_RESPONSE_HOURS = 48;
- $IS_ROUTED = 1; //0000 0001 有路由信息
- $IS_IN_VALID_TIME = 2; //0000 0010 大于4小时
- $IS_WEIGHED = 4; //0000 0100 称重过
- $IS_RECEIVED = 8; //0000 1000 已经收货
- $IS_SENDING = 16; //0001 0000 正在派送
- $IS_SHORT_NO_RESPONSE = 32; //0010 0000 中转异常
- $IS_LONG_NO_RESPONSE = 64; //0010 0000 疑似丢件
- $IS_SENDING_NO_RESPONSE = 128; //0010 0000 派送异常
- $conclusion = (function () use (
- $data, $delivered_duration, $last_routed_duration,
- $VALID_HOURS, $IS_ROUTED, $IS_IN_VALID_TIME, $IS_WEIGHED, $IS_RECEIVED, $IS_SENDING, $IS_SHORT_NO_RESPONSE, $IS_LONG_NO_RESPONSE, $IS_SENDING_NO_RESPONSE,
- $SHORT_RESPONSE_HOURS, $LONG_RESPONSE_HOURS, $SENDING_RESPONSE_HOURS,
- $orderPackage
- ) {
- $conclusion = 0;
- $conclusion |= !empty($data['transfer_status']) ? $IS_ROUTED : 0;
- $conclusion |= ($delivered_duration > $VALID_HOURS) ? $IS_IN_VALID_TIME : 0;
- $conclusion |= ($orderPackage->weighed_at) ? $IS_WEIGHED : 0;
- $conclusion |= ($data['status'] == '已收件') ? $IS_RECEIVED : 0;
- $conclusion |= ($data['status'] == '派送中') ? $IS_SENDING : 0;//
- $conclusion |= ($last_routed_duration > $SHORT_RESPONSE_HOURS && $last_routed_duration < $LONG_RESPONSE_HOURS) ? $IS_SHORT_NO_RESPONSE : 0;
- $conclusion |= ($last_routed_duration > $LONG_RESPONSE_HOURS) ? $IS_LONG_NO_RESPONSE : 0;
- $conclusion |= ($last_routed_duration > $SENDING_RESPONSE_HOURS && $data['status'] == '派送中') ? $IS_SENDING_NO_RESPONSE : 0;
- return $conclusion;
- })();
- switch ($conclusion) {
- case $IS_IN_VALID_TIME:
- $data['exception_type'] = '疑似库内丢件';
- break;
- case $IS_IN_VALID_TIME | $IS_WEIGHED:
- $data['exception_type'] = '揽件异常';
- break;
- case $IS_ROUTED | $IS_IN_VALID_TIME | $IS_SHORT_NO_RESPONSE:
- case $IS_ROUTED | $IS_IN_VALID_TIME | $IS_SHORT_NO_RESPONSE | $IS_WEIGHED:
- $data['exception_type'] = '中转异常';
- break;
- case $IS_ROUTED | $IS_IN_VALID_TIME | $IS_LONG_NO_RESPONSE:
- case $IS_ROUTED | $IS_IN_VALID_TIME | $IS_LONG_NO_RESPONSE | $IS_WEIGHED:
- $data['exception_type'] = '疑似丢件';
- break;
- default:
- break;
- }
- if ($conclusion
- == ($conclusion | $IS_ROUTED | $IS_IN_VALID_TIME | $IS_SENDING | $IS_SENDING_NO_RESPONSE)) {
- $data['exception_type'] = '派件异常';
- }
- switch ($conclusion) {
- case $IS_IN_VALID_TIME:
- case $IS_IN_VALID_TIME | $IS_WEIGHED:
- case $IS_ROUTED | $IS_SHORT_NO_RESPONSE:
- case $IS_LONG_NO_RESPONSE:
- $data['exception'] = '是';
- break;
- default:
- break;
- }
- return [
- 'exception_type' => array_key_exists('exception_type', $data) ? $data['exception_type'] : null,
- 'exception' => array_key_exists('exception', $data) ? $data['exception'] : null,
- ];
- }
- /**
- * @param $nativeData
- * @return string
- */
- private function getStatus($nativeData): string
- {
- $status = null;
- switch ($nativeData->status) {
- case 'GOT':
- $status = '已揽收';
- break;
- case 'TRANSIT':
- $status = '在途';
- break;
- case 'SIGNED':
- $status = '已收件';
- break;
- case 'RETURN':
- $status = '返回中';
- break;
- case 'SIGNFAIL':
- $status = '无';
- break;
- default:
- $status = '无';
- }
- return $status;
- }
- /**
- * @param $nativeRoutes
- * @return array
- */
- private function getTransferStatus($nativeRoutes): array
- {
- $transferStatus = [];
- foreach ($nativeRoutes as $nativeRoute) {
- $item = [];
- $item['accept_time'] = $nativeRoute->time;
- $item['accept_address'] = $nativeRoute->description;
- $item['remark'] = "";
- $transferStatus[] = $item;
- }
- return $transferStatus;
- }
- }
|