您好,登錄后才能下訂單哦!
這篇文章主要介紹如何使用聚合數據API查詢快遞數據,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
因為朋友的網站是用 ThinkPHP 寫的,為了保持將來代碼的兼容,這三個功能也用 ThinkPHP 寫成。
項目的所有文件都放在了 GitHub 上,部分敏感數據已經隱藏,你需要自行替換,地址如下:
GitHub 地址:使用聚合數據API查詢快遞數據-短信驗證碼-企業核名
因為這三個功能并不是正式產品,將來會需要嵌入到網站的各個功能模塊中去,所以為了查看起來方便,三個功能的代碼都寫在一個文件里,你只要重點關注以下幾個文件就好:
/Home/Conf/config.php 參數配置文件 /Home/Controller/IndexController.class.php 后端代碼、API的請求與處理 /Home/View/Index_index.html 前端 html
分別到上面兩家網站上找到“快遞”、“短信”、“核名”的文檔地址,根據里面的說明,把 KEY、URL 等信息放入配置文件Home/Conf/config.php,方便后面重復使用。
常用快遞API文檔
短信API文檔
核名-文檔
注意 短信的 API 服務,要先到網站的后臺添加“短信模板”,讓管理員審核后才可以正常調用
最后,Home/Conf/config.php 配置文件里的內容如下:
return array( // 快遞查詢 'EXPRESS_APP_KEY' => '你的快遞 APPKEY', 'EXPRESS_QUERY_URL' => 'http://v.juhe.cn/exp/index', //快遞單號查詢 'EXPRESS_COM_URL' => 'http://v.juhe.cn/exp/com', //快遞公司查詢 // 發短信 'SEND_SMS_KEY' => '你的短信接口 APPKEY', 'SEND_SMS_URL' => 'http://v.juhe.cn/sms/send', // 核名 'COMPANY_KEY' => '核名 APPKEY', 'COMPANY_URL' => 'http://eci.yjapi.com/ECIFast/Search', //數據庫配置信息 'DB_TYPE' => 'mysql', // 數據庫類型 'DB_HOST' => 'localhost', // 服務器地址 'DB_NAME' => '你的數據庫名', // 數據庫名 'DB_USER' => '你的數據庫用戶名', // 用戶名 'DB_PWD' => '密碼', // 密碼 'DB_PORT' => 3306, // 端口 'DB_PREFIX' => 'pre_', // 數據庫表前綴 'DB_CHARSET'=> 'utf8', // 字符集 );
為了防止惡意用戶利用暴露在外的短信接口搗亂,需要對每個手機號碼的行為進行記錄。例如:
向某個手機號碼發送短信驗證碼后, 60 秒內不能再次發送 必須在 1 小時內填寫短信驗證碼,否則會過期 避免 ajax 請求地址被機器人程序利用,在表單里要使用圖片驗證碼才能提交數據 關于“表單驗證碼”我們后面代碼會說明,這里先創建表結構如下,用于記錄短信發送記錄:
CREATE TABLE `pre_smsrecord` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `mobile` varchar(11) NOT NULL DEFAULT '', `tpl_id` int(11) NOT NULL, `code` int(6) NOT NULL, `time` int(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=M
mobile 是手機號碼 tpl_id是在網站后臺添加并通過審核的短信模板 code是發送的驗證碼(一般是4位或6位) time是發送時間戳 直接下載sql進行還原:在本項目的 GitHub 地址上也可以直接從 /Pubic 目錄找到 sql 文件,你可以直接把它還原你的 MySQL 上。
因為三個功能都需要表單驗證碼,所以首先實現它。
打開 /Home/View/Index_index.html,注意里面圖片驗證碼 img 標簽,以及對應的 javascript
<p> (通用)輸入驗證碼 <input type="text" name="verify" id="verify"> <img id="verify-img" src="/?m=Home&c=Index&a=verify" alt=""> <a id="btn-refresh-verify" href="javascript:;" title="">刷新</a> </p> <script type="text/javascript" charset="utf-8"> jQuery(document).ready(function($) { // 刷新驗證碼按鈕 $("#btn-refresh-verify").click(function(event) { $("#verify-img").attr('src', '/?m=Home&c=Index&a=verify' + "&time=" + new Date().getTime()); }); }); </script>
對應的后端代碼在 /Home/Controller/IndexController.class.php 中
/** * +-------------------------------------------------------------------------- * 生成驗證碼 * * +-------------------------------------------------------------------------- */ public function verify(){ $Verify = new \Think\Verify(); $Verify->entry(); } /** * +-------------------------------------------------------------------------- * 檢查驗證碼 * * @param string $code 輸入的驗證碼 * @return boolean * +-------------------------------------------------------------------------- */ protected function check_verify($code){ $verify = new \Think\Verify(); return $verify->check($code); }
因為 3 個功能實際上都是通過網絡來請求一個第三方網站的 API 接口地址,因此可以統一成一個通用的方法。代碼如下,可以傳入三個變量,分別為 :url、參數數組、請求方式(是否是post,默認為0),返回一個 json 格式的數據。
/** * +-------------------------------------------------------------------------- * 通用的“聚合數據”請求接口,返回JSON數據 * * @param string $url 接口地址 * @param array $params 傳遞的參數 * @param int $ispost 是否以POST提交,默認GET * @return json * +-------------------------------------------------------------------------- */ public function juhecurl($url,$params=false,$ispost=0){ $httpInfo = array(); $ch = curl_init(); curl_setopt( $ch, CURLOPT_HTTP_VERSION , CURL_HTTP_VERSION_1_1 ); curl_setopt( $ch, CURLOPT_USERAGENT , 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22' ); curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT , 30 ); curl_setopt( $ch, CURLOPT_TIMEOUT , 30); curl_setopt( $ch, CURLOPT_RETURNTRANSFER , true ); if( $ispost ) { curl_setopt( $ch , CURLOPT_POST , true ); curl_setopt( $ch , CURLOPT_POSTFIELDS , $params ); curl_setopt( $ch , CURLOPT_URL , $url ); } else { if($params){ curl_setopt( $ch , CURLOPT_URL , $url.'?'.$params ); }else{ curl_setopt( $ch , CURLOPT_URL , $url); } } $response = curl_exec( $ch ); if ($response === FALSE) { //echo "cURL Error: " . curl_error($ch); return false; } $httpCode = curl_getinfo( $ch , CURLINFO_HTTP_CODE ); $httpInfo = array_merge( $httpInfo , curl_getinfo( $ch ) ); curl_close( $ch ); return $response; }
后面我們獲取快遞數據、發送短信、查詢企業名稱,都可以調用這個通用的方法。
打開 /Home/View/Index_index.html
<h2>獲取快遞數據</h2> <div id="express-module"> <p> 選擇公司 <select name="express-company" id="express-company"> <option value="sf">順豐</option> <option value="sto">申通</option> <option value="yt">圓通</option> <option value="yd">韻達</option> <option value="tt">天天</option> <option value="ems">EMS</option> <option value="zto">中通</option> <option value="ht">匯通</option> </select> </p> <p> 輸入單號 <input type="text" name="express-number" id="express-number"> </p> <p> <button id="btn-query-express" type="button" class="btn btn-default">查詢快遞</button> </p> <p>返回結果:</p> <p id="reason" ></p> <p>快件動態:</p> <ul id="express-result"> </ul> </div> <!-- 引入jquery庫 --> <script src="__PUBLIC__/jquery.min.js" type="text/javascript"></script> <script type="text/javascript" charset="utf-8"> jQuery(document).ready(function($) { //點擊快遞查詢按鈕 $("#btn-query-express").click(function(event) { $("#reason").html(""); // 更新驗證碼 $("#verify-img").attr('src', '/?m=Home&c=Index&a=verify' + "&time=" + new Date().getTime()); $.getJSON( '/?m=Home&c=Index&a=getExpressData', { company: $("#express-company").val(), number: $("#express-number").val(), verify: $("#verify").val(), }, function(json, textStatus) { if(json['resultcode'] == 200){ var result_list = json['result']['list']; $("#express-result").html(""); for(var i = 0, l = result_list.length; i < l; i++) { $("#express-result").append("<li>" + result_list[i]['datetime'] + "," + result_list[i]['remark'] + "," +result_list[i]['zone'] + "</li>"); } } $("#reason").html(json['reason']); }); }); }); </script>
對應的后端代碼為如下,特別注意,你要把 this->juhecurl(C(“EXPRESS_QUERY_URL”), $params, 1); 這段的注釋去掉(因為我開發的時候查詢余額不足,所以使用了一個寫死的數組來讓程序能正常運行)
/** * +-------------------------------------------------------------------------- * 獲取快遞數據 * * @param string $get.company 快遞公司代碼 * @param string $get.number 快遞單號 * @return json * +-------------------------------------------------------------------------- */ public function getExpressData(){ // 傳入 get 參數,包括公司代號、快遞單號、驗證碼 $com = I("get.company"); $no = I("get.number"); $verify = I("get.verify"); // 處理驗證碼 if ( !$this->check_verify($verify) ) { $content = array('resultcode'=>1000, 'reason'=>'驗證碼填寫錯誤'); echo json_encode($content); exit(); } // 處理機器人程序刷接口(目前通過IP判斷) $ip = get_client_ip(0, true); $Record = M("expressrecord"); $express_record = $Record->where("ip='" . $ip . "'")->find(); if( $express_record && ( (time() - $express_record['time']) < 60 ) ){ echo json_encode(array('reason'=>'60秒內只能查詢一次')); exit(); } if ( $com && $no ) { $params = array( 'key' => C("EXPRESS_APP_KEY"), 'com' => $com, 'no' => $no ); // 開發測試階段直接返回值,不請求 API // $content = $this->juhecurl(C("EXPRESS_QUERY_URL"), $params, 1); $content = array('resultcode'=>200, 'reason'=>'查詢成功', 'result'=>array('list'=>array())); // 刪除舊記錄(如果有),然后添加新的記錄 $Record->where("ip='" . $ip . "'")->delete(); $data = array( 'ip' => $ip, 'time'=>time() ); $Record->add($data); //$returnArray = json_decode($content,true); echo json_encode($content, true); } }
短信驗證碼的發送和檢驗
廢話不多說,前端html直接上代碼。這里實際上有兩個動作,一個是“給我手機號碼 xxxxx 發個驗證碼”,另一個是“我已經收到了,并填寫了,請看我填寫的驗證碼對不對”。
<h2>發送短信驗證碼與檢查</h2> <div id="sms-module"> <p> 短信模板: <select name="send-sms-tplid" id="send-sms-tplid"> <option value="5596">申請注冊</option> <option value="5602">申請找回密碼</option> <option value="5603">在線核名</option> </select> </p> <p> 手機號碼:<input type="text" name="send-sms-mobile" id="send-sms-mobile"> </p> <p> 輸入手機驗證碼:<input type="text" name="send-sms-code" id="send-sms-code"> <span id="sms-count-down"></span> <button id="btn-send-sms" type="button" class="btn btn-default">發送驗證碼</button> </p> <p> <button id="btn-check-sms" type="button" class="btn btn-default">提交手機驗證碼</button> </p> </div> <script type="text/javascript" charset="utf-8"> /** * 發送短信驗證碼后,60秒倒計時 */ var seconds_left = 60; function sms_count_down(){ if(seconds_left > 0){ seconds_left = seconds_left-1; //var b=new Date(); document.getElementById("sms-count-down").innerHTML = seconds_left + "秒"; setTimeout("sms_count_down()",1000); } else { //根據 http://stackoverflow.com/questions/7526601/setattributedisabled-false-changes-editable-attribute-to-false // 不能為 setAttribute 設置任何值,都會變成 ”disabled“,要使用 removeAttribute document.getElementById("btn-send-sms").removeAttribute("disabled"); document.getElementById("btn-send-sms").innerHTML = "重新發送"; document.getElementById("sms-count-down").innerHTML = ""; } } jQuery(document).ready(function($) { //發送短信 $("#btn-send-sms").click(function(event) { $("#reason").html(""); $.getJSON( '/?m=Home&c=Index&a=sendSMS', { tplid: $("#send-sms-tplid").val(), mobile: $("#send-sms-mobile").val(), }, function(json, textStatus) { $("#reason").html(json['reason']); var error_code = json['error_code']; if(error_code == 0){ // 測試階段,不禁用,可檢查 60 秒重復發送 //$("#btn-send-sms").attr("disabled", true); //開始倒計時 sms_count_down(); }else{ $("#btn-send-sms").html("重新發送"); } }); }); //檢查短信驗證碼 $("#btn-check-sms").click(function(event) { $("#reason").html(""); // 更新驗證碼 $("#verify-img").attr('src', '/?m=Home&c=Index&a=verify' + "&time=" + new Date().getTime()); $.getJSON( '/?m=Home&c=Index&a=checkSmsCode', { tplid: $("#send-sms-tplid").val(), mobile: $("#send-sms-mobile").val(), code: $("#send-sms-code").val(), verify: $("#verify").val(), }, function(json, textStatus) { $("#reason").html(json['reason']); }); }); });
同樣因為有兩個動作,后端會稍微復雜一點點
/** * +-------------------------------------------------------------------------- * 請求發送短信接口,60秒后才能重新發送 * * @param int $get.tplid 短信模板id * @param string $get.mobile 手機號碼 * @return json * +-------------------------------------------------------------------------- */ public function sendSMS(){ $tpl_id = I("get.tplid"); // 短信模板id:注冊 5596 找回密碼 5602 在線核名 5603 $mobile = I("get.mobile"); // 手機號碼 // 檢查數據庫記錄 ,是否在 60 秒內已經發送過一次 $Record = M("smsrecord"); $where = array( 'mobile' => $mobile, 'tpl_id' => $tpl_id, ); $sms_record = $Record->where($where)->find(); if( $sms_record && ( (time() - $sms_record['time']) < 60 ) ){ echo json_encode(array('reason'=>'60秒內不能多次發送')); exit(); } // 如果60秒內沒有發過,則發送驗證碼短信(6位隨機數字) $code = mt_rand(100000, 999999); $smsConf = array( 'key' => C("SEND_SMS_KEY"), //您申請的APPKEY 'mobile' => $mobile, //接受短信的用戶手機號碼 'tpl_id' => $tpl_id, //您申請的短信模板ID,根據實際情況修改 'tpl_value' =>'#code#=' . $code //您設置的模板變量,根據實際情況修改 '#code#=1234&#company#=聚合數據' ); //測試階段,不發短信,直接設置一個“發送成功” json 字符串 $content = $this->juhecurl(C("SEND_SMS_URL") ,$smsConf, 1); //請求發送短信 //$content = json_encode(array('error_code'=>0, 'reason'=>'發送成功')); if($content){ $result = json_decode($content,true); $error_code = $result['error_code']; if($error_code == 0){ // 狀態為0,說明短信發送成功 // 數據庫存儲發送記錄,用于處理倒計時和輸入驗證,首先要刪除舊記錄 $Record->where("mobile=" . $mobile)->delete(); $data = array( 'mobile' => $mobile, 'tpl_id'=> $tpl_id, 'code'=>$code, 'time'=>time() ); $Record->data($data)->add(); //echo "短信發送成功,短信ID:".$result['result']['sid']; }else{ //狀態非0,說明失敗 //echo "短信發送失敗(".$error_code."):".$msg; } }else{ //返回內容異常,以下可根據業務邏輯自行修改 //$result['reason'] = '短信發送失敗'; } echo $content; } /** * +-------------------------------------------------------------------------- * 檢查填寫的手機驗證碼是否填寫正確 * 可以添加更多字段改造成注冊、登錄等表單 * * @param string $get.verify 驗證碼 * @param string $get.mobile 手機號碼 * @param int $get.tplid 短信模板ID * @param int $get.code 手機接收到的驗證碼 * +-------------------------------------------------------------------------- */ public function checkSmsCode(){ $verify = I("get.verify"); $tpl_id = I("get.tplid"); // 短信模板id:注冊 5596 找回密碼 5602 在線核名 5603 $mobile = I("get.mobile"); // 手機號碼 $code = I("get.code"); // 手機收到的驗證碼 if(!$this->check_verify($verify)){ $content = array('resultcode'=>1000, 'reason'=>'驗證碼填寫錯誤'); echo json_encode($content); exit(); } // 檢查數據庫記錄,輸入的手機驗證碼是否和之前通過短信 API 發送到手機的一致 $Record = M("smsrecord"); $where = array( 'mobile' => $mobile, 'tpl_id' => $tpl_id, 'code' => $code, ); $sms_record = $Record->where($where)->find(); if($sms_record){ echo json_encode(array('reason'=>'短信驗證碼核對成功')); // 處理后面的程序(如繼續登錄、注冊等) }else{ echo json_encode(array('reason'=>'短信驗證碼錯誤')); } }
因為這個接口本來只提供了每次查詢一個關鍵詞,而朋友的網站要求能每次查詢用“,”分隔的多個關鍵詞,因此需要對提交的數據和返回到前端的進行一番處理(循環處理多個列表)。
前端代碼比較簡單
<h2>企業核名</h2> <div id="company-module"> <p> 省份:上海 <input type="hidden" name="company-province" id="company-province" value="SH"> </p> <p> <input type="text" name="company-name" id="company-name"> </p> </div> <button id="btn-company" type="button" class="btn btn-default">企業核名</button> <p>公司查詢列表:</p> <ul id="company-result"> </ul> <javascript 略…… //企業核名(可輸入多個以逗號分隔的名稱來多次查詢) $("#btn-company").click(function(event) { $("#reason").html(""); $("#company-result").html(""); // 更新驗證碼 $("#verify-img").attr('src', '/?m=Home&c=Index&a=verify' + "&time=" + new Date().getTime()); $.getJSON( '/?m=Home&c=Index&a=getCompanyName', { province: $("#company-province").val(), companyName: $("#company-name").val(), verify: $("#verify").val(), }, function(json, textStatus) { if(json['reason']){ $("#reason").html(json['reason']); } else { //console.log(json); var json_list = JSON.parse(json); if (json_list.length > 0){ for(i in json_list){ var result_list = json_list[i].Result; if (result_list.length > 0){ for(j in result_list){ //console.log(result_list[j]); $("#company-result").append("<li> 名稱:" + result_list[j].Name + ", 法人:" + result_list[j].OperName + ", 狀態:" + result_list[j].Status + "</li>"); } } } } } }); }); </javascript>
后端代碼
/** * +-------------------------------------------------------------------------- * 企業核名 * 該接口 http://eci.yjapi.com/ECIFast/Search 僅支持 GET 方式,因此 $param 為字符串形式 * * @param string $get.province 省份 * @param string $get.companyName 公司名 * @return json * +-------------------------------------------------------------------------- */ public function getCompanyName(){ // 傳入 get 參數 $province = I("get.province"); $companyName = I("get.companyName"); $verify = I("get.verify"); // 處理驗證碼 if ( !$this->check_verify($verify) ) { $content = array('resultcode'=>1000, 'reason'=>'驗證碼填寫錯誤'); echo json_encode($content); exit(); } // 處理機器人程序刷接口(目前通過IP判斷) $ip = get_client_ip(0, true); $Record = M("companyrecord"); $company_record = $Record->where("ip='" . $ip . "'")->find(); // if( $company_record && ( (time() - $company_record['time']) < 60 ) ){ // echo json_encode(array('reason'=>'60秒內只能查詢一次企業名稱')); // exit(); // } $resultArray = array(); if ( $province && $companyName ) { // 刪除舊記錄(如果有),然后添加新的記錄 $Record->where("ip='" . $ip . "'")->delete(); // 循環處理多個公司名 $companies = explode(",", $companyName); foreach ($companies as $key => $value) { $params = "key=" . C("COMPANY_KEY") . "&province={$province}&companyName={$value}"; // 開發測試階段直接返回值,不請求 API $content = $this->juhecurl(C("COMPANY_URL"), $params, 0); $returnArray = json_decode($content,true); // 循環插入新的結果 $resultArray[] = $returnArray; //$content = array('resultcode'=>200, 'reason'=>'查詢成功', 'result'=>array('list'=>array())); } $data = array( 'ip' => $ip, 'time'=>time() ); $Record->add($data); $content = json_encode($resultArray, true); echo json_encode($content, true); } }
以上是“如何使用聚合數據API查詢快遞數據”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。