感谢您的反馈!
淘宝全球开放平台会对每个 API 请求的身份进行验证,伺服器也将验证呼叫参数是否有效。因此,每个 HTTP 请求必须包含签名资讯,签名无效的请求将被拒绝。
淘宝全球开放平台通过 App Key 和分配给应用程式的金钥来验证请求的身份。 App 金钥用于在 HTTP 请求 URL 和伺服器端签名字串时生成签名字串。请严格保密您的金钥。
如果手动编写 HTTP 请求(而不使用官方 SDK),则需要了解以下签名算法。
生成签名的过程如下:
Before sort:
foo=1, bar=2, foo_bar=3, foobar=4
After sort:
bar=2, foo=1, foo_bar=3, foobar=4
将排序后的参数及其值连接到一个字串中。举例:bar2foo1foo_bar3foobar4
在连接的字串前面添加API名称。举例,添加API名称“/test/api”:
/test/apibar2foo1foo_bar3foobar4
hmac_sha256(/test/apibar2foo1foo_bar3foobar4)
hex("helloworld".getBytes("utf-8")) = "68656C6C6F776F726C64"
JAVA 示例代码:
/**
* Sign the API request with body.
*/
public static String signApiRequest(Map<String, String> params, String body, String appSecret, String signMethod, String apiName) throws IOException {
// first: sort all text parameters
String[] keys = params.keySet().toArray(new String[0]);
Arrays.sort(keys);
// second: connect all text parameters with key and value
StringBuilder query = new StringBuilder();
query.append(apiName);
for (String key : keys) {
String value = params.get(key);
if (areNotEmpty(key, value)) {
query.append(key).append(value);
}
}
// third:put the body to the end
if (body != null) {
query.append(body);
}
// next : sign the whole request
byte[] bytes = null;
if(signMethod.equals(Constants.SIGN_METHOD_HMAC)) {
bytes = encryptWithHmac(query.toString(), appSecret);
} else if(signMethod.equals(Constants.SIGN_METHOD_SHA256)) {
bytes = encryptHMACSHA256(query.toString(), appSecret);
}
// finally : transfer sign result from binary to upper hex string
return byte2hex(bytes);
}
private static byte[] encryptHMACSHA256(String data, String secret) throws IOException {
byte[] bytes = null;
try {
SecretKey secretKey = new SecretKeySpec(secret.getBytes(Constants.CHARSET_UTF8), Constants.SIGN_METHOD_HMAC_SHA256);
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;
}
/**
* Transfer binary array to HEX string.
*/
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 SignRequest(IDictionary<string, string> parameters, string body, string appSecret, string signMethod, string apiName)
{
// first : sort all key with asci order
IDictionary<string, string> sortedParams = new SortedDictionary<string, string>(parameters, StringComparer.Ordinal);
// second : contact all params with key order
StringBuilder query = new StringBuilder();
query.Append(apiName);
foreach (KeyValuePair<string, string> kv in sortedParams)
{
if (!string.IsNullOrEmpty(kv.Key) && !string.IsNullOrEmpty(kv.Value))
{
query.Append(kv.Key).Append(kv.Value);
}
}
// third : add body to last
if (!string.IsNullOrEmpty(body))
{
query.Append(body);
}
// next : sign the string
byte[] bytes = null;
if (signMethod.Equals(Constants.SIGN_METHOD_SHA256))
{
HMACSHA256 sha256 = new HMACSHA256(Encoding.UTF8.GetBytes(appSecret));
bytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(query.ToString()));
}
// finally : transfer binary byte to hex string
StringBuilder result = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
{
result.Append(bytes[i].ToString("X2"));
}
return result.ToString();
}
PYTHON 示例代码:
def sign(secret,api, parameters):
#===========================================================================
# @param secret
# @param parameters
#===========================================================================
sort_dict = sorted(parameters)
parameters_str = "%s%s" % (api,
str().join('%s%s' % (key, parameters[key]) for key in sort_dict))
h = hmac.new(secret.encode(encoding="utf-8"), parameters_str.encode(encoding="utf-8"), digestmod=hashlib.sha256)
return h.hexdigest().upper()
其他程式设计语言的签名样例代码,请参阅官方 SDK 的原始程式码。