import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.type.TypeReference;
public class TestSignature {
private static Map<String, Object> replaceHashMapsWithTreeMaps(Map<String, Object> map) {
Map<String, Object> treeMap = new TreeMap<>(map);
for (Map.Entry<String, Object> entry : treeMap.entrySet()) {
if (entry.getValue() instanceof Map) {
entry.setValue(replaceHashMapsWithTreeMaps((Map<String, Object>) entry.getValue()));
} else if (entry.getValue() instanceof List) {
entry.setValue(processList((List) entry.getValue()));
}
}
return treeMap;
}
private static List processList(List list) {
List newList = new ArrayList();
for (Object item : list) {
if (item instanceof Map) {
newList.add(replaceHashMapsWithTreeMaps((Map<String, Object>) item));
} else if (item instanceof List) {
newList.add(processList((List) item));
} else {
newList.add(item);
}
}
return newList;
}
public static Map<String, Object> generateSignature(String apiSecret, String apiKey, String method, String requestPath, Object body) {
// 生成时间戳 (RFC3339Nano格式)
String timestamp = Instant.now().toString();
// 准备签名消息
method = method.toUpperCase().trim();
requestPath = requestPath.trim();
StringBuilder message = new StringBuilder()
.append(timestamp)
.append(method)
.append(requestPath);
// 如果有请求体,需要处理
if (body != null) {
try {
if (body instanceof String) {
message.append(((String) body).trim());
} else {
// 如果是对象,转换为排序后的JSON字符串
ObjectMapper mapper = new ObjectMapper();
String jsonStr = mapper.writeValueAsString(body);
Map<String, Object> jsonMap = mapper.readValue(jsonStr, new TypeReference<Map<String, Object>>() {});
Map<String, Object> sortedMap = replaceHashMapsWithTreeMaps(jsonMap);
message.append(mapper.writeValueAsString(sortedMap));
}
} catch (Exception e) {
throw new RuntimeException("Failed to process body", e);
}
}
try {
// 使用HMAC-SHA256算法生成签名
Mac hmac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKey = new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
hmac.init(secretKey);
byte[] hash = hmac.doFinal(message.toString().getBytes(StandardCharsets.UTF_8));
String signature = Base64.getEncoder().encodeToString(hash);
// 构建返回结果
Map<String, Object> result = new HashMap<>();
result.put("signature", signature);
result.put("timestamp", timestamp);
Map<String, String> headers = new HashMap<>();
headers.put("AVE-ACCESS-SIGN", signature);
headers.put("AVE-ACCESS-TIMESTAMP", timestamp);
headers.put("AVE-ACCESS-KEY", apiKey);
result.put("headers", headers);
Map<String, String> debug = new HashMap<>();
debug.put("message", message.toString());
debug.put("method", method);
debug.put("request_path", requestPath);
result.put("debug", debug);
return result;
} catch (Exception e) {
throw new RuntimeException("Failed to generate signature", e);
}
}
}