(六)接口交互详解

本篇介绍一个接口请求的完整交互过程。

请求参数

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<String, String> param = new HashMap<String, String>();

    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());
}

签名算法

签名算法描述如下:

  1. 将请求参数按参数名升序排序;
  2. 按请求参数名及参数值相互连接组成一个字符串:<paramName1><paramValue1><paramName2><paramValue2>...
  3. 将应用密钥分别添加到以上请求参数串的头部和尾部:<secret><请求参数字符串><secret>
  4. 对该字符串进行MD5运算,得到一个二进制数组;
  5. 将该二进制数组转换为十六进制的字符串(全部大写),该字符串即是这些请求参数对应的签名;
  6. 该签名值使用sign参数一起和其它请求参数一起发送给服务开放平台。

伪代码:

Map<String,Object> paramsMap = new ...; // 参数

Set<String> keySet = paramsMap.keySet();
List<String> paramNames = new ArrayList<String>(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字段进行验证,验证步骤如下:

  1. 根据客户端传过来的app_key拿到服务端保存的secret
  2. 拿到secret后通过签名算法生成服务端的serverSign
  3. 比较客户端sign和serverSign是否相等,如果相等则证明客户端传来的数据是合法数据,否则不通过返回错误信息。
  4. 处理业务,返回结果

猜你喜欢

转载自blog.csdn.net/thc1987/article/details/80090541
今日推荐