false, 'trackList' => [], 'expressStatus' => '', 'expressCompanyName' => '', 'expressCompanyCode' => '', ]; } } protected static function fromAliyun(array $providerResult) { $root = $providerResult['raw'] ?? ($providerResult['data'] ?? []); // kzexpress:logisticsTraceDetailList / logisticsTraceDetails $dataBlock = $root['data'] ?? $root; $traceDetails = self::pickKzexpressTraceList($dataBlock); if (!empty($traceDetails)) { return self::fromKzexpressTrace($providerResult, $dataBlock, $traceDetails); } // 文档格式:data.logisticsEvents if (!empty($root['data']['logisticsEvents'])) { return self::fromExprLogisticsEvents($providerResult, $root['data']); } // wuliu.market alicloudapi.com/kdi if (!empty($root['result']['list'])) { return self::fromWuliuResult($providerResult, $root['result'], $root); } // expQuery 等:data[] 含 context/time if (!empty($root['data']) && is_array($root['data']) && isset($root['data'][0]['context'])) { return self::fromExpQueryData($providerResult, $root); } $data = $root['data'] ?? $root; if (!empty($data['logisticsEvents'])) { return self::fromExprLogisticsEvents($providerResult, $data); } return [ 'success' => !empty($providerResult['success']), 'trackList' => [], 'expressStatus' => is_string($data['status'] ?? null) ? $data['status'] : '', 'expressCompanyName' => $data['expressCompanyName'] ?? ($root['expTextName'] ?? ''), 'expressCompanyCode' => $data['expressCompany'] ?? ($root['expSpellName'] ?? ''), 'lastDescription' => $root['msg'] ?? '', 'lastTime' => '', ]; } protected static function pickKzexpressTraceList(array $data) { foreach (['logisticsTraceDetailList', 'logisticsTraceDetails', 'logisticsTraceDetail'] as $key) { if (!empty($data[$key]) && is_array($data[$key])) { return $data[$key]; } } return []; } protected static function fromKzexpressTrace(array $providerResult, array $data, array $traceDetails) { $trackList = []; foreach ($traceDetails as $item) { $time = $item['timeDesc'] ?? ''; if ($time === '' && !empty($item['time']) && is_numeric($item['time'])) { $ts = (string) $item['time']; if (strlen($ts) >= 13) { $time = date('Y-m-d H:i:s', (int) floor($item['time'] / 1000)); } elseif (strlen($ts) === 10) { $time = date('Y-m-d H:i:s', (int) $item['time']); } } $desc = trim((string) ($item['desc'] ?? ($item['description'] ?? ''))); if ($desc === '') { $area = trim((string) ($item['areaName'] ?? ($item['location'] ?? ''))); $statusText = trim((string) ($item['subLogisticsStatus'] ?? ($item['logisticsStatus'] ?? ''))); $desc = trim($area . ($statusText !== '' ? ' ' . $statusText : '')); } $trackList[] = [ 'AcceptTime' => $time, 'AcceptStation' => $desc, 'Location' => $item['areaName'] ?? ($item['city'] ?? ''), 'Action' => self::mapAliyunStateToAction($item['logisticsStatus'] ?? ($item['subLogisticsStatus'] ?? '')), ]; } usort($trackList, function ($a, $b) { return strcmp($b['AcceptTime'], $a['AcceptTime']); }); return [ 'success' => !empty($providerResult['success']), 'trackList' => $trackList, 'expressStatus' => $data['logisticsStatusDesc'] ?? ($data['logisticsStatus'] ?? ''), 'expressCompanyName' => $data['logisticsCompanyName'] ?? ($data['cpName'] ?? ''), 'expressCompanyCode' => $data['cpCode'] ?? '', 'expressNo' => $data['mailNo'] ?? ($data['expressNo'] ?? ''), 'lastDescription' => $data['theLastMessage'] ?? (!empty($trackList) ? ($trackList[0]['AcceptStation'] ?? '') : ''), 'lastTime' => $data['theLastTime'] ?? (!empty($trackList) ? ($trackList[0]['AcceptTime'] ?? '') : ''), ]; } protected static function fromExprLogisticsEvents(array $providerResult, array $data) { $trackList = []; foreach ($data['logisticsEvents'] ?? [] as $event) { $trackList[] = [ 'AcceptTime' => $event['date'] ?? '', 'AcceptStation' => $event['description'] ?? '', 'Location' => $event['location'] ?? ($event['city'] ?? ''), 'Action' => self::mapAliyunStateToAction($event['state'] ?? ''), ]; } usort($trackList, function ($a, $b) { return strcmp($b['AcceptTime'], $a['AcceptTime']); }); return [ 'success' => !empty($providerResult['success']), 'trackList' => $trackList, 'expressStatus' => $data['status'] ?? '', 'expressCompanyName' => $data['expressCompanyName'] ?? '', 'expressCompanyCode' => $data['expressCompany'] ?? '', 'lastDescription' => $data['lastDescription'] ?? '', 'lastTime' => $data['lastTime'] ?? '', ]; } protected static function fromWuliuResult(array $providerResult, array $result, array $root) { $trackList = []; foreach ($result['list'] ?? [] as $item) { $trackList[] = [ 'AcceptTime' => $item['time'] ?? ($item['ftime'] ?? ''), 'AcceptStation' => $item['status'] ?? ($item['context'] ?? ''), 'Location' => $item['location'] ?? '', 'Action' => self::mapAliyunStateToAction($item['status'] ?? ''), ]; } return [ 'success' => !empty($providerResult['success']), 'trackList' => $trackList, 'expressStatus' => $result['deliverystatus'] ?? ($root['msg'] ?? ''), 'expressCompanyName' => $result['expName'] ?? ($result['type'] ?? ''), 'expressCompanyCode' => $result['type'] ?? '', 'lastDescription' => !empty($trackList) ? ($trackList[0]['AcceptStation'] ?? '') : '', 'lastTime' => !empty($trackList) ? ($trackList[0]['AcceptTime'] ?? '') : '', ]; } protected static function fromExpQueryData(array $providerResult, array $root) { $trackList = []; foreach ($root['data'] as $item) { $trackList[] = [ 'AcceptTime' => $item['time'] ?? '', 'AcceptStation' => $item['context'] ?? '', 'Location' => $item['location'] ?? '', 'Action' => self::mapAliyunStateToAction($item['status'] ?? ''), ]; } return [ 'success' => !empty($providerResult['success']), 'trackList' => $trackList, 'expressStatus' => $root['updateStr'] ?? ($root['msg'] ?? ''), 'expressCompanyName' => $root['expTextName'] ?? '', 'expressCompanyCode' => $root['expSpellName'] ?? '', 'lastDescription' => !empty($trackList) ? ($trackList[0]['AcceptStation'] ?? '') : '', 'lastTime' => !empty($trackList) ? ($trackList[0]['AcceptTime'] ?? '') : '', ]; } protected static function fromKdniao(array $providerResult) { $data = $providerResult['data'] ?? []; $traces = $data['Traces'] ?? []; $trackList = []; foreach ($traces as $trace) { $trackList[] = [ 'AcceptTime' => $trace['AcceptTime'] ?? '', 'AcceptStation' => $trace['AcceptStation'] ?? '', 'Location' => $trace['Location'] ?? '', 'Action' => $trace['Action'] ?? ($data['State'] ?? 0), ]; } $statusMap = [ '0' => '暂无轨迹', '1' => '已揽收', '2' => '运输中', '3' => '已签收', '4' => '问题件', ]; $state = (string) ($data['State'] ?? ''); return [ 'success' => !empty($providerResult['success']), 'trackList' => $trackList, 'expressStatus' => $statusMap[$state] ?? '', 'expressCompanyName' => $data['ShipperCode'] ?? '', 'expressCompanyCode' => $data['ShipperCode'] ?? '', 'lastDescription' => !empty($trackList) ? ($trackList[0]['AcceptStation'] ?? '') : '', 'lastTime' => !empty($trackList) ? ($trackList[0]['AcceptTime'] ?? '') : '', ]; } public static function mapAliyunStateToAction($state) { $state = trim((string) $state); $map = [ '已揽收' => 1, '收件扫描' => 1, 'ACCEPT' => 1, '运送中' => 2, '运输中' => 2, '转运中' => 2, '入中转' => 2, '出中转' => 2, 'TRANSPORT'=> 2, '派送中' => 202, '待派送' => 202, 'DELIVERING' => 202, '已签收' => 3, 'SIGN' => 3, 'STA_SIGN' => 3, 'AGENT_SIGN' => 304, '第三方代收' => 304, 'AGENT_SIGN' => 304, '问题件' => 4, '拒收' => 4, '退回件' => 4, 'FAILED' => 4, ]; if (isset($map[$state])) { return $map[$state]; } foreach ($map as $keyword => $action) { if ($state !== '' && mb_strpos($state, $keyword) !== false) { return $action; } } return 2; } /** * 修正派件图标(与原 OrderExpress::detail 逻辑一致) */ public static function fixDeliveringIcons(array $trackList) { if (empty($trackList)) { return $trackList; } foreach ($trackList as $k => &$v) { if (($v['Action'] ?? null) == 202) { if ($k >= 2) { $trackList[$k - 2]['Action'] = 3; $trackList[$k - 1]['Action'] = 4; } } } unset($v); return $trackList; } }