java
package com.dataxai.web.core.config;
import com.alibaba.fastjson2.JSON;
import com.dataxai.web.domain.Wxpay;
import com.dataxai.web.mapper.WxpayMapper;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.*;
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.beans.factory.annotation.Autowired;
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 org.springframework.core.io.ClassPathResource;
import javax.annotation.PostConstruct;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
@Configuration
@Data //使用set方法将wxpay节点中的值填充到当前类的属性中
@Slf4j
public class WxPayConfig {
// 商户号
private String mchId;
// 商户API证书序列号
private String mchSerialNo;
// 商户私钥文件
private String privateKeyPath;
// APIv3密钥
private String apiV3Key;
// APPID
private String appid;
// 微信服务器地址
private String domain;
// 接收结果通知地址
private String notifyDomain;
// 接收结果通知地址
private String notifyDomainProd;
// APIv2密钥
private String partnerKey;
@Autowired
private WxpayMapper configMapper;
@PostConstruct
public void init() {
log.info("初始化微信支付配置...");
//从数据库获得配置信息
Wxpay dbConfig = configMapper.getOne(1l);
if (dbConfig != null) {
this.mchId = dbConfig.getMchId();
this.mchSerialNo = dbConfig.getMchSerialNo();
this.privateKeyPath = dbConfig.getPrivateKeyPath(); // 设置私钥路径
this.apiV3Key = dbConfig.getApiV3Key();
this.appid = dbConfig.getAppId();
this.domain = dbConfig.getDomain();
this.notifyDomain = dbConfig.getNotifyDomain();
this.notifyDomainProd = dbConfig.getNotifyDomainProd();
this.partnerKey = dbConfig.getPartnerKey();
log.info("微信支付配置已成功初始化: {}", JSON.toJSONString(dbConfig));
} else {
throw new IllegalStateException("未找到微信支付配置");
}
}
/**
* 获取商户的私钥文件
* @param filename
* @return
*/
private PrivateKey getPrivateKey(String filename) {
System.out.println("filename = "+filename);
filename = "/config/"+filename;
ClassPathResource resource = new ClassPathResource(filename);
InputStream inputStream = null;
try {
inputStream = resource.getInputStream();
return PemUtil.loadPrivateKey(inputStream);
} catch (IOException 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;
}
}
mapper层和controller层省略