diff --git a/certs/README.md b/certs/README.md deleted file mode 100644 index 71f05b6..0000000 --- a/certs/README.md +++ /dev/null @@ -1,68 +0,0 @@ -# 证书目录说明 - -这个目录用于存放支付相关的证书文件,支持Docker容器化部署。 - -## 目录结构 - -``` -certs/ -├── README.md # 本说明文件 -├── wechat/ # 微信支付证书目录 -│ ├── apiclient_key.pem # 商户私钥证书 -│ ├── apiclient_cert.pem # 商户证书 -│ └── wechatpay_cert.pem # 微信支付平台证书 -└── alipay/ # 支付宝证书目录 - ├── app_private_key.pem # 应用私钥 - ├── appCertPublicKey.crt # 应用公钥证书 - ├── alipayCertPublicKey.crt # 支付宝公钥证书 - └── alipayRootCert.crt # 支付宝根证书 -``` - -## 使用说明 - -### 1. 开发环境 -- 将证书文件放在 `src/main/resources/certs/dev/` 目录下 -- 应用会从classpath加载证书 - -### 2. 生产环境 -- 将证书文件放在此目录下 -- Docker容器会将此目录挂载到 `/app/certs` -- 应用会从挂载卷加载证书 - -### 3. 证书文件权限 -```bash -# 设置证书文件为只读权限 -chmod -R 444 certs/ - -# 设置目录权限 -chmod 755 certs/ -chmod 755 certs/wechat/ -chmod 755 certs/alipay/ -``` - -## 安全注意事项 - -1. **不要将证书文件提交到版本控制系统** -2. **确保证书文件权限设置正确** -3. **定期更新证书文件** -4. **备份重要的证书文件** - -## 证书获取方式 - -### 微信支付证书 -1. 登录微信商户平台 -2. 进入"账户中心" -> "API安全" -3. 下载商户证书和平台证书 - -### 支付宝证书 -1. 登录支付宝开放平台 -2. 进入应用详情页 -3. 在"开发设置"中下载相关证书 - -## 故障排除 - -如果遇到证书加载问题,请检查: -1. 证书文件是否存在 -2. 证书文件路径是否正确 -3. 证书文件权限是否正确 -4. 证书文件是否已过期 diff --git a/src/main/java/com/gxwebsoft/bszx/controller/BszxPayController.java b/src/main/java/com/gxwebsoft/bszx/controller/BszxPayController.java index 305cf8b..03171e8 100644 --- a/src/main/java/com/gxwebsoft/bszx/controller/BszxPayController.java +++ b/src/main/java/com/gxwebsoft/bszx/controller/BszxPayController.java @@ -204,9 +204,15 @@ public class BszxPayController extends BaseController { @Schema(description = "异步通知") @PostMapping("/notify/{tenantId}") public String wxNotify(@RequestHeader Map header, @RequestBody String body,HttpServletRequest request, @PathVariable("tenantId") Integer tenantId) { - // 获取支付配置信息用于解密 - String key = "Payment:1:".concat(tenantId.toString()); + // 获取支付配置信息用于解密 - 优先使用 Payment:1* 格式 + String key = "Payment:11"; // 微信支付类型为1,使用 Payment:11 格式 Payment payment = redisUtil.get(key, Payment.class); + + // 如果 Payment:1* 格式不存在,尝试原有格式 + if (payment == null) { + String fallbackKey = "Payment:1:".concat(tenantId.toString()); + payment = redisUtil.get(fallbackKey, Payment.class); + } String uploadPath = conf.getUploadPath(); // 开发环境 @@ -223,9 +229,10 @@ public class BszxPayController extends BaseController { mid = payment.getMchId(); apiV3Key = payment.getApiKey(); serialNumber = payment.getMerchantSerialNumber(); - privateKey = payment.getApiclientKey(); - apiclientCert = conf.getUploadPath().concat("/file").concat(payment.getApiclientCert()); - pubKey = uploadPath.concat("file").concat(payment.getPubKey()); + // 生产环境使用容器证书路径 /www/wwwroot/file.ws + privateKey = "/www/wwwroot/file.ws" + payment.getApiclientKey(); + apiclientCert = "/www/wwwroot/file.ws" + payment.getApiclientCert(); + pubKey = "/www/wwwroot/file.ws" + payment.getPubKey(); pubId = payment.getPubKeyId(); } RequestParam requestParam = new RequestParam.Builder() diff --git a/src/main/java/com/gxwebsoft/common/core/config/CertificateProperties.java b/src/main/java/com/gxwebsoft/common/core/config/CertificateProperties.java index ab09a24..4857dcc 100644 --- a/src/main/java/com/gxwebsoft/common/core/config/CertificateProperties.java +++ b/src/main/java/com/gxwebsoft/common/core/config/CertificateProperties.java @@ -7,7 +7,7 @@ import org.springframework.stereotype.Component; /** * 证书配置属性类 * 支持开发环境从classpath加载证书,生产环境从Docker挂载卷加载证书 - * + * * @author 科技小王子 * @since 2024-07-26 */ @@ -27,7 +27,7 @@ public class CertificateProperties { /** * Docker挂载卷证书根路径 */ - private String certRootPath = "/app/certs"; + private String certRootPath = "/www/wwwroot/file.ws"; /** * 开发环境证书路径前缀 @@ -130,7 +130,7 @@ public class CertificateProperties { /** * 获取证书文件的完整路径 - * + * * @param certType 证书类型(wechat/alipay) * @param fileName 文件名 * @return 完整路径 @@ -150,7 +150,7 @@ public class CertificateProperties { /** * 获取微信支付证书路径 - * + * * @param fileName 文件名 * @return 完整路径 */ @@ -160,7 +160,7 @@ public class CertificateProperties { /** * 获取支付宝证书路径 - * + * * @param fileName 文件名 * @return 完整路径 */ @@ -170,7 +170,7 @@ public class CertificateProperties { /** * 检查证书加载模式是否为classpath模式 - * + * * @return true if classpath mode */ public boolean isClasspathMode() { @@ -179,7 +179,7 @@ public class CertificateProperties { /** * 检查证书加载模式是否为文件系统模式 - * + * * @return true if filesystem mode */ public boolean isFilesystemMode() { @@ -188,7 +188,7 @@ public class CertificateProperties { /** * 检查证书加载模式是否为挂载卷模式 - * + * * @return true if volume mode */ public boolean isVolumeMode() { diff --git a/src/main/java/com/gxwebsoft/common/system/controller/PaymentController.java b/src/main/java/com/gxwebsoft/common/system/controller/PaymentController.java index 348909f..f68c414 100644 --- a/src/main/java/com/gxwebsoft/common/system/controller/PaymentController.java +++ b/src/main/java/com/gxwebsoft/common/system/controller/PaymentController.java @@ -7,6 +7,7 @@ import com.gxwebsoft.common.core.annotation.OperationLog; import com.gxwebsoft.common.core.utils.RedisUtil; import com.gxwebsoft.common.core.utils.RequestUtil; import com.gxwebsoft.common.core.web.*; +import com.gxwebsoft.common.core.service.PaymentCacheService; import com.gxwebsoft.common.system.entity.Payment; import com.gxwebsoft.common.system.entity.User; import com.gxwebsoft.common.system.entity.UserBalanceLog; @@ -51,6 +52,8 @@ public class PaymentController extends BaseController { private RedisUtil redisUtil; @Resource private RequestUtil requestUtil; + @Resource + private PaymentCacheService paymentCacheService; @Operation(summary = "余额支付接口") @PostMapping("/balancePay") @@ -96,10 +99,9 @@ public class PaymentController extends BaseController { amount.setTotal(money); amount.setCurrency("CNY"); transaction.setAmount(amount); - // 获取支付配置信息用于解密 - String key = "Payment:0:".concat(order.getTenantId().toString()); - System.out.println("key = " + key); - final Payment payment = redisUtil.get(key, Payment.class); + // 获取支付配置信息用于解密 - 使用缓存服务 + Payment payment = paymentCacheService.getWechatPayConfig(order.getTenantId()); + System.out.println("获取到支付配置: " + payment.getMchId()); requestUtil.pushBalancePayNotify(transaction, payment); return success("支付成功",order.getOrderNo()); @@ -161,8 +163,8 @@ public class PaymentController extends BaseController { return fail(payment.getName() + "已存在"); } if (paymentService.save(payment)) { - String key = "Payment:" + payment.getCode() + ":" + getTenantId(); - redisUtil.set(key,payment); + // 使用缓存服务统一管理缓存 + paymentCacheService.cachePaymentConfig(payment, getTenantId()); return success("添加成功"); } return fail("添加失败"); @@ -174,8 +176,8 @@ public class PaymentController extends BaseController { @PutMapping() public ApiResult update(@RequestBody Payment payment) { if (paymentService.updateById(payment)) { - String key = "Payment:" + payment.getCode() + ":" + getTenantId(); - redisUtil.set(key,payment); + // 使用缓存服务统一管理缓存 + paymentCacheService.cachePaymentConfig(payment, getTenantId()); return success("修改成功"); } return fail("修改失败"); @@ -187,9 +189,10 @@ public class PaymentController extends BaseController { @DeleteMapping("/{id}") public ApiResult remove(@PathVariable("id") Integer id) { final Payment payment = paymentService.getById(id); - System.out.println("payment = " + payment); - String key = "Payment:" + payment.getCode() + ":" + getTenantId(); - redisUtil.delete(key); + System.out.println("payment = " + payment); + + // 使用缓存服务统一管理缓存删除 + paymentCacheService.removePaymentConfig(payment.getCode(), getTenantId()); if (paymentService.removeById(id)) { return success("删除成功"); } diff --git a/src/main/java/com/gxwebsoft/shop/service/impl/ShopOrderServiceImpl.java b/src/main/java/com/gxwebsoft/shop/service/impl/ShopOrderServiceImpl.java index e344ec1..f637dcf 100644 --- a/src/main/java/com/gxwebsoft/shop/service/impl/ShopOrderServiceImpl.java +++ b/src/main/java/com/gxwebsoft/shop/service/impl/ShopOrderServiceImpl.java @@ -10,6 +10,7 @@ import com.gxwebsoft.common.core.exception.BusinessException; import com.gxwebsoft.common.core.utils.RedisUtil; import com.gxwebsoft.common.core.utils.CertificateLoader; +import com.gxwebsoft.common.core.service.PaymentCacheService; import com.gxwebsoft.common.system.entity.Payment; import com.gxwebsoft.common.system.param.PaymentParam; import com.gxwebsoft.common.system.service.PaymentService; @@ -65,6 +66,8 @@ private CertificateProperties certConfig; @Resource private CertificateLoader certificateLoader; + @Resource + private PaymentCacheService paymentCacheService; @Override public PageResult pageRel(ShopOrderParam param) { @@ -192,23 +195,13 @@ /** * 读取微信支付配置 + * 生产环境优先从缓存读取 Payment:1* 格式的商户信息 * * @param order * @return */ public Payment getPayment(ShopOrder order) { - String key2 = "Payment:".concat(order.getPayType().toString()).concat(":").concat(order.getTenantId().toString()); - final Payment payment = redisUtil.get(key2, Payment.class); - if (ObjectUtil.isNotEmpty(payment)) { - return payment; - } - final PaymentParam paymentParam = new PaymentParam(); - paymentParam.setType(order.getPayType()); - final List payments = paymentService.listRel(paymentParam); - if (payments.isEmpty()) { - throw new BusinessException("请完成支付配置"); - } - return payments.get(0); + return paymentCacheService.getPaymentConfig(order.getPayType(), order.getTenantId()); } /** @@ -229,15 +222,15 @@ apiclientCert = certificateLoader.loadCertificatePath( certConfig.getWechatPayCertPath(certConfig.getWechatPay().getDev().getWechatpayCertFile())); } else { - // 生产环境配置 - 从上传目录加载 - final String uploadPath = config.getUploadPath(); + // 生产环境配置 - 从容器证书目录加载 + final String certRootPath = certConfig.getCertRootPath(); // /www/wwwroot/file.ws privateKey = certificateLoader.loadCertificatePath( - uploadPath.concat("file").concat(payment.getApiclientKey())); + certRootPath + payment.getApiclientKey()); apiclientCert = certificateLoader.loadCertificatePath( - uploadPath.concat("file").concat(payment.getApiclientCert())); + certRootPath + payment.getApiclientCert()); if (payment.getPubKey() != null && !payment.getPubKey().isEmpty()) { pubKey = certificateLoader.loadCertificatePath( - uploadPath.concat("file").concat(payment.getPubKey())); + certRootPath + payment.getPubKey()); } } diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 7d6c15f..7b203cf 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -2,7 +2,7 @@ # 服务器配置 server: - port: 9202 + port: 9200 # 数据源配置 spring: diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index 9ad43a9..4a65c72 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -57,4 +57,12 @@ config: # 生产环境证书配置 certificate: load-mode: VOLUME # 生产环境从Docker挂载卷加载 - cert-root-path: /app/certs + cert-root-path: /www/wwwroot/file.ws + +# 支付配置缓存 +payment: + cache: + # 支付配置缓存键前缀,生产环境使用 Payment:1* 格式 + key-prefix: "Payment:1" + # 缓存过期时间(小时) + expire-hours: 24