淘寶API介面AG文件接入呼叫方法詳解

搭建bc介面API系統演示發表於2022-05-13

淘寶開放平臺(TOP)的API是基於HTTP協議來呼叫的,開發者(AG)可以直接使用TOP提供的官方SDK(支援多種語言,包含了請求的封裝,簽名加密,響應解釋,效能優化等)來呼叫,也可以根據AG介面協議來封裝HTTP請求進行呼叫,以下主要是針對自行封裝HTTP請求進行API介面呼叫的原理進行詳細解說。

image

AG介面呼叫入口

呼叫API的服務URL地址,開放平臺目前提供了2個環境給ISV使用:正式環境,海外環境。

  • 正式環境: ISV軟體建立應用後呼叫介面使用請求地址,有http和https兩種地址。
  • 海外環境: 海外環境主要是給海外(歐美國家)ISV使用,對於海外的ISV,使用海外環境會比國內環境的效能高一倍。

呼叫環境 服務地址
正式環境 caichen,cc
海外環境 caichen,cc

公共引數

呼叫任何一個API都必須傳入的引數,目前支援的公共引數有:

引數名稱

引數型別

是否必須

引數描述

method

String

具體API介面名稱,例:taobao.item.seller.get

app_key

String

TOP分配給應用的AppKey。例:12345678

session

String

可選

使用者授權成功後,平臺頒發給應用的授權session,詳細介紹請點選這裡。當此API文件的標籤上註明:“需要授權”,則此引數必傳;“不需要授權”,則此引數不需要傳。

timestamp

String

時間戳,格式為yyyy-MM-dd HH:mm:ss,時區為GMT+8,例如:2016-01-01 12:00:00。淘寶API服務端允許客戶端請求最大時間誤差為10分鐘。

v

String

API協議版本,可選值:2.0

sign_method

String

簽名的摘要演算法,可選值為:hmac,md5,hmac-sha256。

sign

String

API輸入引數簽名結果,簽名演算法參照下面的介紹。

format

String

返回內容響應格式。不傳預設為xml格式,可選值:xml,json。

simplify

Boolean

是否採用精簡JSON返回格式,僅當format=json時有效,可選值:false,true,不傳為false。

業務引數

API呼叫除了必須包含公共引數外,如果API本身有業務級的引數也必須傳入,每個API的業務級引數請考API文件說明。

簽名演算法

為了防止API呼叫過程中被黑客惡意篡改,呼叫任何一個API都需要攜帶簽名,TOP服務端會根據請求引數,對簽名進行驗證,簽名不合法的請求將會被拒絕。TOP目前支援的簽名演算法有三種:MD5(sign_method=md5),HMAC_MD5(sign_method=hmac),HMAC_SHA256(sign_method=hmac-sha256),簽名大體過程如下:

  • 對所有API請求引數(包括公共引數和業務引數,但除去sign引數和byte[]型別的引數),根據引數名稱的 ASCII碼錶的順序排序。如:foo:1, bar:2, foo_bar:3, foobar:4排序後的順序是bar:2, foo:1, foo_bar:3, foobar:4。
  • 將排序好的引數名和引數值拼裝在一起,根據上面的示例得到的結果為:bar2foo1foo_bar3foobar4。
  • 把拼裝好的字串採用utf-8編碼,使用簽名演算法對編碼後的位元組流進行摘要。如果使用MD5演算法,則需要在拼裝的字串前後加上app的secret後,再進行摘要,如:md5(secret+bar2foo1foo_bar3foobar4+secret);如果使用HMAC_MD5演算法,則需要用app的secret初始化摘要演算法後,再進行摘要,如:hmac_md5(bar2foo1foo_bar3foobar4)。
  • 將摘要得到的位元組流結果使用十六進位制表示,如:hex("helloworld".getBytes("utf-8")) = "68656C6C6F776F726C64"

說明:MD5和HMAC_MD5都是128位長度的摘要演算法,用16進製表示,一個十六進位制的字元能表示4個位,所以簽名後的字串長度固定為32個十六進位制字元。

JAVA簽名示例程式碼

public static String signTopRequest(Map<String, String> params, String secret, String signMethod) throws IOException {	// 第一步:檢查引數是否已經排序
	String[] keys = params.keySet().toArray(new String[0]);
	Arrays.sort(keys);	// 第二步:把所有引數名和引數值串在一起
	StringBuilder query = new StringBuilder();	if (Constants.SIGN_METHOD_MD5.equals(signMethod)) { //簽名的摘要演算法,可選值為:hmac,md5,hmac-sha256
		query.append(secret);
	}	for (String key : keys) {
		String value = params.get(key);		if (StringUtils.areNotEmpty(key, value)) {
			query.append(key).append(value);
		}
	}	// 第三步:使用MD5/HMAC加密
	byte[] bytes;	if (Constants.SIGN_METHOD_HMAC.equals(signMethod)) {
		bytes = encryptHMAC(query.toString(), secret);
	} else {
		query.append(secret);
		bytes = encryptMD5(query.toString());
	}	// 第四步:把二進位制轉化為大寫的十六進位制(正確簽名應該為32大寫字串,此方法需要時使用)
	//return byte2hex(bytes);}public static byte[] encryptHMAC(String data, String secret) throws IOException {	byte[] bytes = null;	try {
		SecretKey secretKey = new SecretKeySpec(secret.getBytes(Constants.CHARSET_UTF8), "HmacMD5");
		Mac mac = Mac.getInstance(secretKey.getAlgorithm());
		mac.init(secretKey);
		bytes = mac.doFinal(data.getBytes(Constants.CHARSET_UTF8));
	} catch (GeneralSecurityException gse) {		throw new IOException(gse.toString());
	}	return bytes;
}public static byte[] encryptMD5(String data) throws IOException {	return encryptMD5(data.getBytes(Constants.CHARSET_UTF8));
}public static String byte2hex(byte[] bytes) {
	StringBuilder sign = new StringBuilder();	for (int i = 0; i < bytes.length; i++) {
		String hex = Integer.toHexString(bytes[i] & 0xFF);		if (hex.length() == 1) {
			sign.append("0");
		}
		sign.append(hex.toUpperCase());
	}	return sign.toString();
}

C#簽名示例程式碼

public static string SignTopRequest(IDictionary<string, string> parameters, string secret, string signMethod){    // 第一步:把字典按Key的字母順序排序
    IDictionary<string, string> sortedParams = new SortedDictionary<string, string>(parameters, StringComparer.Ordinal);
    IEnumerator<KeyValuePair<string, string>> dem = sortedParams.GetEnumerator();    // 第二步:把所有引數名和引數值串在一起
    StringBuilder query = new StringBuilder();    if (Constants.SIGN_METHOD_MD5.Equals(signMethod)) //簽名的摘要演算法,可選值為:hmac,md5,hmac-sha256
    {
        query.Append(secret);
    }    while (dem.MoveNext())
    {        string key = dem.Current.Key;        string value = dem.Current.Value;        if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(value))
        {
            query.Append(key).Append(value);
        }
    }    // 第三步:使用MD5/HMAC加密
    byte[] bytes;    if (Constants.SIGN_METHOD_HMAC.Equals(signMethod))
    {
        HMACMD5 hmac = new HMACMD5(Encoding.UTF8.GetBytes(secret));
        bytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(query.ToString()));
    }    else
    {
        query.Append(secret);
        MD5 md5 = MD5.Create();
        bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(query.ToString()));
    }    // 第四步:把二進位制轉化為大寫的十六進位制
    StringBuilder result = new StringBuilder();    for (int i = 0; i < bytes.Length; i++)
    {
        result.Append(bytes[i].ToString("X2"));
    }    return result.ToString();
}

其他語言簽名示例程式碼請參見TOP官方SDK原始碼。

呼叫示例

taobao.item.seller.get呼叫為例,具體步驟如下:

1. 設定引數值

公共引數:

  • method=taobao.item.seller.get
  • app_key=12345678
  • session=test
  • timestamp=2016-01-01 12:00:00
  • format=json
  • v=2.0
  • sign_method=md5

業務引數:

  • fields=num_iid,title,nick,price,num
  • num_iid=11223344

2. 按ASCII順序排序(去掉等號)

  • app_key12345678
  • fieldsnum_iid,title,nick,price,num
  • formatjson
  • methodtaobao.item.seller.get
  • num_iid11223344
  • sessiontest
  • sign_methodmd5
  • timestamp2016-01-01 12:00:00
  • v2.0

3. 拼接引數名與引數值

app_key12345678fieldsnum_iid,title,nick,price,numformatjsonmethodtaobao.item.seller.getnum_iid11223344sessiontestsign_methodmd5timestamp2016-01-01 12:00:00v2.0

4. 生成簽名
假設app的secret為helloworld,則簽名結果為:hex(md5(helloworld+按順序拼接好的引數名與引數值+helloworld)) = "66987CB115214E59E6EC978214934FB8"

5. 組裝HTTP請求
將所有引數名和引數值採用utf-8進行URL編碼(引數順序可隨意,但必須要包括簽名引數),然後通過GET或POST(含byte[]型別引數)發起請求,如:

%3A00%3A00&format=json&v=2.0&sign_method=md5&fields=num_iid%2Ctitle%2Cnick%2Cprice%2Cnum&num_iid=11223344&sign=66987CB115214E59E6EC978214934FB8

注意事項

  • 所有的請求和響應資料編碼皆為utf-8格式,URL裡的所有引數名和引數值請做URL編碼。如果請求的Content-Type是application/x-www-form-urlencoded,則HTTP Body體裡的所有引數值也做URL編碼;如果是multipart/form-data格式,每個表單欄位的引數值無需編碼,但每個表單欄位的charset部分需要指定為utf-8。
  • 引數名與引數值拼裝起來的URL長度小於1024個字元時,可以用GET發起請求;引數型別含byte[]型別或拼裝好的請求URL過長時,必須用POST發起請求。所有API都可以用POST發起請求,  但要求系統引數都放在query體中, 比如上述HTTP請求,系統引數app_key應該在queryt體,而業務引數fields可以在body體裡,也可以在在query體,但推薦放body體,防止URL過長。
  • 生成簽名(sign)僅對未使用TOP官方SDK進行API呼叫時需要操作,如使用了TOP官方SDK,該步驟SDK會自動完成。

常見平臺級錯誤碼

錯誤碼 錯誤資訊 錯誤原因 解決方案
7

msg:App Call Limited

sub_code:accesscontrol.limited-by- app-access-count

該應用(appkey)呼叫流量達到當天限制
(1)現在提供了緊急流量重置功能,每天可以重新整理三次,流量重置後會清零重新統計。
步驟:登入  開放平臺控制檯--應用管理--選擇對應應用管理--APP證照-- 點選 重置流量控制 ,就可以觸發流量重新整理。
(2)後續可在  支援中心提交工單,讓技術支援小二申請更高流量。
7

msg:App Call Limited

sub_code:accesscontrol.limited-by- api-access-count 

對單介面(api)呼叫總頻率的達到限制
該限制是平臺針對所有isv應用同時訪問某個api介面每分鐘或每秒鐘呼叫總量的限制。是api級別的限制,與單個isv應用(appkey)無關,api級別流量限制目的是防止短時間內請求量過大影響後端服務的穩定性。
api限流報錯,一般無法進行調整,只能稍後重試。此種錯誤一般還伴有“This ban will last for ** more seconds” 的資訊,意思是等待**秒鐘以後再呼叫。
解決辦法:
建議ISV調整降低該介面呼叫頻率,錯開高峰期呼叫。或者使用其他可介面進行分流。
7

msg:App Call Limited

sub_code:accesscontrol.limited-by- app-api-access-count

平臺限制單appkey呼叫某個介面的頻率 介面業務方為了幫助每個appkey介面呼叫資源的合理分配,做的每個應用的頻率限制,依照“This ban will last for ** more seconds” 中提示的限制時間結束後再呼叫。
11

Insufficient ISV Permissions

開發者許可權不足

isv.permission-api-package-empty 沒有和任何訪問包關聯,建議根據業務規則申請對應的許可權

isv.permission-api-package-not-allowed 不允許訪問不可訪問組的API,建議檢查一下自己申請的應用標籤是否正確,如果確實需要訪問不可訪問組的API需要根據業務規則到對應的業務線申請許可權 例如:買家不可訪問組就會有一些訂單API不允許買家應用訪問

isv.permission-api-package-limit 關聯的包中不允許訪問該API,建議根據業務規則申請對應的許可權

isv.permission-ip-whitelist-limit IP限制不允許訪問,建議到安全中心配置正確的IP白名單

21 Missing Method 缺少方法名引數 傳入的引數加入method欄位
22 Invalid Method 不存在的方法名 傳入的method欄位必需是你所呼叫的API的名稱,並且該API是確實存在的
24 Missing Signature 缺少簽名引數 傳入的引數中必需包含sign欄位
25 Invalid Signature 無效簽名

1、檢查appsecret是否正確,一般都是由於appsecret不對導致。

2、再簽名演算法是否正確,必需根據正確的演算法算出來的。

26 Missing Session 缺少SessionKey引數 傳入的引數中必需包含session欄位
27 Invalid Session 無效的SessionKey引數 如果報session不合法可能是使用者沒有繫結session或session過期造成的,使用者需要重新授權一下然後傳入新的sessionKey; 另外檢查生成的sessionkey和appkey是否匹配。
28 Missing App Key 缺少AppKey引數 傳入的引數必需包含app_key欄位
29 Invalid App Key 無效的AppKey引數 appkey傳入不對,確保appkey可用或者請求API的環境一致。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70017243/viewspace-2893936/,如需轉載,請註明出處,否則將追究法律責任。

相關文章