server = new KdniaoServer(); } public $status = [ '0' => 'noinfo', '1' => 'collect', '2' => 'transport', '201' => 'transport', '202' => 'delivery', '211' => 'delivery', '3' => 'signfor', '301' => 'signfor', '302' => 'signfor', '311' => 'signfor', '4' => 'difficulty', '401' => 'invalid', '402' => 'timeout', '403' => 'timeout', '404' => 'refuse', '412' => 'timeout', ]; public function search($data, $orderExpress = 0) { $requestData = $this->formatRequest($data); $result = $this->server->search($requestData); $traces = $result['Traces'] ?? []; $status = $result['State']; $formatResult = $this->formatResult([ 'status' => $status, 'traces' => $traces ]); if ($orderExpress) { $this->updateExpress($formatResult, $orderExpress); } return $formatResult; } public function subscribe($data) { $requestData = $this->formatRequest($data); $result = $this->server->subscribe($requestData); return $result; } public function cancel($data) { $config = $this->getConfig(); $this->server->cancel([ 'ShipperCode' => $data['express_code'], 'OrderCode' => $data['order_code'], 'ExpNo' => $data['express_no'], "CustomerName" => $config['customer_name'], "CustomerPwd" => $config['customer_pwd'] ]); } public function push(array $data) { $success = true; $reason = ''; try { $data = json_decode(html_entity_decode($data['RequestData']), true); $expressData = $data['Data']; foreach ($expressData as $key => $express) { $orderExpress = OrderExpress::where('express_no', $express['LogisticCode'])->where('express_code', $express['ShipperCode'])->find(); if (!$orderExpress) { Log::error('order-express-notfound:' . json_encode($express)); continue; } if (!$express['Success']) { if (isset($express['Reason']) && (strpos($express['Reason'], '三天无轨迹') !== false || strpos($express['Reason'], '七天内无轨迹变化') !== false)) { $this->subscribe([ 'express_code' => $express['ShipperCode'], 'express_no' => $express['LogisticCode'] ]); } Log::error('order-express-resubscribe:' . json_encode($express)); continue; } $traces = $express['Traces'] ?? []; $status = $express['State']; $formatResult = $this->formatResult([ 'status' => $status, 'traces' => $traces ]); $this->updateExpress($formatResult, $orderExpress); } } catch (HttpResponseException $e) { $data = $e->getResponse()->getData(); $reason = $data ? ($data['msg'] ?? '') : $e->getMessage(); } catch (\Exception $e) { $success = false; $reason = $e->getMessage(); } return $this->server->pushResult($success, $reason); } public function eOrder($data, $items) { $config = $this->getConfig(); if ($config['type'] !== 'vip') { throw new \Exception('仅快递鸟标准版接口支持电子面单功能!'); } $consignee = $data['consignee']; $order = $data['order']; $sender = $data['sender'] ?? $config['sender'] ?? []; if (empty($sender)) { throw new \Exception('请配置默认发货人信息'); } $requestData = [ "CustomerName" => $config['customer_name'], "CustomerPwd" => $config['customer_pwd'], "MonthCode" => $config['month_code'] ?? '', "SendSite" => $config['send_site'] ?? '', "SendStaff" => $config['send_staff'] ?? '', "ShipperCode" => $config['express']['code'] ?? '', "PayType" => $config['pay_type'] ?? 1, "ExpType" => $config['exp_type'] ?? 1, "IsReturnPrintTemplate" => 0, "TemplateSize" => '130', "Volume" => 0, "OrderCode" => $order['order_sn'] . '_' . time(), "Remark" => $order['remark'] ?? '小心轻放' ]; $requestData['Sender'] = [ 'Name' => $sender['name'], 'Mobile' => $sender['mobile'], 'ProvinceName' => $sender['province_name'], 'CityName' => $sender['city_name'], 'ExpAreaName' => $sender['district_name'], 'Address' => $sender['address'] ]; $requestData['Receiver'] = [ "Name" => $consignee['consignee'], "Mobile" => $consignee['mobile'], "ProvinceName" => $consignee['province_name'], "CityName" => $consignee['city_name'], "ExpAreaName" => $consignee['district_name'], "Address" => $consignee['address'] ]; $totalCount = 0; $totalWeight = 0; foreach ($items as $k => $item) { $goodsName = $item['goods_title'] . ($item['goods_sku_text'] ? '-' . $item['goods_sku_text'] : ''); $requestData['Commodity'][] = [ "GoodsName" => $goodsName, "Goodsquantity" => $item['goods_num'], "GoodsWeight" => $item['goods_num'] * ($item['goods_weight'] ?? 0) ]; $totalCount += $item['goods_num']; $totalWeight += $item['goods_num'] * ($item['goods_weight'] ?? 0); } $requestData['Quantity'] = $totalCount; $requestData['Weight'] = $totalWeight; $result = $this->server->eOrder($requestData); if ($result['Success'] === true && $result['ResultCode'] === "100") { return [ 'code' => $config['express']['code'], 'name' => $config['express']['name'], 'no' => $result['Order']['LogisticCode'], 'ext' => $result, 'driver' => 'kdniao' ]; } return false; } protected function formatRequest($data) { $requestData = [ 'express_code' => $data['express_code'] ?? '', 'express_no' => $data['express_no'], 'mobile' => (isset($data['mobile']) && $data['mobile']) ? substr($data['mobile'], 7) : '' ]; return $requestData; } protected function formatResult($data) { $status = $this->status[$data['status']] ?? 'noinfo'; $traces = []; if (is_array($data['traces'])) { foreach ($data['traces'] as $trace) { $action = $trace['Action'] ?? ''; if ($action !== '') { $currentStatus = $this->status[$action] ?? 'noinfo'; } $traces[] = [ 'content' => $trace['AcceptStation'], 'change_date' => date('Y-m-d H:i:s', strtotime(substr($trace['AcceptTime'], 0, 19))), 'status' => $currentStatus ?? 'noinfo' ]; } } return compact('status', 'traces'); } protected function getConfig() { return [ 'type' => 'free', 'ebusiness_id' => '', 'app_key' => '', 'customer_name' => '', 'customer_pwd' => '', 'month_code' => '', 'send_site' => '', 'send_staff' => '', 'express' => [], 'pay_type' => 1, 'exp_type' => 1, 'sender' => [] ]; } }