SPRINGBOOT-9 Signature JAVA API

必须先要吐槽一下,一个API连个好用的文档都没有,全靠和人当面沟通,浪费了一整天的时间调接口。

 

先上代码:

以下函数为API提供方提供的代码,大致就是把所有的参数全部打包起来和timestamp一起做一个SHA1加密。


    public static String signatureWithParamsAndUrlPath(String urlPath, Map<String, Object> params, String secretKey,Long timestamp) throws Exception{
        List<String> paramValueList = new ArrayList<String>();
        if (params != null) {
            for (Map.Entry<String, Object> entry : params.entrySet()) {
                if (entry.getValue() != null) {
                    paramValueList.add(entry.getKey() +"="+ entry.getValue());
                }
            }
        }
        Collections.sort(paramValueList);

        StringBuilder valueToDigest = new StringBuilder();
        valueToDigest.append(timestamp);
        valueToDigest.append('\n');
        valueToDigest.append(urlPath);
        valueToDigest.append('\n');


        for (int i = 0; i < paramValueList.size(); i++) {
            if(i > 0){
                valueToDigest.append("&");
            }
            valueToDigest.append(paramValueList.get(i));
        }

        String charset = "UTF-8";

        return new String(Hex.encodeHex(
                HmacUtils.hmacSha1(secretKey.getBytes(charset), valueToDigest.toString().getBytes(charset)), false));
    }

好了,至此为止,API提供方没有提供其他的任何说明了:

问题是:

我的入参,形如device-a该以什么方式入参?没有说明。

如果我有多个入参,是否有变化?没有说明。

如果没有入参,返回值是什么。没有说明。

 

然后开始漫漫连调路。先写了一个大致如下的计算signature和形成header的方法

   @Override
    public List<Map> readAPI(Map<String, Object> inputparam) {
        long time1 = System.currentTimeMillis();
        String timestamp = String.valueOf(time1);
        String signature = "";


        List<BasicNameValuePair> content = new ArrayList<>();
        for (String key : inputparam.keySet()) {
            content.add(new BasicNameValuePair(key, inputparam.get(key).toString()));
        }

        try {
            signature = this.signatureWithParamsAndUrlPath( this.path, inputparam ,this.key ,time1);
        }
        catch (Exception e)
        {e.printStackTrace();}

        List<BasicHeader> headers = new ArrayList<>();
        headers.add(new BasicHeader("Id", this.id));
        headers.add(new BasicHeader("Timestamp", timestamp));
        headers.add(new BasicHeader("Signature", signature));
        headers.add(new BasicHeader("content-type", "application/x-www-form-urlencoded"));

        return requestAPI(headers, content);
    }

并写了一个 HTTP API请求的方法(该方法已经是正确的方法了)

 private List<Map> requestIpam(List<BasicHeader> headers,List<BasicNameValuePair> content ) {
        HttpURLConnection connection = null;
        BufferedReader reader = null;
        String line = null;
        List<Map> result = new ArrayList<>();
        String json_read = "";
        String content_read = "";

        for (int i = 0; i < content.size(); i++) {
            if(i > 0){
                content_read += ("&");
            }
            content_read += (content.get(i));
        }

        try {
            for (int i = 0; i <= 3; i++) {
                URL url = new URL(this.host+this.path+"?"+content_read);

                connection = (HttpURLConnection) url.openConnection();
                connection.setDoOutput(true);
                connection.setDoInput(true);
                connection.setRequestMethod("POST");
                connection.setRequestProperty("accept", "*/*");
                connection.setRequestProperty("connection", "Keep-Alive");
                connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
                for (BasicHeader header:headers){
                    connection.setRequestProperty(header.getName(),header.getValue());
                }
                connection.connect();// 建立TCP连接


                if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {


                    // 获取URLConnection对象对应的输出流
                    reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));// 发送http请求

                    // 循环读取流
                    while ((line = reader.readLine()) != null) {
                        json_read += line;// "\n"
                    }
                    logger.info("result"+json_read.toString());

                   } else {
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            connection.disconnect();
        }
        return result;
    }

然后说说是怎么一路被坑的吧:

首先:按API提供的同学的说法,需要把URLPATH拼到signature里面,好,我问拼的是

1.https://blog.csdn.net/guotch/article/details/95308055?not_checkout=1还是

2.blog.csdn.net/guotch/article/details/95308055?not_checkout=1还是

3.guotch/article/details/95308055?not_checkout=1

4.guotch/article/details/95308055

老哥一会一改口,一会是方案4,一会儿是方案1。

过了没多久又给我一个参考代码,一看,居然是方案5!

https://blog.csdn.net/guotch/article/details/95308055?params=[not_checkout=1]

然后开始改POST路径,我说老哥你这个not_checkout=1到底是怎么传进API的?

老哥说就是按content传。于是我写了一个out.write(param) 向OutputStreamWriter里面写,还是不对。

又是一顿改,老哥说你直接在url里面用问号拼起来就行。结果还是不行,终于无法忍受,当面找到老哥坐在一起调测

老哥一顿debug,哦给错了,其实前面那个signature是方案4。

终于花了一天的时间把API给调通了。

 

https://blog.csdn.net/java173842219/article/details/54020168

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值