package com.nuvole.hnnx.hnnxPay;
|
|
import com.csii.sg.codec.Hex;
|
import org.springframework.util.Assert;
|
|
import javax.crypto.Mac;
|
import javax.crypto.spec.SecretKeySpec;
|
import java.io.UnsupportedEncodingException;
|
import java.nio.charset.StandardCharsets;
|
import java.security.PrivateKey;
|
import java.security.Signature;
|
import java.util.*;
|
|
/**
|
* @author awlwen
|
* @since 2017/11/30
|
*/
|
public class SignatureSigner {
|
/**
|
* 将字节数组转换为16进制字符串
|
* 算法:
|
* 将字节数组中每个字节取出后转换为16进制,截取低八位
|
* 将不足2位的字符前补0,解析时可按2位分隔
|
*
|
* @param byteArray 字节数组
|
* @return 16进制字符
|
*/
|
private String byteToHex(byte[] byteArray) {
|
if (byteArray == null) {
|
return "";
|
}
|
StringBuffer sb = new StringBuffer();
|
for (int i = 0; i < byteArray.length; i++) {
|
String hexString = Integer.toHexString(byteArray[i] & 0x00ff);
|
if (hexString.length() != 2) {
|
//如果字符长度不为2位,前补0占位
|
sb.append("0");
|
}
|
sb.append(hexString);
|
}
|
return sb.toString();
|
}
|
|
private static byte[] signLow(String plain, String algorithm, PrivateKey privateKey) {
|
Assert.notNull(plain, "plain is null.");
|
Assert.notNull(algorithm, "algorithm is null.");
|
Assert.notNull(privateKey, "private key is null.");
|
try {
|
Signature sign = Signature.getInstance(algorithm);
|
sign.initSign(privateKey);
|
sign.update(plain.getBytes());
|
return sign.sign();
|
} catch (Exception ex) {
|
throw new RuntimeException(ex);
|
}
|
}
|
|
private static byte[] signLowByte(byte[] plain, String algorithm, PrivateKey privateKey) {
|
Assert.notNull(plain, "plain is null.");
|
Assert.notNull(algorithm, "algorithm is null.");
|
Assert.notNull(privateKey, "private key is null.");
|
try {
|
Signature sign = Signature.getInstance(algorithm);
|
sign.initSign(privateKey);
|
sign.update(plain);
|
return sign.sign();
|
} catch (Exception ex) {
|
throw new RuntimeException(ex);
|
}
|
}
|
|
public static String laBaSign(Map<String, String> parameters, String accessKeySecret) {
|
// Step 1: Sort the parameters by key in ascending order
|
List<Map.Entry<String, String>> sortedParams = new ArrayList<>(parameters.entrySet());
|
Collections.sort(sortedParams, Comparator.comparing(Map.Entry::getKey));
|
|
// Step 2: Generate the string to sign
|
StringBuilder stringToSign = new StringBuilder();
|
for (Map.Entry<String, String> param : sortedParams) {
|
if (param.getValue() != null && !param.getValue().isEmpty()) {
|
stringToSign.append(param.getKey()).append("=").append(param.getValue()).append("&");
|
}
|
}
|
stringToSign.deleteCharAt(stringToSign.length() - 1); // Remove the last '&'
|
|
// Step 3: Generate the signature
|
try {
|
Mac hmacSha256 = Mac.getInstance("HmacSHA256");
|
SecretKeySpec keySpec = new SecretKeySpec(accessKeySecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
|
hmacSha256.init(keySpec);
|
byte[] signData = hmacSha256.doFinal(stringToSign.toString().getBytes(StandardCharsets.UTF_8));
|
|
// Step 4: Base64 encode the signature
|
return Base64.getEncoder().encodeToString(signData);
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
|
return null;
|
}
|
/**
|
* 使用提供的算法与私钥对交易数据签名
|
*
|
* @param plain 交易数据明文
|
* @param privateKey java.security.PrivateKey 私钥
|
* @return 签名
|
*/
|
public String sign(String plain, PrivateKey privateKey) {
|
byte[] bytes = signLow(plain, HnnxConstant.ALGORITHM, privateKey);
|
return Hex.toHex(bytes);
|
}
|
|
/**
|
* 快捷支付sign
|
*
|
* @param plain
|
* @param privateKey
|
* @return
|
*/
|
public String kjSign(String plain, PrivateKey privateKey) {
|
byte[] bytes = new byte[0];
|
try {
|
bytes = signLowByte(plain.getBytes("utf-8"), HnnxConstant.KJ_ALGORITHM, privateKey);
|
} catch (UnsupportedEncodingException e) {
|
e.printStackTrace();
|
}
|
return Base64.getEncoder().encodeToString(bytes);
|
}
|
|
}
|