Administrator
2024-02-26 b5b296cc01699f96029b07073fe9d0078bedd445
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
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 + "\"";
    }
}