package com.dsh.course.util.wx; import org.bouncycastle.jce.provider.BouncyCastleProvider; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.Security; import java.security.Signature; import java.security.spec.PKCS8EncodedKeySpec; import java.util.*; public class WeChatSignUtil { static { Security.addProvider(new BouncyCastleProvider()); } /** * 使用商户私钥对字符串进行 SHA256withRSA 签名 * * @param content 待签名字符串 * @param privateKeyPath 商户私钥文件路径(pem 格式) * @return 签名结果(Base64 编码) */ public static String signWithRSAPrivateKey(String content, String privateKeyPath) throws Exception { String privateKeyPEM = readPemFile(privateKeyPath); String privateKeyContent = privateKeyPEM .replace("-----BEGIN PRIVATE KEY-----", "") .replace("-----END PRIVATE KEY-----", "") .replaceAll("\\s+", ""); byte[] decodedKey = Base64.getDecoder().decode(privateKeyContent); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey); KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC"); PrivateKey privateKey = keyFactory.generatePrivate(keySpec); Signature signature = Signature.getInstance("SHA256withRSA"); signature.initSign(privateKey); signature.update(content.getBytes(StandardCharsets.UTF_8)); return Base64.getEncoder().encodeToString(signature.sign()); } private static String readPemFile(String filePath) throws IOException { StringBuilder sb = new StringBuilder(); try (BufferedReader br = new BufferedReader(new FileReader(filePath))) { String line; while ((line = br.readLine()) != null) { sb.append(line).append("\n"); } } return sb.toString(); } /** * 按照微信 V3 规范生成待签名字符串 */ public static String buildSignMessage(Map map) { List keys = new ArrayList<>(map.keySet()); Collections.sort(keys); StringBuilder sb = new StringBuilder(); for (String key : keys) { Object value = map.get(key); if (value != null && !value.toString().isEmpty()) { sb.append(key).append("=").append(value).append("\n"); } } return sb.toString(); } }