3. para-hmac-auth签名算法
获取 Body 字节数组,采用 Base64 编码得到 Content。
2.签名字段
“X-App-Id”、“X-Sequence-No”、“X- Timestamp”和“Body”作为签名字段,“Body” 的值为上一步生成的Content。
3.排序
按照 ASCII 递增排序(字母升序排序),如果第一位一样,则按照第二位,以此类推。
4.生成待签名字符串
过滤掉空值(null或空字符)的key,将排序后的参数与值组合成“参数=参数值”的格式,并且把这些参数用&字符连接起来,最后拼接“&”和APP密钥,生成待签名字符串。示例值如下:
Post:
Body=dGVzdHQ=&X-App-Id=100001&X-Sequence-No=2020010916354525600001&X-Timestamp=20200109163545256&47d57ce4266c187ea60d66279b152c4b
Get:
X-App-Id=100001&X-Sequence-No=2020010916354525600001&X- Timestamp=20200109163545256&47d57ce4266c187ea60d66279b152c4b
获取待签名字符串字节数组,用SHA256生成摘要值,并进行Base64编码,得到签名字串。
签名算法说明:
Base64(
SHA256(
Body=Base64({X-App-Id}&
X-Sequence-No={X-Timestamp}&
${AppSecret}
)
)
Base64(
SHA256(
X-App-Id={X-Sequence-No}&
X-Timestamp={AppSecret}
)
)
package com.nanxing;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.Map;
import java.util.TreeMap;
public class SignTest {
public static void main(String[] args) throws NoSuchAlgorithmException {
String appId = "EX1001";
String appKey = "dafsfdsfasdfa";
TreeMap<String,String> headerMap = new TreeMap<>();
//获得时间戳
String timestamp = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
//生成流水号
String sequenceNo = timestamp + ((int)((Math.random()*9+1)*10000));
headerMap.put("X-Timestamp", timestamp);
headerMap.put("X-Sequence-No", sequenceNo);
headerMap.put("X-App-Id", appId);
String body = "{\n" +
"\"context\": {\n" +
"\"CultureName\": \"zh-CN\", \n" +
"\"EntCode\": \"0819\", \n" +
"\"OrgCode\": \"100\", \n" +
"\"UserCode\": \"admin\" \n" +
"}, \n" +
"\"bomItem\": \"10101.00001\" \n" +
"}";
if (StringUtils.isNotEmpty(body)){
headerMap.put("Body", Base64.getEncoder().encodeToString(body.getBytes()));
}
String sign = sign(headerMap,appKey );
headerMap.put( "X-Signature", sign);
headerMap.remove("Body");
String url = "http://api-test.nanxing.com/erp/qryBomCompentService";
HttpResponse response = HttpUtil.createPost(url).addHeaders(headerMap).body(body).execute();
System.out.println(response.body());
}
/**
*
* @param signMap
* @param macKey 秘钥
* @return
* @throws NoSuchAlgorithmException
*/
public static String sign(TreeMap<String, String> signMap, String macKey) throws NoSuchAlgorithmException {
if (MapUtils.isEmpty(signMap)){
return "";
}
//签名
String sha256 = sha256(generateSignString(signMap, macKey));
System.out.println(sha256);
return sha256;
}
/**
* sha256加密
* @param data 待加密数据
* @return
* @throws NoSuchAlgorithmException
*/
public static String sha256(String data) throws NoSuchAlgorithmException {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
byte[] digest = messageDigest.digest(data.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(digest);
}
public static String generateSignString(TreeMap<String, String> signMap, String macKey) {
if (MapUtils.isEmpty(signMap)){
return "";
}
StringBuilder signStrBuilder = new StringBuilder();
for (Map.Entry<String, String> entry : signMap.entrySet()){
//过滤空值
if (StringUtils.isEmpty(entry.getValue())){
continue;
}
//拼接签名字段
signStrBuilder.append(entry.getKey())
.append("=")
.append(entry.getValue())
.append("&");
}
String sign = signStrBuilder.append(macKey).toString();
return sign;
}
}
修改于 2024-04-21 01:42:05