# Sign方式v4(非对称加密)

需要申请对应环境的appKeyappSecret

测试域名:https://openapi-test.babycare.com/api/gateway

正式域名:https://gateway.babycare.com

# 1、请求的公共参数(Header)

名称 类型 必填 描述
appKey String 请求应用编码
signRequestId String 请求号(一个随机编码),参与签名
signRequestTime String 请求时间戳(单位:秒),参与签名
signVersion String 4.0 , 参与签名
sign String 签名

签名参数是放在header头部中的,不能在url参数拼接或者放在body体中

# 2、签名算法

# 签名⽣成的通⽤步骤如下:

# 第一步:

将所有⾮空请求参数(包括Header中参与签名参数,Body参数,QueryString参数),按照参数名ASCII码从⼩到⼤排序(字典序),使 ⽤URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。

# 注意事项:

1、参数名ASCII码从⼩到⼤排序(字典顺序)

2、如果参数的值为空不参与签名;

3、参数名区分⼤⼩写;

# 第⼆步:

在stringA最后拼接上key=appSecret得到stringSignTemp字符串,并对stringSignTemp进⾏MD5运算,再将得到的字符串所有字符转 换为⼤写,得到sign值signValue。

# Java代码示例

    public static void main(String[] args) {
          //访问appKey
          String appKey = "需要申请";
          //访问appSecret
          String appSecret = "需要申请";
          //版本号
          String signVersion = "4.0";
          //网关地址
          String gatewayUrl = "网关地址";
          // 构造参数使用treeMap保证构建sign字符串时有序
          Map<String, Object> params = Maps.newTreeMap();
          // 基础参数 用户加密
          String signRequestId = UUID.randomUUID().toString();
          long signRequestTime = System.currentTimeMillis() / 1000;
          //加密参数
          params.put("signVersion", signVersion);
          params.put("signRequestId", signRequestId);
          params.put("signRequestTime", signRequestTime);
          //不管是body中的参数,还是url拼接的参数都要参与签名
         //要放到boody的参数
          Map<String,Object> bodyParam = Maps.newHashMap();
          bodyParam.put("name","zhangsan");
          bodyParam.put("age",12);
          params.putAll(bodyParam);
          //要放到url做拼接的参数
          Map<String,Object> urlParam = Maps.newHashMap();
          urlParam.put("id",12);
          params.putAll(urlParam);
          String sign = sign(appSecret, params);
          HttpHeaders headers = setHeaders(appKey, signVersion, signRequestId, signRequestTime, sign);
  
          RestTemplate restTemplate = new RestTemplate();
          HttpEntity<JSONObject> request = new HttpEntity<JSONObject>(JSONObject.toJSONString(bodyParam), headers);

          // /test03/aaa/bbb 为应用接口访问地址(包含路由)
          // 案例是post请求,get请求修改类型,并传参数用url拼接的方式
          ResponseEntity<Object> entity = restTemplate.exchange
                  (gatewayUrl + "/test03/aaa/bbb?id=12", HttpMethod.POST, request, Object.class);
          System.out.println(entity.getBody());
      }
  
      /**
       * 加密
       * @param appSecret
       * @param params
       * @return
       */
      private static String sign(String appSecret, Map<String, Object> params) {
          StringBuilder builder = new StringBuilder();
          for (Map.Entry<String, Object> entry : params.entrySet()) {
              if (Objects.isNull(entry.getValue())) {
                    continue;
              }
              builder.append(entry.getKey())
                      .append("=")
                      .append(entry.getValue())
                      .append("&");
          }
          // 将key拼接到字符串末尾
          builder.append("key=").append(appSecret);
          // sign进行加密
          return DigestUtils.md5Hex(builder.toString()).toUpperCase();
      }
  
      /**
       * 设置头部参数
       *
       * @param appKey
       * @param signApiVersion
       * @param signRequestId
       * @param signRequestTime
       * @param sign
       * @return
       */
      private static HttpHeaders setHeaders(String appKey, String signVersion, String signRequestId, long signRequestTime, String sign) {
          HttpHeaders headers = new HttpHeaders();
          headers.set("appKey", appKey);
          headers.set("sign", sign);
          headers.set("signVersion", signVersion);
          headers.set("signRequestId", signRequestId);
          headers.set("signRequestTime", signRequestTime + "");
          headers.setContentType(MediaType.APPLICATION_JSON);
          return headers;
      }