package com.dy.pipirrWebChat.payment; import javax.crypto.NoSuchPaddingException; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.security.*; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; import java.util.Random; /** * @author ZhuBaoMin * @date 2024-02-22 20:31 * @LastEditTime 2024-02-22 20:31 * @Description */ public class PayHelper { private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; /** * 获取32位随机字符串 * @return 随机串 */ public static String generateRandomString() { Random random = new Random(); StringBuilder sb = new StringBuilder(32); for (int i = 0; i < 32; i++) { int index = random.nextInt(CHARACTERS.length()); sb.append(CHARACTERS.charAt(index)); } return sb.toString(); } /** * 获取私钥对象 * @param filename 私钥文件路径 * @return 私钥对象 * @throws IOException */ public static PrivateKey getPrivateKey(String filename) throws IOException { //String filename = "C:\\webchat\\apiclient_key.pem"; String content = new String(Files.readAllBytes(Paths.get(filename)), "utf-8"); try { String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "") .replace("-----END PRIVATE KEY-----", "") .replaceAll("\\s+", ""); KeyFactory kf = KeyFactory.getInstance("RSA"); return kf.generatePrivate( new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey))); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("当前Java环境不支持RSA", e); } catch (InvalidKeySpecException e) { throw new RuntimeException("无效的密钥格式"); } } /** * 构造签名串_下单 * @param method HTTP请求方法 * @param url URL * @param timestamp 时间戳 * @param nonceStr 随机串 * @param body 报文主题 * @return 签名串 */ public static String buildMessage_order(String method, String url, long timestamp, String nonceStr, String body) { return method + "\n" + url + "\n" + timestamp + "\n" + nonceStr + "\n" + body + "\n"; } public static String buildMessage_signAgain(String appid, String timestamp, String nonceStr, String pkg) { return appid + "\n" + timestamp + "\n" + nonceStr + "\n" + pkg + "\n"; } /** * 签名 * @param message 被签名信息 * @param certFileName 私钥证书文件路径 * @return signature签名值,签名信息中的一项,参与生成签名信息 * @throws NoSuchAlgorithmException * @throws InvalidKeyException * @throws SignatureException * @throws IOException */ public static String sign(byte[] message, String certFileName) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, IOException { Signature sign = Signature.getInstance("SHA256withRSA"); sign.initSign(getPrivateKey(certFileName)); sign.update(message); return Base64.getEncoder().encodeToString(sign.sign()); } /** * 获取签名信息 * @param method * @param url * @param body * @return 签名信息,HTTP头中的签名信息 * HTTP头:Authorization: 认证类型 签名信息 * 认证类型,WECHATPAY2-SHA256-RSA2048 */ public static String getToken(String method, String url, String body, String nonceStr, Long timestamp, String certFileName) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException, SignatureException, InvalidKeyException, NoSuchPaddingException { String message = buildMessage_order(method, url, timestamp, nonceStr, body); String signature = sign(message.getBytes("utf-8"), certFileName); return "mchid=\"" + PayInfo.mchid + "\"," + "nonce_str=\"" + nonceStr + "\"," + "timestamp=\"" + timestamp + "\"," + "serial_no=\"" + PayInfo.serial_no + "\"," + "signature=\"" + signature + "\""; } }