config = $config; } /** * 查询物流信息 * * @param array $data * @param mixed $orderExpress * @return array|null */ public function search(array $data, $orderExpress = null) { $host = "https://swexquery.market.alicloudapi.com"; $path = "/query/expressquery"; $method = "POST"; // 优先使用 AppCode,如果未配置则使用 AppKey 和 AppSecret 生成签名 $appcode = $this->config['appcode'] ?? ''; if (empty($appcode)) { $appkey = $this->config['appkey'] ?? ''; $appsecret = $this->config['appsecret'] ?? ''; if (empty($appkey) || empty($appsecret)) { throw new \Exception('阿里云AppCode或AppKey/AppSecret未配置'); } // 使用 AppKey 和 AppSecret 生成 AppCode(参考阿里云文档) $appcode = base64_encode($appkey . ':' . $appsecret); } $headers = []; $headers[] = "Authorization:APPCODE " . $appcode; $headers[] = "Content-Type:application/x-www-form-urlencoded; charset=UTF-8"; // 构建请求参数 $expressNumber = $data['express_no'] ?? ''; $expressType = $data['express_code'] ?? ''; $phoneNumber = $data['mobile'] ?? ''; $bodys = "express_number=" . urlencode($expressNumber); // if (!empty($expressType)) { // $bodys .= "&express_type=" . urlencode($expressType); // } if (!empty($phoneNumber)) { $bodys .= "&phone_number=" . urlencode($phoneNumber); } $url = $host . $path; $curl = curl_init(); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); curl_setopt($curl, CURLOPT_FAILONERROR, false); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_HEADER, false); if (1 == strpos("$" . $host, "https://")) { curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); } curl_setopt($curl, CURLOPT_POSTFIELDS, $bodys); $response = curl_exec($curl); $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); curl_close($curl); if ($httpCode != 200 || empty($response)) { throw new \Exception('阿里云物流查询接口请求失败'); } $result = json_decode($response, true); if (empty($result)) { throw new \Exception('阿里云物流查询接口返回数据解析失败'); } // 解析阿里云返回的数据 $expressData = $this->parseResponse($result); if ($orderExpress) { $this->updateExpress($expressData, $orderExpress); } return $expressData; } /** * 解析阿里云返回的数据 * * @param array $result * @return array */ protected function parseResponse($result) { // 阿里云返回格式参考 // 成功格式: // { // "charge": 1, // "result": { // "info": [ // { // "cpCode": "STO", // "theLastTime": "2025-09-08 18:55:18", // "mailNo": "772****722", // "theLastMessage": "已签收,签收人凭取货码签收", // "cpMobile": "95543", // "logisticsCompanyName": "申通快递", // "cpUrl": "http://www.sto.cn", // "takeTime": "1天18小时7分", // "courier": "**路北**14-8店", // "courierPhone": "135**3135", // "logisticsStatusDesc": "已签收", // "logisticsTraceDetailList": [ // { // "areaCode": "CN110100000000", // "areaName": "北京,北京市", // "subLogisticsStatus": "ACCEPT", // "time": "1773037503000", // "logisticsStatus": "ACCEPT", // "desc": "顺丰速运 已收取快件,您的期待,我们定竭诚守护,不负所托。" // } // ], // "logisticsStatus": "SIGN" // } // ] // }, // "result_code": "0000", // "result_msg": "调用成功", // "request_id": "TID762ff34c093040b69e4c04b5f01a560a" // } // // 失败格式: // { // "charge": 2, // "result_code": "2102", // "result_msg": "请求参数错误", // "request_id": "TID7b21ec5e862d445fac39b0af4c36008d" // } // 检查错误格式 if (isset($result['result_code'])) { if ($result['result_code'] != '0000') { $msg = $result['result_msg'] ?? '查询失败'; throw new \Exception('阿里云物流查询:' . $msg); } } // 获取物流信息 $infoList = $result['result']['info'] ?? []; if (empty($infoList)) { throw new \Exception('阿里云物流查询:未找到物流信息'); } $info = $infoList[0]; // 转换物流状态 $status = $this->convertStatus($info['logisticsStatus'] ?? ''); // 转换物流轨迹 $traces = []; $traceList = $info['logisticsTraceDetailList'] ?? []; if (is_array($traceList)) { foreach ($traceList as $trace) { $timestamp = $trace['time'] ?? ''; $changeDate = ''; if (!empty($timestamp)) { // 时间戳转换为日期格式 if (strlen($timestamp) == 13) { $changeDate = date('Y-m-d H:i:s', $timestamp / 1000); } else { $changeDate = date('Y-m-d H:i:s', $timestamp); } } $traces[] = [ 'content' => $trace['desc'] ?? $trace['content'] ?? '', 'change_date' => $changeDate ?: date('Y-m-d H:i:s'), 'status' => $status ]; } } return [ 'status' => $status, 'traces' => $traces ]; } /** * 转换物流状态 * * @param string $status * @return string */ protected function convertStatus($status) { // 阿里云状态映射到系统状态 $statusMap = [ 'NOINFO' => 'noinfo', // 无信息 'ACCEPT' => 'collect', // 已揽件 'TRANSPORT' => 'transport', // 运输中 'DELIVERY' => 'delivery', // 派送中 'SIGN' => 'signfor', // 已签收 'REFUSE' => 'refuse', // 拒收 'DIFFICULTY' => 'difficulty', // 问题件 'INVALID' => 'invalid', // 无效件 'TIMEOUT' => 'timeout', // 超时 'FAIL' => 'fail', // 签收失败 'BACK' => 'back' // 退回 ]; return $statusMap[$status] ?? 'noinfo'; } /** * 订阅物流信息推送 * * @param array $data * @return void */ public function subscribe(array $data) { throw new \Exception('阿里云物流查询不支持订阅功能'); } /** * 接收物流推送 * * @param array $data * @return void */ public function push(array $data) { throw new \Exception('阿里云物流查询不支持推送功能'); } /** * 电子面单 * * @param array $data * @param array $items * @return void */ public function eOrder(array $data, $items) { throw new \Exception('阿里云物流查询不支持电子面单功能'); } }