jiangqs
2023-06-19 cd8d65c1e5378bddded25cad300f34024ba136ba
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package com.ruoyi.shop.util;
 
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.shop.util.dto.CertificateItem;
import com.ruoyi.shop.util.dto.EncryptedCertificateItem;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
 
/**
 * @date 2020-03-18 15:06
 * @description
 */
@Slf4j
public class Certificate {
 
    private static final Logger logger = LoggerFactory.getLogger(Certificate.class);
 
    /**
     * 获取微信支付平台证书
     *
     * @param merchantId
     * @param timeout
     * @param serialNo
     * @param mchPrivateKeyPath
     * @param APIv3Key
     * @param savePath
     * @return
     */
    public static List<X509Certificate> getCertByAPI(String merchantId, int timeout, String serialNo, String mchPrivateKeyPath, String wechatPubKeyPath, String APIv3Key, String savePath) {
        String result = "";
        //创建http请求
        HttpGet httpGet = new HttpGet("https://api.mch.weixin.qq.com/v3/certificates");
        httpGet.addHeader("Content-Type", "application/json");
        httpGet.addHeader("Accept", "application/json");
 
        String authorization = SignUtils.authorization("GET", "/v3/certificates", merchantId, serialNo, "", mchPrivateKeyPath);
 
        //设置认证信息
        httpGet.setHeader("Authorization", authorization);
 
        //设置请求器配置:如超时限制等
        RequestConfig config = RequestConfig.custom().setSocketTimeout(timeout * 1000).setConnectTimeout(timeout * 1000).build();
        httpGet.setConfig(config);
        List<X509Certificate> x509Certs = new ArrayList<X509Certificate>();
        try {
            CloseableHttpClient httpClient = HttpClients.createDefault();
            CloseableHttpResponse response = httpClient.execute(httpGet);
            int statusCode = response.getStatusLine().getStatusCode();
            HttpEntity httpEntity = response.getEntity();
            result = EntityUtils.toString(httpEntity, "UTF-8");
            if (statusCode == 200) {
                logger.info("下载平台证书返回结果:" + result);
                Header[] timestampHeader = response.getHeaders("Wechatpay-Timestamp");
                Header[] nonceHeader = response.getHeaders("Wechatpay-Nonce");
                Header[] signatureHeader = response.getHeaders("Wechatpay-Signature");
                if (timestampHeader != null && timestampHeader.length > 0 &&
                        nonceHeader != null && nonceHeader.length > 0 &&
                        signatureHeader != null && signatureHeader.length > 0) {
                    // 验证微信支付返回签名
                    String wTimestamp = timestampHeader[0].getValue();
                    String wNonce = nonceHeader[0].getValue();
                    String wSign = signatureHeader[0].getValue();
 
                    logger.info("wTimestamp:{},wNonce:{},wSign:{}", wTimestamp, wNonce, wSign);
                    // 拼装待签名串
                    StringBuffer ss = new StringBuffer();
                    ss.append(wTimestamp).append("\n");
                    ss.append(wNonce).append("\n");
                    ss.append(result).append("\n");
                    // 验证签名
                    if (SignUtils.v3VerifyRSA(ss.toString(), Base64.decodeBase64(wSign.getBytes()), wechatPubKeyPath)) {
                        List<CertificateItem> certList = new ArrayList<CertificateItem>();
                        JSONObject json = JSONObject.parseObject(result);
                        logger.info("查询结果json字符串转证书List:" + json.get("data"));
                        JSONArray jsonArray = (JSONArray) json.get("data");
                        for (int i = 0; i < jsonArray.size(); i++) {
                            CertificateItem certificateItem = new CertificateItem();
                            EncryptedCertificateItem encryptCertificate = new EncryptedCertificateItem();
                            JSONObject bo = JSONObject.parseObject(jsonArray.get(i).toString());
                            certificateItem.setSerial_no(bo.get("serial_no").toString());
                            certificateItem.setEffective_time(bo.get("effective_time").toString());
                            certificateItem.setExpire_time(bo.get("expire_time").toString());
                            JSONObject encryptBo = JSONObject.parseObject(bo.get("encrypt_certificate").toString());
                            encryptCertificate.setAlgorithm(encryptBo.get("algorithm").toString());
                            encryptCertificate.setNonce(encryptBo.get("nonce").toString());
                            encryptCertificate.setAssociated_data(encryptBo.get("associated_data").toString());
                            encryptCertificate.setCiphertext(encryptBo.get("ciphertext").toString());
                            certificateItem.setEncrypt_certificate(encryptCertificate);
                            certList.add(certificateItem);
                        }
                        logger.info("证书List:" + certList);
 
                        /*List<PlainCertificateItem> plainList = decrypt(certList, APIv3Key);
                        if (CollectionUtils.isNotEmpty(plainList)) {
                            logger.info("平台证书开始保存");
                            x509Certs = saveCertificate(plainList, savePath);
                        }*/
                    }
                }
            }
            response.close();
            httpClient.close(); //throw
            return x509Certs;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("下载平台证书返回结果:" + e);
        }
        return x509Certs;
    }
 
 
    /*private static List<PlainCertificateItem> decrypt(List<CertificateItem> certList,CloseableHttpResponse response) throws GeneralSecurityException, IOException {
        List<PlainCertificateItem> plainCertificateList = new ArrayList<PlainCertificateItem>();
        AesUtil aesUtil = new AesUtil("".getBytes(StandardCharsets.UTF_8));
        for(CertificateItem item:certList){
            PlainCertificateItem bo = new PlainCertificateItem();
            bo.setSerialNo(item.getSerial_no());
            bo.setEffectiveTime(item.getEffective_time());
            bo.setExpireTime(item.getExpire_time());
            logger.info("平台证书密文解密");
            bo.setPlainCertificate(aesUtil.decryptToString(item.getEncrypt_certificate().getAssociated_data().getBytes(StandardCharsets.UTF_8),
                    item.getEncrypt_certificate().getNonce().getBytes(StandardCharsets.UTF_8), item.getEncrypt_certificate().getCiphertext()));
            logger.info("平台证书公钥明文:"+bo.getPlainCertificate());
            plainCertificateList.add(bo);
        }
        return plainCertificateList;
    }*/
 
 
    //证书保存
    /*private static List<X509Certificate> saveCertificate(List<PlainCertificateItem> cert) throws IOException {
        List<X509Certificate> x509Certs = new ArrayList<X509Certificate>();
        File file = new File("平台证书路径");
        file.mkdirs();
        for (PlainCertificateItem item : cert) {
            ByteArrayInputStream inputStream = new ByteArrayInputStream(item.getPlainCertificate().getBytes(StandardCharsets.UTF_8));
            X509Certificate x509Cert = PemUtil.loadCertificate(inputStream);
            x509Certs.add(x509Cert);
            String outputAbsoluteFilename = file.getAbsolutePath() + File.separator + "wechatpay_" + item.getSerialNo() + ".pem";
            try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputAbsoluteFilename), StandardCharsets.UTF_8))) {
                writer.write(item.getPlainCertificate());
            }
            logger.info("输出证书文件目录:" + outputAbsoluteFilename);
        }
        return x509Certs;
    }*/
}