1.注册快递100账号,获取key和公司编号
注:快递100基础版不支持主流快递,如三通一达、顺丰、京东、EMS、德邦、天天、百世、邮政等主流快递的查询。企业版支持所有快递,且有100单的免费测试。
我注册的是企业版的。
注册成功后,从这里获取key和customer(公司编号)用于接口使用
可以查看接口信息,能使用那些功能,下图是企业版拥有的功能
我只是用到其中圈红的三个接口
2.接口使用简单讲解
(1)智能判断接口:输入一个正确的物流单号,可以智能的判断属于哪个快递公司的物流单号,获取相应快递公司的编码,用于实时查询接口和订阅推送接口
返回智能识别的结果可能有多个结果也可能没有结果,这边业务使用时需要判断一下
返回结果为多个时,我一般取第一个(可能性最大)
(2)实时查询接口:顾名思义,手动的去实时查询物流的最新动态
参数注意一下这几个必填的,还有查顺丰的单号时手机号必填,其他的看情况去设置参数即可
快递公司编码是智能识别出的公司编码,当然如果知道要查询的快递是哪个公司的快递,可以不使用智能识别接口
返回结果:
对快递单号状态的解释:
我当前项目中没有对快递状态进行处理,只是展示快递的信息给用户
(3)订阅推送接口:跟项目结合的更紧密一点,通过订阅某个物流单号,当订阅的单号物流状态更新后,通过设定的回调地址异步的通知项目,这样就可以不必实时的请求快递100的实时查询物流接口
有好处也有不好的地方,需要自己去设计数据库,存储和展示,后期准备把项目改成这样,当然需要结合项目的业务逻辑去实现。
参数比较多:但是只需要看必需的参数和顺丰单号特殊处理手机号就行,其他参数是选填
订阅的快递公司编码是智能识别出的公司编码,当然如果知道要查询的快递是哪个公司的快递,可以不使用智能识别接口
回调地址是你项目的回调地址,不要弄错了
返回信息中查看lastResult中的state:快递单号状态、ischeck:是否签收标记、data:物流信息数组,data里面有多个物流信息,第一个是最新的。
3.接口封装为类和回调处理
class Logistics
{
/**
* 客户授权key
* @var string
*/
protected $key = '';
/**
* 查询公司编号
* @var string
*/
protected $customer = '';
/**
* 智能判断快递公司编码
* @param $num
* @return array|mixed
*/
public function autoNumber($num)
{
if (empty($num)) return [];
//智能判断请求地址
$url = 'http://www.kuaidi100.com/autonumber/auto';
$post_data = array();
$post_data['key'] = $this->key;
$post_data['num'] = $num;
$params = $this->urlEncodeParam($post_data);
$result = $this->curlRequest($url, $params);
return $result[0] ?? [];
}
/**
* 订阅请求
* @param $num
* @return mixed
*/
public function subscribe($num)
{
//订阅请求地址
$url = 'http://poll.kuaidi100.com/poll';
$type = $this->autoNumber($num);
if (!isset($type['comCode']) || empty($type['comCode'])) return [];
//参数设置
$param = array(
'company' => $type['comCode'], //快递公司编码
'number' => $num, //快递单号
'from' => '', //出发地城市
'to' => '', //目的地城市
'key' => $this->key, //客户授权key
'parameters' => array(
'callbackurl' => 'http://www.solveset.net/api/logisticsNotify',//回调地址
'salt' => '', //加密串
'resultv2' => '1', //行政区域解析
'autoCom' => '0', //单号智能识别
'interCom' => '0', //开启国际版
'departureCountry' => '', //出发国
'departureCom' => '', //出发国快递公司编码
'destinationCountry' => '', //目的国
'destinationCom' => '', //目的国快递公司编码
'phone' => '' //手机号
)
);
//请求参数
$post_data = array();
$post_data['schema'] = 'json';
$post_data['param'] = json_encode($param);
$params = $this->urlEncodeParam($post_data);
return $this->curlRequest($url, $params);
}
/**
* 实时查询
* @param $num
* @return mixed
*/
public function nowQuery($num)
{
//实时查询请求地址
$url = 'http://poll.kuaidi100.com/poll/query.do';
$type = $this->autoNumber($num);
if (!isset($type['comCode']) || empty($type['comCode'])) return [];
//参数设置
$param = array(
'com' => $type['comCode'], //快递公司编码
'num' => $num, //快递单号
'phone' => '', //手机号
'from' => '', //出发地城市
'to' => '', //目的地城市
'resultv2' => '1' //开启行政区域解析
);
//请求参数
$post_data = array();
//查询公司编号
$post_data['customer'] = $this->customer;
$post_data['param'] = json_encode($param);
$sign = md5($post_data['param'] . $this->key . $post_data['customer']);
$post_data['sign'] = strtoupper($sign);
$params = $this->urlEncodeParam($post_data);
return $this->curlRequest($url, $params);
}
/**
* 对参数进行urlencode
* @param $data
* @return bool|string
*/
protected function urlEncodeParam($data)
{
$params = '';
foreach ($data as $k => $v) {
$params .= $k . '=' . urlencode($v) . '&';//默认UTF-8编码格式
}
$data = substr($params, 0, -1);
return $data;
}
/**
* curl请求
* @param $url
* @param $post_data
* @return mixed
*/
protected function curlRequest($url, $post_data)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
$data = str_replace("\"", '"', $result);
return json_decode($data, true);
}
}
调用:
$obj = new Logistics();
print_r($obj->nowQuery('123123'));
//print_r($obj->subscribe('123123'));
回调处理
路由:使用的是laravel框架
//物流订阅回调
Route::any('/api/logisticsNotify', 'Api\ApiTestController@logisticsNotify');
业务处理
//测试物流订阅回调
public function logisticsNotify()
{
$body = file_get_contents('php://input');
if (!empty($body)) {
//url解码
$body_str = urldecode($body);
$data_str = substr($body_str, strpos($body_str, 'param=') + 6);
if (!empty($data_str)) {
//json字符串转换为数组格式
$data = djson($data_str);
//处理逻辑
iF(!empty($data)) {
//快递单状态 0在途,1揽收,2疑难,3签收,4退签,5派件,6退回
if($data['lastResult']['state'] == 3) {
//订单状态修改为已收货
}
}
//记录日志
$filePath = createLogFile('logisticsNotify.log', 'logs/solve');
file_put_contents($filePath, '物流单号异步通知:' . var_export($data, true), FILE_APPEND);
}
}
//返回成功状态
echo json(['result' => true, 'returnCode' => 200, 'message' => '成功']);
}
日志中的记录
到目前为止,只是简单的解释了三个接口,写了一个demo,但是大概思路和流程是完善的,是对项目使用快递100的一个整理和备忘。