API是基于HTTP协议来调用的,开发者 可以根据的协议来封装HTTP请求进行调用。(参考淘宝API 写的)
协议:填充参数 > 生成签名 > 拼装HTTP请求 > 发起HTTP请求> 得到HTTP响应 > 解释json结果,以下是大体的调用过程示意图:
调用API的服务URL地址
调用任何一个API都必须传入的参数,目前支持的公共参数有 :
参数名称 | 参数类型 | 是否必须 | 参数描述 |
---|---|---|---|
method | String | 是 | API接口名称。 |
app_key | String | 是 | TOP分配给应用的AppKey。 |
timestamp | String | 是 | 时间戳,格式为yyyy-MM-dd HH:mm:ss,时区为GMT+8,例如:2016-01-01 12:00:00。服务端允许客户端请求最大时间误差为10分钟。 |
format | String | 否 | 响应格式。默认为xml格式,可选值:xml,json。 |
v | String | 是 | API协议版本,可选值:2.0。 |
sign_method | String | 是 | 签名的摘要算法,可选值为:hmac,md5。 |
sign | String | 是 | API输入参数签名结果,签名算法参照下面的介绍。 |
API调用除了必须包含公共参数外,如果API本身有业务级的参数也必须传入,每个API的业务级参数请考API文档说明。
为了防止API调用过程中被黑客恶意篡改,调用任何一个API都需要携带签名,服务端会根据请求参数,对签名进行验证,签名不合法的请求将会被拒绝。目前支持的签名算法有两种:MD5(sign_method=md5),HMAC_MD5(sign_method=hmac),签名大体过程如下:
说明:MD5和HMAC_MD5都是128位长度的摘要算法,用16进制表示,一个十六进制的字符能表示4个位,所以签名后的字符串长度固定为32个十六进制字符。
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Map;
/**
* Description
*
* ======================
* ======================
*
* @Author created by lgy
* @Date 2019/9/19
*/
public class SignMethodParamsRequest {
private static final String SIGN_METHOD_MD5 = "md5";
private static final String SIGN_METHOD_HMAC = "hmac";
private static final String CHARSET_UTF8 = "utf-8";
/**
* 方法参数签名
* ========================
*
* @param params
* @param secret
* @param signMethod
* @return
* @throws IOException
*/
public static String signParamsRequest(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 (SIGN_METHOD_MD5.equals(signMethod)) {
query.append(secret);
}
for (String key : keys) {
String value = params.get(key);
if (isNotEmpty(key) && isNotEmpty(value)) {
query.append(key).append(value);
}
}
// 第三步:使用MD5/HMAC加密
byte[] bytes;
if (SIGN_METHOD_HMAC.equals(signMethod)) {
bytes = encryptHMAC(query.toString(), secret);
} else {
query.append(secret);
System.out.println("字符串为:" + query);
bytes = encryptMD5(query.toString());
}
// 第四步:把二进制转化为大写的十六进制
return byte2hex(bytes);
}
/**
* 对字节流进行HMAC_MD5摘要
* ========================
*
* @param data
* @param secret
* @return
* @throws IOException
*/
private static byte[] encryptHMAC(String data, String secret) throws IOException {
byte[] bytes = null;
try {
SecretKey secretKey = new SecretKeySpec(secret.getBytes(CHARSET_UTF8), "HmacMD5");
Mac mac = Mac.getInstance(secretKey.getAlgorithm());
mac.init(secretKey);
bytes = mac.doFinal(data.getBytes(CHARSET_UTF8));
} catch (GeneralSecurityException gse) {
throw new IOException(gse.toString());
}
return bytes;
}
/**
* 对字符串采用UTF-8编码后,用MD5进行摘要
* ========================
*
* @param data
* @return
* @throws IOException
*/
private static byte[] encryptMD5(String data) throws IOException {
return encryptMD5(data.getBytes(CHARSET_UTF8));
}
/**
* 对字节流进行MD5摘要。
* ========================
*
* @param data
* @return
* @throws IOException
*/
private static byte[] encryptMD5(byte[] data) throws IOException {
byte[] bytes = null;
try {
MessageDigest md = MessageDigest.getInstance("MD5");
bytes = md.digest(data);
} catch (GeneralSecurityException gse) {
throw new IOException(gse.toString());
}
return bytes;
}
/**
* 把字节流转换为十六进制表示方式。
* ========================
*
* @param bytes
* @return
*/
private 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();
}
/**
* 非空判断
* ========================
*
* @param value
* @return
*/
private static boolean isNotEmpty(String value) {
int strLen;
if (value == null || (strLen = value.length()) == 0) {
return false;
}
for (int i = 0; i < strLen; i++) {
if ((Character.isWhitespace(value.charAt(i)) == false)) {
return true;
}
}
return false;
}
}
medgest-md5.js
function array(n) {
for (i = 0; i < n; i++) this[i] = 0;
this.length = n;
}
/* Quelques fonctions fondamentales doivent ¨ºtre transform¨¦es ¨¤ cause
* d'erreurs Javascript.
* Essayez par exemple de calculer 0xffffffff >> 4 ...
* Les fonctions utilis¨¦es maintenant sont il est vrai plus lentes que les
* fonctions originales mais elles fonctionnent.
*/
function integer(n) {
return n % (0xffffffff + 1);
}
function shr(a, b) {
a = integer(a);
b = integer(b);
if (a - 0x80000000 >= 0) {
a = a % 0x80000000;
a >>= b;
a += 0x40000000 >> (b - 1);
} else
a >>= b;
return a;
}
function shl1(a) {
a = a % 0x80000000;
if (a & 0x40000000 == 0x40000000) {
a -= 0x40000000;
a *= 2;
a += 0x80000000;
} else
a *= 2;
return a;
}
function shl(a, b) {
a = integer(a);
b = integer(b);
for (var i = 0; i < b; i++) a = shl1(a);
return a;
}
function and(a, b) {
a = integer(a);
b = integer(b);
var t1 = (a - 0x80000000);
var t2 = (b - 0x80000000);
if (t1 >= 0)
if (t2 >= 0)
return ((t1 & t2) + 0x80000000);
else
return (t1 & b);
else
if (t2 >= 0)
return (a & t2);
else
return (a & b);
}
function or(a, b) {
a = integer(a);
b = integer(b);
var t1 = (a - 0x80000000);
var t2 = (b - 0x80000000);
if (t1 >= 0)
if (t2 >= 0)
return ((t1 | t2) + 0x80000000);
else
return ((t1 | b) + 0x80000000);
else
if (t2 >= 0)
return ((a | t2) + 0x80000000);
else
return (a | b);
}
function xor(a, b) {
a = integer(a);
b = integer(b);
var t1 = (a - 0x80000000);
var t2 = (b - 0x80000000);
if (t1 >= 0)
if (t2 >= 0)
return (t1 ^ t2);
else
return ((t1 ^ b) + 0x80000000);
else
if (t2 >= 0)
return ((a ^ t2) + 0x80000000);
else
return (a ^ b);
}
function not(a) {
a = integer(a);
return (0xffffffff - a);
}
/* D¨¦but de l'algorithme */
var state = new array(4);
var count = new array(2);
count[0] = 0;
count[1] = 0;
var buffer = new array(64);
var transformBuffer = new array(16);
var digestBits = new array(16);
var S11 = 7;
var S12 = 12;
var S13 = 17;
var S14 = 22;
var S21 = 5;
var S22 = 9;
var S23 = 14;
var S24 = 20;
var S31 = 4;
var S32 = 11;
var S33 = 16;
var S34 = 23;
var S41 = 6;
var S42 = 10;
var S43 = 15;
var S44 = 21;
function F(x, y, z) {
return or(and(x, y), and(not(x), z));
}
function G(x, y, z) {
return or(and(x, z), and(y, not(z)));
}
function H(x, y, z) {
return xor(xor(x, y), z);
}
function I(x, y, z) {
return xor(y, or(x, not(z)));
}
function rotateLeft(a, n) {
return or(shl(a, n), (shr(a, (32 - n))));
}
function FF(a, b, c, d, x, s, ac) {
a = a + F(b, c, d) + x + ac;
a = rotateLeft(a, s);
a = a + b;
return a;
}
function GG(a, b, c, d, x, s, ac) {
a = a + G(b, c, d) + x + ac;
a = rotateLeft(a, s);
a = a + b;
return a;
}
function HH(a, b, c, d, x, s, ac) {
a = a + H(b, c, d) + x + ac;
a = rotateLeft(a, s);
a = a + b;
return a;
}
function II(a, b, c, d, x, s, ac) {
a = a + I(b, c, d) + x + ac;
a = rotateLeft(a, s);
a = a + b;
return a;
}
function transform(buf, offset) {
var a = 0,
b = 0,
c = 0,
d = 0;
var x = transformBuffer;
a = state[0];
b = state[1];
c = state[2];
d = state[3];
for (i = 0; i < 16; i++) {
x[i] = and(buf[i * 4 + offset], 0xff);
for (j = 1; j < 4; j++) {
x[i] += shl(and(buf[i * 4 + j + offset], 0xff), j * 8);
}
}
/* tour 1 */
a = FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
d = FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
c = FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
b = FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
a = FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
d = FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
c = FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
b = FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
a = FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
d = FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
c = FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
b = FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
a = FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
d = FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
c = FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
b = FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* tour 2 */
a = GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
d = GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
c = GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
b = GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
a = GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
d = GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
c = GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
b = GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
a = GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
d = GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
c = GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
b = GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
a = GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
d = GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
c = GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
b = GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* tour 3 */
a = HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
d = HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
c = HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
b = HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
a = HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
d = HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
c = HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
b = HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
a = HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
d = HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
c = HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
b = HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
a = HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
d = HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
c = HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
b = HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
/* tour 4 */
a = II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
d = II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
c = II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
b = II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
a = II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
d = II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
c = II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
b = II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
a = II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
d = II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
c = II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
b = II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
a = II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
d = II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
c = II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
b = II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
}
/* Avec l'initialisation de Dobbertin:
state[0] = 0x12ac2375;
state[1] = 0x3b341042;
state[2] = 0x5f62b97c;
state[3] = 0x4ba763ed;
s'il y a une collision:
begin 644 Message1
M7MH=JO6_>MG!X?!51$)W,CXV!A"=(!AR71,TF$W()/MEHR%C4:G1R:Q"=
`
end
begin 644 Message2
M7MH=JO6_>MG!X?!51$)W,CXV!A"=(!AR71,TF$W()/MEHREC4:G1R:Q"=
`
end
*/
function init() {
count[0] = count[1] = 0;
state[0] = 0x67452301;
state[1] = 0xefcdab89;
state[2] = 0x98badcfe;
state[3] = 0x10325476;
for (i = 0; i < digestBits.length; i++)
digestBits[i] = 0;
}
function update(b) {
var index, i;
index = and(shr(count[0], 3), 0x3f);
if (count[0] < 0xffffffff - 7)
count[0] += 8;
else {
count[1]++;
count[0] -= 0xffffffff + 1;
count[0] += 8;
}
buffer[index] = and(b, 0xff);
if (index >= 63) {
transform(buffer, 0);
}
}
function finish() {
var bits = new array(8);
var padding;
var i = 0,
index = 0,
padLen = 0;
for (i = 0; i < 4; i++) {
bits[i] = and(shr(count[0], (i * 8)), 0xff);
}
for (i = 0; i < 4; i++) {
bits[i + 4] = and(shr(count[1], (i * 8)), 0xff);
}
index = and(shr(count[0], 3), 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
padding = new array(64);
padding[0] = 0x80;
for (i = 0; i < padLen; i++)
update(padding[i]);
for (i = 0; i < 8; i++)
update(bits[i]);
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
digestBits[i * 4 + j] = and(shr(state[i], (j * 8)), 0xff);
}
}
}
/* Fin de l'algorithme MD5 */
function hexa(n) {
var hexa_h = "0123456789abcdef";
var hexa_c = "";
var hexa_m = n;
for (hexa_i = 0; hexa_i < 8; hexa_i++) {
hexa_c = hexa_h.charAt(Math.abs(hexa_m) % 16) + hexa_c;
hexa_m = Math.floor(hexa_m / 16);
}
return hexa_c;
}
var ascii = "01234567890123456789012345678901" +
" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
"[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
function MD5(message) {
var l, s, k, ka, kb, kc, kd;
init();
for (k = 0; k < message.length; k++) {
l = message.charAt(k);
update(ascii.lastIndexOf(l));
}
finish();
ka = kb = kc = kd = 0;
for (i = 0; i < 4; i++) ka += shl(digestBits[15 - i], (i * 8));
for (i = 4; i < 8; i++) kb += shl(digestBits[15 - i], ((i - 4) * 8));
for (i = 8; i < 12; i++) kc += shl(digestBits[15 - i], ((i - 8) * 8));
for (i = 12; i < 16; i++) kd += shl(digestBits[15 - i], ((i - 12) * 8));
s = hexa(kd) + hexa(kc) + hexa(kb) + hexa(ka);
return s;
}
sign-params.js
// 业务参数排序
function serviceParamsSort(serviceParams) {
return serviceParams.sort().join("");
}
//获取当前时间 时间戳yyyy-MM-dd HH:mm:ss 格式
function getFormatDate() {
var date = new Date();
var seperator1 = "-";
var seperator2 = ":";
var month = date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1;
var strDate = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
var currentdate = date.getFullYear() + seperator1 + month + seperator1 + strDate +
" " + date.getHours() + seperator2 + date.getMinutes() +
seperator2 + date.getSeconds();
return currentdate;
}
// 格式化时间戳 yyyy-MM-dd HH:mm:ss
function formatDate(date) {
var seperator1 = "-";
var seperator2 = ":";
var month = date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1;
var strDate = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
var currentdate = date.getFullYear() + seperator1 + month + seperator1 + strDate +
" " + date.getHours() + seperator2 + date.getMinutes() +
seperator2 + date.getSeconds();
return currentdate;
}
//方法参数验签
function signParam(maps, app_secret, sign_method) {
var keys = new Array();
for (var key of maps.keys()) {
keys.push(key);
}
//第一步 先对键值排序
keys = keys.sort();
// 第二部 将所有的参数名和参数值拼接在一起
var query = "";
if (sign_method == "md5") {
query = query + app_secret;
}
// 拼接maps 的key 和value值
for (var key of keys) {
var value = maps.get(key);
if ((key != null && key != "") && (value != null && value != "")) {
query = query + key + value;
}
}
// 第三部 使用md5加密
var bytes = new Array();
if (sign_method == "md5") {
query = query + app_secret;
return MD5(query).toUpperCase();
}
}
function stringToBytes(str) {
var ch, st, re = [];
for (var i = 0; i < str.length; i++) {
ch = str.charCodeAt(i); // get char
st = []; // set up "stack"
do {
st.push(ch & 0xFF); // push byte to stack
ch = ch >> 8; // shift value down by 1 byte
}
while (ch);
// add stack contents to result
// done because chars have "wrong" endianness
re = re.concat(st.reverse());
}
// return an array of bytes
return re;
}
服务器过滤器(较早版本)
/** ----解决跨域访问报错---- */
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST,GET,PUT,OPTIONS,DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers",
"Origin,X-Requested-With,Content-Type,Accept,Authorization,token");
/** ----解决跨域访问报错---- */
/** -------------- open api校验 ./start-------------- */
String appkey = request.getParameter("app_key");
String v = request.getParameter("v");
String timestamp = request.getParameter("timestamp");
String signMethod = request.getParameter("sign_method");
String format = request.getParameter("format");
String clientSign = request.getParameter("sign");
String msg = validParamsNull(appkey, v, timestamp, signMethod, format, clientSign);
if (msg.length() > 2) {
RenderUtil.renderJson(response, new ErrorTip(700, msg));
return;
}
/** -------------- open api校验 ./end-------------- */
/** ---------- 私钥公钥版本校验 ----------------*/
String appSecret = "";
Map map = new HashMap();
map.put("app_key", appkey);
map.put("v", v);
TOpenApi openApi = this.openApiService.getOpenApiByAppkKeyV(appkey, v);
// 非授权公钥 或公钥与版本不一致
if (openApi == null) {
RenderUtil.renderJson(response, new ErrorTip(BizExceptionEnum.APP_KEY_ILLEGAL.getCode(),
BizExceptionEnum.APP_KEY_ILLEGAL.getMessage()));
return;
} else {
appSecret = openApi.getAppSecret();
}
// 时间校验,允许10分钟上下的时间差
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = null;
boolean result = true;
try {
date = df.parse(timestamp);
Date serverDate = new Date();
long clientDateTime = date.getTime();
long serverDateTime = serverDate.getTime();
long disparity = Math.abs(serverDateTime - clientDateTime);
// 时间差为大小10分钟之内,result 改为true
if (disparity <= 600000) {
result = false;
}
} catch (ParseException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// 时间差超过10分种
if (result) {
RenderUtil.renderJson(response, new ErrorTip(BizExceptionEnum.TIMESTAMP_DIFFERENCE_BIG.getCode(),
BizExceptionEnum.TIMESTAMP_DIFFERENCE_BIG.getMessage()));
return;
}
// 参数签名校验
Map maps = new HashMap();
Enumeration paramsNames = request.getParameterNames();
String[] ex = {"app_key", "timestamp", "v", "format", "sign", "app_secret", "sign_method"};
String params = "";
for (Enumeration e = paramsNames; e.hasMoreElements(); ) {
String paramName = e.nextElement().toString();
params = params + paramName + ",";
}
// 去除ex包含的公共参数
Set set = new HashSet(Arrays.asList(params.split(",")));
for (String e : ex) {
set.remove(e);
}
params = StringUtils.join(set.toArray(), ",");
// 公共参数
maps.put("method", "zhms.item.seller.get");
maps.put("app_key", appkey);
maps.put("format", "json");
maps.put("v", "1.0");
maps.put("sign_method", signMethod);
maps.put("timestamp", df.format(date));
maps.put("app_secret", appSecret);
// 业务参数
String[] paramsObj = params.split(",");
Arrays.sort(paramsObj);
params = "";
for (String str : paramsObj) {
params = params + str;
}
maps.put("fields", params);
logger.info("参数校验:" + maps);
// 比对参数签名是否一致,不一致校验不通过,无权调用api
String ServerSign = SignMethodParamsRequest.signParamsRequest(maps, appSecret, signMethod);
System.out.println(ServerSign);
if (!clientSign.equals(ServerSign)) {
RenderUtil.renderJson(response,
new ErrorTip(BizExceptionEnum.SIGN_ERROR.getCode(), BizExceptionEnum.SIGN_ERROR.getMessage()));
return;
}
其他语言签名示例代码请自行解决。
1. 设置参数值
公共参数:
业务参数:
2. 按ASCII顺序排序
3. 拼接参数名与参数值
a p p k e y 12345678 f i e l d s n u m i i d , t i t l e , n i c k , p r i c e , n u m f o r m a t j s o n m e t h o d t a o b a o . i t e m . s e l l e r . g e t n u m i i d 11223344 s e s s i o n t e s t s i g n m e t h o d m d 5 t i m e s t a m p 2016 − 01 − 0112 : 00 : 00 v 2.0 app_key12345678fieldsnum_iid,title,nick,price,numformatjsonmethodtaobao.item.seller.getnum_iid11223344sessiontestsign_methodmd5timestamp2016-01-01 12:00:00v2.0 appkey12345678fieldsnumiid,title,nick,price,numformatjsonmethodtaobao.item.seller.getnumiid11223344sessiontestsignmethodmd5timestamp2016−01−0112:00:00v2.0
4. 生成签名
假设app的secret为helloworld,则签名结果为:hex(md5(helloworld+按顺序拼接好的参数名与参数值+helloworld)) = “66987CB115214E59E6EC978214934FB8”
5. 组装HTTP请求
将所有参数名和参数值采用utf-8进行URL编码(参数顺序可随意,但必须要包括签名参数),然后通过GET或POST(含byte[]类型参数)发起请求,如:
http://www.bingo.com/router/rest?method=bingo.item.seller.get&app_key=12345678&session=test×tamp=2016-01-01+12%3A00%3A00&format=json&v=2.0&sign_method=md5&fields=num_iid%2Ctitle%2Cnick%2Cprice%2Cnum&num_iid=11223344&sign=66987CB115214E59E6EC978214934FB8