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 + "\"";
|
}
|
}
|