|
|
@@ -1,82 +1,61 @@
|
|
|
package com.ylx.common.config;
|
|
|
|
|
|
import cn.hutool.core.util.StrUtil;
|
|
|
+import com.github.binarywang.wxpay.config.WxPayConfig;
|
|
|
import com.github.binarywang.wxpay.service.WxPayService;
|
|
|
-import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
|
|
|
+import com.github.binarywang.wxpay.service.impl.WxPayServiceApacheHttpImpl;
|
|
|
+import com.ylx.common.exception.ServiceException;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
-import org.apache.commons.io.IOUtils;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.context.annotation.Bean;
|
|
|
import org.springframework.context.annotation.Configuration;
|
|
|
-import org.springframework.core.io.Resource;
|
|
|
-import org.springframework.core.io.ResourceLoader;
|
|
|
-
|
|
|
-import java.io.InputStream;
|
|
|
-import java.security.KeyFactory;
|
|
|
-import java.security.PrivateKey;
|
|
|
-import java.security.spec.PKCS8EncodedKeySpec;
|
|
|
-import java.util.Base64;
|
|
|
|
|
|
@Slf4j
|
|
|
@Configuration
|
|
|
public class WxPayBeanConfig {
|
|
|
|
|
|
@Autowired
|
|
|
- private WxPayConfig wxPayConfig;
|
|
|
- @Autowired
|
|
|
- private ResourceLoader resourceLoader;
|
|
|
+ private WechatPayConfig wxPayConfig;
|
|
|
|
|
|
@Bean
|
|
|
- public WxPayService wxPayService() throws Exception {
|
|
|
- // SDK原生配置
|
|
|
- com.github.binarywang.wxpay.config.WxPayConfig sdkConfig = new com.github.binarywang.wxpay.config.WxPayConfig();
|
|
|
+ public WxPayService wxPayService() {
|
|
|
+ // 1. 全局前置必填参数校验(启动即校验,提前暴露问题)
|
|
|
+ checkWxPayConfig();
|
|
|
+
|
|
|
+ // 2. 映射SDK原生配置
|
|
|
+ WxPayConfig sdkConfig = new WxPayConfig();
|
|
|
sdkConfig.setAppId(wxPayConfig.getAppId());
|
|
|
sdkConfig.setMchId(wxPayConfig.getMchId());
|
|
|
- // v3密钥
|
|
|
sdkConfig.setApiV3Key(wxPayConfig.getMchKey());
|
|
|
+ sdkConfig.setPrivateCertPath(wxPayConfig.getCertPath());
|
|
|
+ sdkConfig.setPrivateKeyPath(wxPayConfig.getCertKeyPath());
|
|
|
+ sdkConfig.setNotifyUrl(wxPayConfig.getNotifyUrl());
|
|
|
|
|
|
- if (StrUtil.isBlank(wxPayConfig.getCertKeyPath())) {
|
|
|
- log.warn("wx.cert-key-path未配置,跳过初始化微信支付服务");
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- // 读取私钥文件 apiclient_key.pem
|
|
|
- Resource keyRes = resourceLoader.getResource(wxPayConfig.getCertKeyPath());
|
|
|
- if(keyRes.exists()){
|
|
|
- try (InputStream is = keyRes.getInputStream()) {
|
|
|
- PrivateKey privateKey = loadPrivateKey(is);
|
|
|
- sdkConfig.setPrivateKey(privateKey);
|
|
|
- log.info("商户私钥文件加载成功:{}",wxPayConfig.getCertKeyPath());
|
|
|
- } catch (Exception e) {
|
|
|
- log.error("私钥文件存在但读取失败:{}",wxPayConfig.getCertKeyPath(),e);
|
|
|
- }
|
|
|
- }else{
|
|
|
- // 文件不存在,只打日志,不中断启动
|
|
|
- log.warn("商户私钥文件【{}】不存在,微信支付功能禁用",wxPayConfig.getCertKeyPath());
|
|
|
- }
|
|
|
-
|
|
|
- WxPayService payService = new WxPayServiceImpl();
|
|
|
+ // 3. V3推荐Apache HTTP实现,替换旧WxPayServiceImpl
|
|
|
+ WxPayService payService = new WxPayServiceApacheHttpImpl();
|
|
|
payService.setConfig(sdkConfig);
|
|
|
+ log.info("微信支付V3客户端初始化完成,商户号:{}", wxPayConfig.getMchId());
|
|
|
return payService;
|
|
|
}
|
|
|
|
|
|
- /** 从pem输入流读取RSA私钥 */
|
|
|
- private PrivateKey loadPrivateKey(InputStream inputStream) throws Exception {
|
|
|
- try {
|
|
|
- // JDK8不能用inputStream.readAllBytes(),替换成IOUtils
|
|
|
- byte[] bytes = IOUtils.toByteArray(inputStream);
|
|
|
- String pem = new String(bytes)
|
|
|
- .replace("-----BEGIN PRIVATE KEY-----", "")
|
|
|
- .replace("-----END PRIVATE KEY-----", "")
|
|
|
- .replaceAll("\\s+", ""); // \s+ 清除所有换行、空格
|
|
|
-
|
|
|
- byte[] decode = Base64.getDecoder().decode(pem);
|
|
|
- PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(decode);
|
|
|
- KeyFactory kf = KeyFactory.getInstance("RSA");
|
|
|
- return kf.generatePrivate(spec);
|
|
|
- } finally {
|
|
|
- // 关闭流,防止资源泄漏
|
|
|
- IOUtils.closeQuietly(inputStream);
|
|
|
+ /**
|
|
|
+ * 启动时校验所有必填支付配置,缺失直接抛异常阻止项目启动
|
|
|
+ */
|
|
|
+ private void checkWxPayConfig() {
|
|
|
+ if (StrUtil.isBlank(wxPayConfig.getAppId())) {
|
|
|
+ throw new ServiceException("微信支付配置缺失:wx.app-id不能为空");
|
|
|
+ }
|
|
|
+ if (StrUtil.isBlank(wxPayConfig.getMchId())) {
|
|
|
+ throw new ServiceException("微信支付配置缺失:wx.mch-id不能为空");
|
|
|
+ }
|
|
|
+ if (StrUtil.isBlank(wxPayConfig.getMchKey())) {
|
|
|
+ throw new ServiceException("微信支付配置缺失:wx.mch-key(APIv3密钥)不能为空");
|
|
|
+ }
|
|
|
+ if (StrUtil.isBlank(wxPayConfig.getCertPath()) || StrUtil.isBlank(wxPayConfig.getCertKeyPath())) {
|
|
|
+ throw new ServiceException("微信支付证书配置缺失:cert-path/cert-key-path证书路径不能为空");
|
|
|
+ }
|
|
|
+ if (StrUtil.isBlank(wxPayConfig.getNotifyUrl())) {
|
|
|
+ log.warn("微信支付回调地址notify-url未配置,支付回调无法接收");
|
|
|
}
|
|
|
}
|
|
|
}
|