123 lines
4.2 KiB
Java
123 lines
4.2 KiB
Java
package com.example.caseData.extend.app;
|
||
|
||
import cn.hutool.http.HttpRequest;
|
||
import cn.hutool.http.HttpResponse;
|
||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||
import lombok.extern.slf4j.Slf4j;
|
||
|
||
import javax.crypto.Mac;
|
||
import javax.crypto.spec.SecretKeySpec;
|
||
import java.nio.charset.StandardCharsets;
|
||
import java.util.Map;
|
||
import java.util.*;
|
||
|
||
@Slf4j
|
||
public class Base {
|
||
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||
|
||
/**
|
||
* 生成签名
|
||
* @param params 需要签名的参数(支持嵌套 Map)
|
||
* @param secretKey 密钥
|
||
* @return 签名字符串
|
||
*/
|
||
public static String genSignature(Map<String, Object> params, String secretKey) {
|
||
try {
|
||
// Step 1: 对 Map 进行递归排序
|
||
Map<String, Object> sortedMap = sortMapRecursively(params);
|
||
|
||
// Step 2: 转为 JSON 字符串
|
||
String json = objectMapper.writeValueAsString(sortedMap);
|
||
|
||
// Step 3: 使用 HMAC-SHA256 签名
|
||
return hmacSha256(json, secretKey);
|
||
} catch (JsonProcessingException e) {
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 对 Map<String, Object> 进行递归排序(key 排序),支持嵌套 Map 和 List
|
||
*/
|
||
public static Map<String, Object> sortMapRecursively(Map<String, Object> data) {
|
||
Map<String, Object> sortedMap = new TreeMap<>(); // TreeMap 会自动按 key 排序
|
||
|
||
for (Map.Entry<String, Object> entry : data.entrySet()) {
|
||
String key = entry.getKey();
|
||
Object value = entry.getValue();
|
||
|
||
if (value instanceof Map) {
|
||
// 如果是嵌套 map,递归排序
|
||
@SuppressWarnings("unchecked")
|
||
Map<String, Object> nestedMap = (Map<String, Object>) value;
|
||
sortedMap.put(key, sortMapRecursively(nestedMap));
|
||
} else if (value instanceof List) {
|
||
// 如果是列表,检查每一项是否是 map,如果是则排序
|
||
@SuppressWarnings("unchecked")
|
||
List<Object> list = (List<Object>) value;
|
||
List<Object> sortedList = new ArrayList<>();
|
||
for (Object item : list) {
|
||
if (item instanceof Map) {
|
||
@SuppressWarnings("unchecked")
|
||
Map<String, Object> nestedItemMap = (Map<String, Object>) item;
|
||
sortedList.add(sortMapRecursively(nestedItemMap));
|
||
} else {
|
||
sortedList.add(item);
|
||
}
|
||
}
|
||
sortedMap.put(key, sortedList);
|
||
} else {
|
||
// 普通字段,直接插入
|
||
sortedMap.put(key, value);
|
||
}
|
||
}
|
||
|
||
return sortedMap;
|
||
}
|
||
|
||
/**
|
||
* HMAC-SHA256 加密
|
||
*/
|
||
private static String hmacSha256(String data, String key) {
|
||
try {
|
||
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
|
||
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
|
||
sha256_HMAC.init(secretKeySpec);
|
||
byte[] result = sha256_HMAC.doFinal(data.getBytes(StandardCharsets.UTF_8));
|
||
|
||
// 转为 16 进制字符串
|
||
StringBuilder hexString = new StringBuilder();
|
||
for (byte b : result) {
|
||
String hex = Integer.toHexString(0xff & b);
|
||
if (hex.length() == 1) hexString.append('0');
|
||
hexString.append(hex);
|
||
}
|
||
return hexString.toString();
|
||
} catch (Exception e) {
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 发送 POST JSON 请求
|
||
* @param url 请求地址
|
||
* @param jsonData JSON 字符串
|
||
* @param headers 请求头
|
||
* @return 响应字符串
|
||
*/
|
||
public String postJson(String url, String jsonData, Map<String, String> headers) {
|
||
HttpRequest request = HttpRequest.post(url)
|
||
.body(jsonData)
|
||
.header("Content-Type", "application/json");
|
||
|
||
if (headers != null) {
|
||
headers.forEach(request::header);
|
||
}
|
||
|
||
try (HttpResponse response = request.execute()) {
|
||
return response.body();
|
||
}
|
||
}
|
||
}
|