请求参数
easyopen定义了7个固定的参数,用json接收
{
"name":"goods.get",
"version":"2.0",
"app_key":"test",
"data":"%7B%22goods_name%22%3A%22iphone6%22%7D",
"format":"json",
"timestamp":"2018-01-16 17:02:02",
"sign":"4CB446DF67DB3637500D4715298CE4A3"
}
name:接口名称
version:接口版本号
app_key:分配给客户端的app_key
data:业务参数,json格式并且urlencode
format:返回格式,json,xml两种
timestamp:时间戳,yyyy-MM-dd HH:mm:ss
sign:签名串
其中sign需要使用双方约定的签名算法来生成。
请求方式
请求数据放在body体中,采用json格式。这里给出一个POST工具类:
public class PostUtil {
private static final String UTF8 = "UTF-8";
private static final String CONTENT_TYPE_JSON = "application/json";
private static final String ACCEPT_LANGUAGE = "Accept-Language";
/**
* POST请求
* @param url
* @param params
* @param lang 语言zh,en
* @return
* @throws Exception
*/
public static String post(String url, JSONObject params, String lang) throws Exception {
String encode = UTF8;
// 使用 POST 方式提交数据
PostMethod method = new PostMethod(url);
try {
String requestBody = params.toJSONString();
// 请求数据放在body体中,采用json格式
method.setRequestEntity(new StringRequestEntity(requestBody, CONTENT_TYPE_JSON, encode));
// 设置请求语言
method.setRequestHeader(ACCEPT_LANGUAGE, lang);
HttpClient client = new HttpClient();
int state = client.executeMethod(method); // 返回的状态
if (state != HttpStatus.SC_OK) {
throw new Exception("HttpStatus is " + state);
}
String response = method.getResponseBodyAsString();
return response; // response就是最后得到的结果
} catch (Exception e) {
throw e;
} finally {
method.releaseConnection();
}
}
}
请求操作代码:
@Test
public void testGet() throws Exception {
Map param = new HashMap();
Goods goods = new Goods();
String data = JSON.toJSONString(goods);
data = URLEncoder.encode(data, "UTF-8");
param.put("name", "hello");
param.put("app_key", appId);
param.put("data", data);
param.put("timestamp", getTime());
param.put("version", "");
param.put("format", "json");
String sign = ApiUtil.buildSign(param, secret);
param.put("sign", sign);
System.out.println("请求内容:" + JSON.toJSONString(param));
String resp = PostUtil.post(url, param,"zh");
System.out.println(resp);
}
public String getTime() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
}
签名算法
签名算法描述如下:
将请求参数按参数名升序排序;
按请求参数名及参数值相互连接组成一个字符串:...;
将应用密钥分别添加到以上请求参数串的头部和尾部:;
对该字符串进行MD5运算,得到一个二进制数组;
将该二进制数组转换为十六进制的字符串(全部大写),该字符串即是这些请求参数对应的签名;
该签名值使用sign参数一起和其它请求参数一起发送给服务开放平台。
伪代码:
Map paramsMap = new ...; // 参数
Set keySet = paramsMap.keySet();
List paramNames = new ArrayList(keySet);
// 1.
Collections.sort(paramNames);
StringBuilder paramNameValue = new StringBuilder();
// 2.
for (String paramName : paramNames) {
paramNameValue.append(paramName).append(paramsMap.get(paramName));
}
// 3.
String source = secret + paramNameValue.toString() + secret;
// 4.& 5.
String sign = md5(source);
// 6.
paramsMap.put("sign",sign);
服务端验证
服务端拿到请求数据后会sign字段进行验证,验证步骤如下:
根据客户端传过来的app_key拿到服务端保存的secret
拿到secret后通过签名算法生成服务端的serverSign
比较客户端sign和serverSign是否相等,如果相等则证明客户端传来的数据是合法数据,否则不通过返回错误信息。
处理业务,返回结果