微信加解密流程,证书作用讲解,官方SDK使用教程
@Component
public class WxApiV3Utils {
public static final String REDIS_KEY_RCHG_PARTNER_PAY_MRCH_CFG = "rchg_partner_pay_mrch_cfg";
private static final Logger logger = LoggerFactory.getLogger(WxApiV3Utils.class);
private static final Map<String, CloseableHttpClient> MERCHANT_ID_HTTP_CLIENT_MAP = new ConcurrentHashMap<>();
/**
* 证书管理器实例
*/
private final CertificatesManager certificatesManager = CertificatesManager.getInstance();
@Autowired
private RedisUtils redisUtils;
public CloseableHttpClient getHttpClient(String merchantId) throws Exception {
// 获取ApiV3配置
WxPayMrchCfg wxPayMrchCfg = getApiV3Cfg(merchantId);
String merchantSerialNumber = wxPayMrchCfg.getCertSerialNo();
String apiV3Key = wxPayMrchCfg.getPartnerKey();
String certPrivateKeyPath = wxPayMrchCfg.getCertPrivateKeyPath();
// 加载商户私钥
PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new FileInputStream(certPrivateKeyPath));
// 获取验签器
Verifier verifier = getVerifier(merchantId, merchantSerialNumber, apiV3Key, merchantPrivateKey);
Optional<CloseableHttpClient> optional = getHttpClient(merchantId, merchantSerialNumber, merchantPrivateKey,
verifier);
if (!optional.isPresent()) {
throw new RuntimeException("httpClient为空");
}
return optional.get();
}
private WxPayMrchCfg getApiV3Cfg(String merchantId) {
String merchantIdCfg = redisUtils.getHashValue(REDIS_KEY_RCHG_PARTNER_PAY_MRCH_CFG, merchantId);
if (StrUtil.isBlank(merchantIdCfg)) {
throw new RuntimeException("查询不到此微信商户号ApiV3配置:" + merchantId);
}
WxPayMrchCfg wxPayMrchCfg = JSON.parseObject(merchantIdCfg, WxPayMrchCfg.class);
if (!doCheckParam(merchantId, wxPayMrchCfg.getCertSerialNo(), wxPayMrchCfg.getPartnerKey(),
wxPayMrchCfg.getCertPrivateKeyPath())) {
throw new RuntimeException("初始化 CloseableHttpClient 失败,缺少必要参数");
}
return wxPayMrchCfg;
}
private Verifier getVerifier(String merchantId, String merchantSerialNumber, String apiV3Key,
PrivateKey merchantPrivateKey)
throws IOException, GeneralSecurityException, HttpCodeException, NotFoundException {
Verifier verifier;
try {
// 从证书管理器中获取verifier
verifier = certificatesManager.getVerifier(merchantId);
} catch (IllegalArgumentException | NotFoundException e) {
// 向证书管理器增加需要自动更新平台证书的商户信息
certificatesManager.putMerchant(merchantId,
new WechatPay2Credentials(merchantId,
new PrivateKeySigner(merchantSerialNumber, merchantPrivateKey)),
apiV3Key.getBytes(StandardCharsets.UTF_8));
// 从证书管理器中获取verifier
verifier = certificatesManager.getVerifier(merchantId);
} catch (Exception e) {
throw new RuntimeException("获取verifier失败");
}
return verifier;
}
private Optional<CloseableHttpClient> getHttpClient(String merchantId, String merchantSerialNumber,
PrivateKey merchantPrivateKey, Verifier verifier) {
if (MERCHANT_ID_HTTP_CLIENT_MAP.get(merchantId) == null) {
synchronized (WxApiV3Utils.class) {
if (MERCHANT_ID_HTTP_CLIENT_MAP.get(merchantId) == null) {
// 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
CloseableHttpClient newHttpClient = WechatPayHttpClientBuilder.create()
.withMerchant(merchantId, merchantSerialNumber, merchantPrivateKey)
.withValidator(new WechatPay2Validator(verifier)).build();
MERCHANT_ID_HTTP_CLIENT_MAP.put(merchantId, newHttpClient);
}
}
}
return Optional.ofNullable(MERCHANT_ID_HTTP_CLIENT_MAP.get(merchantId));
}
public BizResponse request(CloseableHttpClient httpClient, HttpPost httpPost, String reqMethodName)
throws IOException {
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(5000).setConnectionRequestTimeout(2000)
.setSocketTimeout(5000).build();
httpPost.setConfig(requestConfig);
BizResponse bizResponse;
int statusCode;
// 完成签名并执行请求
try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) { // 处理成功
bizResponse = BizResponse.success(EntityUtils.toString(response.getEntity()));
} else if (statusCode == 204) {// 处理成功,无返回Body
bizResponse = BizResponse.success("success");
} else {
bizResponse = BizResponse.failure(EntityUtils.toString(response.getEntity()));
}
}
logger.info("{} 返回状态码:{},数据:{}", reqMethodName, statusCode, bizResponse.getMsg());
return bizResponse;
}
/**
* 获取微信支付平台证书序列号
*/
public String getPlatformCertificateSerial(String merchantId) throws NotFoundException {
return certificatesManager.getVerifier(merchantId).getValidCertificate().getSerialNumber().toString(16);
}
/**
* 敏感信息加密
*/
public String sensitiveInfoEncrypt(String merchantId, String text) throws Exception {
Verifier verifier = CertificatesManager.getInstance().getVerifier(merchantId);
X509Certificate certificate = verifier.getValidCertificate();
return RsaCryptoUtil.encryptOAEP(text, certificate);
}
private boolean doCheckParam(String mrchId, String certSerialNo, String apiV3Key, String privateKeyFilePath) {
return doCheckValue(mrchId, certSerialNo, apiV3Key, privateKeyFilePath);
}
private boolean doCheckValue(String... item) {
for (String param : item) {
if (StrUtil.isBlank(param)) {
return false;
}
}
return true;
}
}