Browse Source

大改:重构项目

main
科技小王子 4 weeks ago
parent
commit
5746751146
  1. 68
      certs/README.md
  2. 17
      src/main/java/com/gxwebsoft/bszx/controller/BszxPayController.java
  3. 16
      src/main/java/com/gxwebsoft/common/core/config/CertificateProperties.java
  4. 25
      src/main/java/com/gxwebsoft/common/system/controller/PaymentController.java
  5. 27
      src/main/java/com/gxwebsoft/shop/service/impl/ShopOrderServiceImpl.java
  6. 2
      src/main/resources/application-dev.yml
  7. 10
      src/main/resources/application-prod.yml

68
certs/README.md

@ -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. 证书文件是否已过期

17
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<String, String> 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()

16
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() {

25
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("删除成功");
}

27
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<ShopOrder> 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<Payment> 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());
}
}

2
src/main/resources/application-dev.yml

@ -2,7 +2,7 @@
# 服务器配置
server:
port: 9202
port: 9200
# 数据源配置
spring:

10
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

Loading…
Cancel
Save