微信加解密流程,证书作用讲解,官方SDK使用教程

时间:2025-03-06 07:07:59
@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; } }