使用Access Token调用API

参考本文使用生成的Access Token调用API。

开始前准备

  • 调用前需准备参数 appKeyappSecretaccessToken、以及 timestamp

步骤

构造 paramsData

  1. 将所有的已获取的参数名进行ASCII码升序排序。
  2. 将排序后的参数名带上参数值进行拼接,具体可参考下文示例。
  3. 如果存在请求body,则将拼接后字符串再加上请求body生成 paramsData

注解

加入签名的请求body必须与发送请求的body保持一致,否则会导致校验失败。

构造 apim-sign

  1. 依次将 accessTokenparamsDatatimestampappSecret 拼接成字符串生成 signData
  2. 使用 SHA256 算法加密 signData 生成预密文。
  3. 将预密文转成小写字母生成 apim-sign,伪代码如下:
sha256(signData).toLowerCase();

错误码

代码 描述
0 SUCCESS
1001 重复请求,使用了相同的 encryption
1002 appKey 不存在
1003 encryption 不合法
1004 参数不合法
1005 内部服务异常
1202 参数非空
1203 Access Token已过期
1204 刷新Access Token失败

示例

以下示例展示使用Access Token调用一个API接口的方法。

请求URL

https://{apigw-address}/m/v1/b?k3=v3&k1=v1&k2=v2

请求Body

{
  "count": 20,
  "page": 1,
  "desc": "描述"
}

请求参数

参数
accessToken xxxxaaaxxxx
appSecret xxxappSecretxxx
timestamp 1572574909697

请求步骤

通过以下步骤,完成API调用:

  1. 将k3、k1、k2按ASCII码升序排列成为k1、k2、k3。

  2. 依次将k1v1、k2v2、k3v3拼接成字符串k1v1k2v2k3v3。

  3. 依次拼接 k1v1k2v2k3v3 和请求Body成为如下字符串:

    k1v1k2v2k3v3{
    "count": 20,
    "page": 1,
    "desc": "描述"
    }
    
  4. 依次将 accessTokenparamsDatatimestampappSecret 拼接成如下字符串:

    xxxxaaaxxxxk1v1k2v2k3v3{
    "count": 20,
    "page": 1,
    "desc": "描述"
    }1572574909697xxxappSecretxxx
    
  5. 将第4步的字符串使用 SHA256 加密并用小写字母表示,结果为:

    59828328f6c1f9771015dc74e4929ae30f518a35a3d2353972c2ea46556fc981
    
  6. 发送请求:

    curl https://{apigw-address}/m/v1/b?k3=v3&k1=v1&k2=v2 -X POST
    -H 'apim-accesstoken:xxxxaaaxxxx'
    -H 'apim-signature:59828328f6c1f9771015dc74e4929ae30f518a35a3d2353972c2ea46556fc981'
    -H 'apim-timestamp:1572574909697'
    -d '{
    "count": 20,
    "page": 1,
    "desc": "描述"
    }'
    

Java 调用示例

import okhttp3.*;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author lixiangxin
 * @date 2019/10/24 18:56
 **/
public class EncryptUtils {

    /**
     * 利用Java原生的类实现SHA256加密
     *
     * @param str 加密后的参数
     * @return
     */
    public static String getSHA256(String str) {
        MessageDigest messageDigest;
        String encodestr = "";
        try {
            messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.update(str.getBytes(StandardCharsets.UTF_8));
            encodestr = hexString(messageDigest.digest());
        } catch (NoSuchAlgorithmException e) {
            return encodestr;
        }

        return encodestr;
    }

    private static String hexString(byte[] b) {
        StringBuilder hs = new StringBuilder();
        String stmp;
        for (int n = 0; b != null && n < b.length; n++) {
            stmp = Integer.toHexString(b[n] & 0XFF);
            if (stmp.length() == 1) {
                hs.append('0');
            }
            hs.append(stmp);
        }
        return hs.toString();
    }

    public static void main(String[] args) throws IOException {

        String accssToken = "xxxxaaaxxxx";
        String appSecret = "xxxappSecretxxx";
        long timestamp = 1572574909697L;//System.currentTimeMillis();

        String url = "https://{apigw-address}/m/v1/b?k3=v3&k1=v1&k2=v2";
        String requestBody = "{\n" +
                "  \"count\": 20,\n" +
                "  \"page\": 1,\n" +
                "  \"desc\": \"描述\"\n" +
                "}";

        HttpUrl httpUrl = HttpUrl.parse(url);
        if (httpUrl == null) {
            return;
        }

        List<String> keys = new ArrayList<>(httpUrl.queryParameterNames());
        Collections.sort(keys);

        StringBuilder paramsData = new StringBuilder();
        for (String key : keys) {
            String value = httpUrl.queryParameter(key);
            paramsData.append(key).append(value);
        }
        paramsData.append(requestBody);
        String signData = accssToken + paramsData.toString() + timestamp + appSecret;
        String apimSign = getSHA256(signData);

        RequestBody body = FormBody
                .create(MediaType.parse("application/json; charset=utf-8"), requestBody);

        Request request = new Request.Builder().url(url).method("POST", body)
                .addHeader("apim-accesstoken", accssToken)
                .addHeader("apim-signature", apimSign)
                .addHeader("apim-timestamp", timestamp + "")
                .build();

        String res = new OkHttpClient().newCall(request).execute().body().string();
        System.out.println(res);
    }
}