前言
大部分的商城都需要調用快遞的接口來記錄商城的物流信息,這里就給出一種快遞接口(快遞100)調用的方法。
正文
一、官方文檔
1. 官方文檔的地址為:
https://www.kuaidi100.com/openapi/api_subscribe.shtml
二、具體實現
1. 商城服務與快遞接口服務具體交互示意圖:
具體的實現邏輯為:
我們將訂單號發給快遞100,然后訂閱該訂單號的消息。當快遞100中有訂閱信息產生的時候,就會給指定的地址發一個消息去推送類似的消息。
貴公司將需要跟蹤的運單提交給快遞100指定的接口,快遞100接到后就對這些單號進行監控,如果監控到運單有了更新,就主動將這些物流跟蹤信息推送到貴公司指定的接口,
直到這些單的生命周期結束(一般以“已簽收”為准),一個運單快遞100一般會多次推送多條跟蹤信息,貴方將之保存到數據庫。當用戶登錄貴方網站、系統或手機APP時,
直接從貴司的數據庫讀取數據,並顯示於貴方的網站、系統或手機APP。
2. 代碼實現
(1)訂閱某個訂單信息
public static function subscribeExpress($courier_company, $courier_no) { $data = [ 'company' => $courier_company, 'number' => $courier_no, 'key' => config('express_config.poll_key'), 'parameters' => [ 'callbackurl' => env('API_HOST', 'http://panda.qujie8.com/') . 'api/alipay/express/notify', 'departureCountry' => 'CN' ] ]; $post_data = [ 'schema' => 'json', 'param' => json_encode($data), ]; Log::info('訂閱快遞100參數', [$post_data]); $o = ''; foreach ($post_data as $k => $v) { $o .= "$k=" . urlencode($v) . '&';//默認UTF-8編碼格式 } $post_data = substr($o, 0, -1); $url = env('EXPRESS_PUST_URL', 'http://poll.kuaidi100.com/poll'); $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_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); $rst = curl_exec($ch); curl_close($ch); Log::info('訂閱快遞100結果', [$rst]); $rst = json_decode($rst, 1); Log::info('訂閱快遞100結果', [$rst]); if ($rst['result'] == false) { if ($rst['returnCode'] == 501) { Log::info('訂閱快遞100重復', [$rst, 'company' => $courier_company, 'courier_no' => $courier_no]); return true; } throw new ServiceException('訂閱快遞100失敗', $rst['returnCode']); } return true; }
(2)接收每個訂單信息的回調
/** * 快遞100回調 */ public static function notifyExpressInfo($poll_express_info) { $company = array_get($poll_express_info['lastResult'], 'com'); $number = array_get($poll_express_info['lastResult'], 'nu'); $borrow_express_type = FrontConst::BORROW_EXPRESS_TYPE_BORROW; $borrow_info = Borrow::where('business_courier_company_name', $company)->where('business_courier_no', $number)->first(); if (empty($borrow_info)) { $borrow_express_type = FrontConst::BORROW_EXPRESS_TYPE_RETURN; $borrow_info = Borrow::where('courier_company_name', $company)->where('courier_no', $number)->first(); } if (!empty($borrow_info)) { if ($borrow_info->status == FrontConst::STATUS_BORROW_DONE_RETURN) { \Log::info('---快遞100傳輸已完成的訂單號--', ['borrow_id' => $borrow_info->id, 'status' => $borrow_info->status, 'business_courier_no' => $borrow_info->business_courier_no, 'Request_courier_no' => $number]); throw new ServiceException('此單號已還書完成無需操作', -2000); } } if (empty($borrow_info)) { throw new ServiceException('沒有該訂單匹配的物流單號', -1000); } $express_last_info = array_get($poll_express_info, 'lastResult'); if (empty($express_last_info)) { throw new ServiceException('沒有最新快遞物流信息', -1000); } $ischeck = array_get($express_last_info, 'ischeck'); try { DB::beginTransaction(); $express_data = array_reverse($express_last_info['data']); foreach ($express_data as $key => $value) { //查詢該快遞信息是否已經錄入 $borrow_express = BorrowExpress::where('borrow_id', $borrow_info->id)->where('ftime', $value['ftime'])->first(); if (empty($borrow_express)) { $express_info = [ 'ischeck' => $ischeck, 'state' => ExpressConst::$expressState[$express_last_info['state']], 'ftime' => $value['ftime'], 'content' => $value['context'], 'control_status' => ExpressConst::$expressStatus[$poll_express_info['status']], 'control_message' => $poll_express_info['message'], ]; //增加快遞信息 self::addExpress($borrow_info->id, $borrow_info->borrow_source, $borrow_info->status, $express_info, $borrow_express_type); } } //快遞被簽收 if ($ischeck == 1 && $borrow_express_type == FrontConst::BORROW_EXPRESS_TYPE_BORROW) { $borrow_info->status = FrontConst::STATUS_BORROW_RECEIPT_DELIVERY; //修改訂單dead_line,支付寶小程序不需要修改 if ($borrow_info->borrow_source != FrontConst::SOURCE_ALIPAY_APPLETS) { $dead_line_info = BorrowRepository::getBorrowDeadOverdue($borrow_info); $borrow_info->dead_line = empty($dead_line_info['dead_line']) ? $borrow_info->dead_line : $dead_line_info['dead_line']; } $borrow_info->save(); $return_time = strtotime($borrow_info->dead_line); if ($borrow_info->borrow_source == FrontConst::SOURCE_ALIPAY_APPLETS) { $return_time -= FrontConst::APPLETS_RENTS_EXPRESS_RETURN_TIME * 3600 * 24; } if ($borrow_info->borrow_source == FrontConst::SOURCE_ALIPAY) { //判斷是否是信用借還 $notify_alipay_status = true; $user_package = $borrow_info->user_package; $package_info = empty($user_package->book_package) ? $user_package->package : $user_package->book_package; $notify_alipay_status = (!empty($user_package->book_package)) ? true : ($package_info->subscribe_times > 1 ? false : true); //通知支付寶修改訂單時間 if ($notify_alipay_status) { BorrowRepository::orderRentModify($borrow_info, $dead_line_info['dead_line']); \Log::info('該訂單' . $borrow_info->id . '使用的是' . $package_info->name . ',不需要修改到期時間', ['id' => $borrow_info->id]); } } self::addExpress($borrow_info->id, $borrow_info->borrow_source, $borrow_info->status); //發送短信 SmsEntrance::sendCodeByScene($borrow_info->mobile, SmsEntrance::SCENES_USER_BORROW_RECEIPT, date('m', $return_time), date('d', $return_time)); } DB::commit(); } catch (ServiceException $e) { DB::rollBack(); Log::error($e); throw new ServiceException($e->getMessage(), $e->getCode()); } catch (Exception $e) { DB::rollBack(); Log::error($e); throw new ServiceException($e->getMessage(), $e->getCode()); } return true; }
后記
日子要一天一天的過,知識要一點一點的積累。