回顧篇:淘寶API web開發二 呼叫API
上一篇已經說明了如何引導使用者授權登入,獲取access_token。這樣,我們就可以正式呼叫API了。
淘寶提供了兩種呼叫方法,一種為http呼叫方法,一種為https免籤呼叫方式。因為專案用的是第一種方法,那麼在這裡,我們就只介紹http的呼叫方法。
淘寶API採用REST風格,我們需要按照淘寶開發平臺的規範拼裝一個正確的URL,通過HTTP請求到http://gw.api.taobao.com/router/rest(測試環境為http://gw.api.tbsandbox.com/router/rest),就可以獲取到自己需要的資料。
呼叫API時,需要傳入系統引數和應用引數。
系統引數如下:
名稱 |
型別 |
是否必須 |
描述 |
method |
string |
Y |
API介面名稱 |
timestamp |
string |
Y |
時間戳,格式為yyyy-mm-dd HH:mm:ss,例如:2013-05-06 13:52:03。淘寶API服務端允許客戶端請求時間誤差為6分鐘。 |
format |
string |
N |
可選,指定響應格式。預設xml,目前支援格式為xml,json |
app_key |
string |
Y |
TOP分配給應用的AppKey ,建立應用時可獲得 |
v |
string |
Y |
API協議版本,可選值:2.0。 |
sign |
string |
Y |
對 API 輸入引數進行 md5 加密獲得,下面會介紹到sign |
sign_method |
string |
Y |
引數的加密方法選擇,可選值是:md5,hmac |
session |
string |
N |
TOP分配給使用者的SessionKey(或 Access Token),通過登陸授權獲取(可參考上一篇博文) 。API 文件上 “API使用者授權型別” 標識為“需要”的,呼叫時均要傳該引數 |
應用引數如下:
名稱 |
型別 |
是否必須 |
描述 |
fields |
Field List |
Y |
獲取到資料後,需要返回的欄位。 示例值: 更多值請參考http://api.taobao.com/apidoc/api.htm?spm=0.0.0.0.yd3ygq&path=cid:5-apiId:128 |
start_modified |
Date |
Y |
查詢修改開始時間(修改時間跨度不能大於一天)。格式:yyyy-MM-dd HH:mm:ss |
end_modified |
Date |
Y |
查詢修改結束時間,必須大於修改開始時間(修改時間跨度不能大於一天),格式:yyyy-MM-dd HH:mm:ss。 |
status |
string |
N |
交易狀態,預設查詢所有交易狀態的資料,除了預設值外每次只能查詢一種狀態。可選值如 TRADE_NO_CREATE_PAY(沒有建立支付寶交易) WAIT_BUYER_PAY(等待買家付款) 等。 |
type |
string |
N |
交易型別列表,同時查詢多種交易型別可用逗號分隔。默認同時查詢guarantee_trade,auto_delivery,ec,code,step的5種交易型別的資料。 |
ext_type |
string |
N |
可選值有ershou(二手市場的訂單),service(商城服務子訂單)mark(雙十一大促活動異常訂單)作為擴充套件型別篩選只能做單個ext_type查詢,不能全部查詢所有的ext_type型別 |
tag |
string |
N |
賣家對交易的自定義分組標籤,目前可選值為:time_card(點卡軟體代充),fee_card(話費軟體代充) |
page_no |
Number |
N |
頁碼。取值範圍:大於零的整數;預設值:1。注:必須採用倒序的分頁方式(從最後一頁往回取)才能避免漏單問題。 |
page_size |
Number |
N |
每頁條數。取值範圍:1~100,預設值:40。 |
use_has_next |
Boolean |
N |
是否啟用has_next的分頁方式,如果指定true,則返回的結果中不包含總記錄數,但是會新增一個是否存在下一頁的的欄位,通過此種方式獲取增量交易,效率在原有的基礎上有80%的提升。 |
在系統引數中,我們需要傳入引數的簽名驗證sign,淘寶開發平臺伺服器需要對該請求引數進行驗證是否合法,方法如下:
根據引數名稱(除簽名和圖片)將所有請求引數按照字母先後順序排序:key + value.....key + value,再將應用的secretKey加在該字串的前後兩端。
例如,secretKey=4,將引數為foo=1,bar=2,baz=3排序為bar=2,baz=3,foo=1,引數名和引數值連線後,拼接成字串 4bar2baz3foo14
然後再將拼接的字串採用MD5或者HMAC加密,將加密結果轉換為32位大寫字串。
最後,我們就可以將所有的引數拼接好,使用CURL庫將引數POST到淘寶開發平臺,獲取我們需要的資料了。
具體程式碼如下:
設定請求引數的應用級引數 webERP / api / taobao / common / taobaoRequest.php
<?php
/**
* 這個檔案包含 taobaoRequest類
*/
/**
* taobaoRequest 設定請求引數的應用級引數
*/
class taobaoRequest{
/**
* @var array 應用級引數陣列
*/
protected $apiParams = array();
/**
* @var string 使用的介面名稱
*/
protected $apiMethod;
/**
* 設定使用介面的名稱
* @param string $value 介面名稱
*/
function setApiMethod( $value ){
$this->apiMethod = empty($value)? '' : $value;
}
/**
* 返回使用的介面名稱
* @return 使用的介面名稱
*/
function getApiMethod(){
return $this->apiMethod;
}
/**
* 設定應用引數值,為了適用不同的介面,引數名需要自己傳入
* @param string $key 應用引數的引數名,不同介面引數名會有所不同
* @param string $value 引數的值
*/
public function set( $key, $value ){
$this->apiParams[$key] = $value;
}
/**
* 獲取指定的應用引數值
* @param string $key 指定的引數名
* @return string 對應的引數值
*/
public function get( $key ){
return isset($this->apiParams[$key])? $this->apiParams[$key] : null;
}
/**
* 獲取按引數名稱排序後的應用級引數陣列
* @return array 應用級引數陣列
*/
public function getApiParams(){
//將引數按字母排序
ksort($this->apiParams);
if( $this->apiParams ){
return $this->apiParams;
}else{
return [];
}
}
/**
* 有些介面需要傳送附件,獲取檔案的base64編碼
* @param string 檔案路徑
* @return 檔案內容的編碼
*/
public function fileHandle( $file ){
//php curl的附件傳送機制中,需要在檔案路徑前加上@
if(substr($file, 0, 1) == '@'){
$file = substr($file, 1);
$file = base64_encode( file_get_contents($file) );
}
return $file;
}
}
?>
呼叫API介面 webERP / api / taobao / common / taobaoClient.php<?php
/**
* 這個檔案包含taobaoClient類
*/
/**
* taobaoClient類 根據引數生成簽名
* 將引數拼接成指定規則的URL,通過HTTP請求到淘寶開發平臺
* 解析返回的資料
*/
class taobaoClient{
/**
*@var string 應用的appkey
*/
public $appKey;
/**
*@var string 應用的secretKey
*/
public $secretKey;
/**
*@var string HTTP請求的地址
*/
public $gateWayUrl = "http://gw.api.taobao.com/router/rest";
/**
* @var string 請求的系統引數,預設值2.0
*/
public $apiVersion = '2.0';
/**
* 拼裝請求引數拼,通過HTTP請求請求資料
* @param taobaoRequest $request taobaoRequest類物件
* @param string $session 訪問令牌ACCESS TOKEN
*/
public function execute(taobaoRequest $request, $session = null){
$result = new stdClass();//保留類,存放返回的錯誤資訊
//設定系統引數
$sysParams['method'] = $request->getApiMethod();//API介面名稱
if($session != null){
$sysParams['session'] = $session;//access token
}
$sysParams['timestamp'] = date('Y-m-d H:i:s');//時間戳
$sysParams['format'] = 'json'; // 指定響應格式,支援的格式有json,xml
$sysParams['app_key'] = $this->$appKey;
$sysParams['v'] = $this->apiVersion;
$sysParams['sign_method'] = 'md5';//引數的加密方法選擇,可選值是:md5,hmac
//應用級引數
$apiParams = array();
$apiParams = $request->getApiParams();
//系統引數,簽名驗證sign
$sysParams['sign'] = $this->generateSign(array_merge($sysParams, $apiParams ));
$requestUrl = $this->gateWayUrl . '?' . http_build_query($sysParams);
//獲取資料
try{
$resp = $this->curl($requestUrl, $apiParams);
}catch(Exception $e){
$result->code = $e->getcode();
$result->zh_desc = "curl傳送http請求失敗";
$result->en_desc = $e->getMessge();
}
//解析返回結果
$respObject = json_decode($resp); // 解析json格式資料
$respWellFormed = false;
if( null != $respObject){
$respWellFormed = true;
foreach ( $respObject as $propKey => $propValue) {
$respObject = $propValue;
}
}
if(false === $respWellFormed){
$result->code = 1;
$result->zh_desc = "api返回資料錯誤或程式無法解析返回引數";
$result->en_desc = "HTTP_RESPONSE_NOT_WELL_FORMED";
return $result;
}
return $respObject;
}
/**
* 生成驗證簽名sign
* 根據引數名稱(除簽名和圖片)將所有請求引數按照字母先後順序排序,
* 再將應用的secretKey加在該字串的前後兩端,
* 然後再將拼接的字串採用MD5或者HMAC加密,將加密結果轉換為32位大寫字串。
* @param array 請求引數陣列
* @return array 加密後的簽名
*/
private function generateSign( $params ){
if( $params != null){
ksort($params);
$stringToBeSigned = $this->secretKey;
foreach ($params as $key => $value) {
$stringToBeSigned .= "$key$value";
}
$stringToBeSigned .= $this->secretKey;
}else{
$stringToBeSigned = $this->secretKey;
$stringToBeSigned .= $this->secretKey;
}
//注意:根據系統引數sign_method設定的加密的方法
return strtoupper( md5($stringToBeSigned) );
}
/**
* 使用CURL庫,做HTTP請求資料
* @param string 請求訪問的地址
* @param array 訪問所需的應用級引數
* @return json 返回的資料結果
*/
public function curl($url, $postFields = null){
//使用curl庫
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);//需要獲取的URL
curl_setopt($ch, CURLOPT_FAILONERROR, false);//不顯示HTTP狀態碼
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);//獲取的資訊以檔案流的形式返回
//https免籤呼叫方式
if( strlen($url) >5 && strtolower(substr($url, 0, 5)) == 'https'){
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, fasle);//終止從伺服器端進行驗證
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
}
//
if( isset($postFields) && 0 > count($postFields) ){
curl_setopt($ch, CURLOPT_POST, ture);//以POST方式傳送
$postMultipart = false;
//判斷是否有附件傳送
foreach ($postFields as $key => $value) {
if( '@' == substr($value, 0, 1)){
$postMultipart = true;
break;
}
}
unset($key, $value);
if( $postMultipart ){
curl_setopt($ch, CURLOPT_POSTFIELD, $postFields);
}else{
curl_setopt($ch, CURLOPT_POSTFIELD, http_build_query($postFields));
}
}
$response = curl_exec($ch);
if( curl_errno($ch) ){
throw new Exception(curl_errno($ch), 0);
}else{
$httpStatusCode = curl_getinfo($ch, CURLOPT_HTTP_CODE);
if(200 != $httpStatusCode){
throw new Exception($response, $httpStatusCode);
}
}
curl_close($ch);
return $response;
}
}
?>
現在來測試呼叫taobao.trade.sold.increment.get介面,程式碼如下webERP / api / taobao / tradeSoldIncrementGet.php
<?php
//測試呼叫介面 taobao.trade.sold.increment.get
date_default_timezone_set('PRC');//設定時區
//結束時間 預設當天
$end_date = date('Y-m-d 23:59:59');
//開始時間前一天
$start_date = date('Y-m-d 23:59:59', strtotime("$end_date -1 day"));
require_once 'common/taobaoConfig.php';
require_once 'common/taobaoRequest.php';
$request = new taobaoRequest();
//呼叫介面taobao.trades.sold.increment.get
$request->setApiMethod('taobao.trades.sold.increment.get');
//根據淘寶要求的該介面的應用引數,設定各個引數值
$fields = 'seller_nick, buyer_nick, title, type, created, tid,buyer_rate,can_rate,status, payment, discount_fee, adjust_fee, post_fee, total_fee, pay_time, end_time, modified, consign_time, buyer_obtain_point_fee, point_fee, real_point_fee, received_payment,num, price, cod_fee, cod_status, shipping_type, receiver_name, receiver_state, receiver_city, receiver_district, receiver_address, receiver_zip, receiver_mobile, receiver_phone,alipay_id,alipay_no,has_buyer_message,credit_card_fee,step_trade_status,step_paid_fee,mark_desc,trade_source,seller_flag,is_part_consign, orders.title, orders.price, orders.num, orders.sku_id, orders.refund_status, orders.status, orders.oid, orders.total_fee, orders.payment, orders.discount_fee, orders.adjust_fee, orders.sku_properties_name, orders.outer_sku_id, orders.refund_id,orders.end_time,orders.consign_time,orders.shipping_type,orders.logistics_company,orders.invoice_no';
$request->set('fields',$fields);
$request->set('start_modified',$start_date);
$request->set('end_modified',$end_date);
$page_size = 20;
$request->set('page_size', $page_size);//每頁20條記錄
$request->set('use_has_next', 'true');//分頁獲取
$page_no = 1;
while(true){
$request->set('page_no', $page_no);//獲取第page_no頁資料
$response = $taobao->execute($request,$access_token);
echo '<pre>';
var_dump($response);//輸出返回結果,可根據自己需要做其他操作
//獲取錯誤,停止獲取
if( isset($response->code) ){
break;
}
//判斷是否還存在下一頁,如果還存在,則繼續請求資料
if( $response->has_next ){
$page_no++;
}else{
break;
}
}
?>