Files

279 lines
8.8 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace app\common\library\app\physical\express\provider;
/**
* 阿里云物流查询驱动
*
* 服务文档:https://market.aliyun.com/detail/cmapi00071922
*
* 接口地址:https://swexquery.market.alicloudapi.com/query/expressquery
* 请求方式:POST
* 认证方式:APPCODE
*
* 配置信息:
* - AppKey203944259
* - AppSecretR8rx9QLNZlRKxHtvgjBlocFI8f0hq12J
* - AppCoded6beec8b9be945bfa3c07b9c712f6bce
*/
class Aliyun extends Base
{
protected $config = [];
public function __construct($config = [])
{
parent::__construct();
$this->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('阿里云物流查询不支持电子面单功能');
}
}