package org.springblade.common.config; import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder; import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner; import com.wechat.pay.contrib.apache.httpclient.auth.ScheduledUpdateCertificatesVerifier; import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials; import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator; import com.wechat.pay.contrib.apache.httpclient.util.PemUtil; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.apache.http.impl.client.CloseableHttpClient; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import java.io.FileInputStream; import java.nio.charset.StandardCharsets; import java.security.PrivateKey; @Configuration @ConfigurationProperties(prefix = "wxpay") //读取wxpay节点 @Data //使用set方法将wxpay节点中的值填充到当前类的属性中 @Slf4j public class WxPayConfig { // 商户号 private String mchId; // 商户API证书序列号 private String mchSerialNo; // 商户私钥文件 private String privateKeyPath; private String privateCertPath; // APIv3密钥 private String apiV3Key; // APPID private String appid; // 微信服务器地址 private String domain; // 接收结果通知地址 private String notifyDomain; // APIv2密钥 private String partnerKey; /** * 获取商户的私钥文件 * * @param filename * @return */ private PrivateKey getPrivateKey(String filename) { try { // FileInputStream fileInputStream = new FileInputStream(filename); // log.info("文件内容:" + fileInputStream); return PemUtil.loadPrivateKey(getFileInputStream(filename)); } catch (Exception e) { log.info("私钥文件不存在", e); throw new RuntimeException("私钥文件不存在", e); } } /** * 获取商户的文件 * * @param filename * @return */ public static FileInputStream getFileInputStream(String filename) { try { FileInputStream fileInputStream = new FileInputStream(filename); return fileInputStream; } catch (Exception e) { log.info("读取文件不存在", e); throw new RuntimeException("读取文件不存在", e); } } /** * 获取商户的文件 * * @return */ // @Bean // public KeyStore keyStore() { // try { // InputStream certStream = WxPayConfig.class.getClassLoader().getResourceAsStream(privateCertPath); // KeyStore ks = KeyStore.getInstance("PKCS12"); // ks.load(certStream, mchId.toCharArray()); // return ks; // } catch (Exception e) { // log.info("读取文件不存在", e); // throw new RuntimeException("读取文件不存在", e); // } // } /** * 获取签名验证器 * * @return */ // @Bean public ScheduledUpdateCertificatesVerifier getVerifier() { log.info("获取签名验证器"); //获取商户私钥 PrivateKey privateKey = getPrivateKey(privateKeyPath); //私钥签名对象 PrivateKeySigner privateKeySigner = new PrivateKeySigner(mchSerialNo, privateKey); //身份认证对象 WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(mchId, privateKeySigner); // 使用定时更新的签名验证器,不需要传入证书 ScheduledUpdateCertificatesVerifier verifier = new ScheduledUpdateCertificatesVerifier( wechatPay2Credentials, apiV3Key.getBytes(StandardCharsets.UTF_8)); return verifier; } /** * 获取http请求对象 * * @param verifier * @return */ // @Bean(name = "wxPayClient") public CloseableHttpClient getWxPayClient(ScheduledUpdateCertificatesVerifier verifier) { log.info("获取httpClient"); //获取商户私钥 PrivateKey privateKey = getPrivateKey(privateKeyPath); WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create() .withMerchant(mchId, mchSerialNo, privateKey) .withValidator(new WechatPay2Validator(verifier)); // ... 接下来,你仍然可以通过builder设置各种参数,来配置你的HttpClient // 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新 CloseableHttpClient httpClient = builder.build(); return httpClient; } /** * 获取HttpClient,无需进行应答签名验证,跳过验签的流程 */ // @Bean(name = "wxPayNoSignClient") public CloseableHttpClient getWxPayNoSignClient() { //获取商户私钥 PrivateKey privateKey = getPrivateKey(privateKeyPath); //用于构造HttpClient WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create() //设置商户信息 .withMerchant(mchId, mchSerialNo, privateKey) //无需进行签名验证、通过withValidator((response) -> true)实现 .withValidator((response) -> true); // 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新 CloseableHttpClient httpClient = builder.build(); log.info("== getWxPayNoSignClient END =="); return httpClient; } }