4 changed files with 317 additions and 40 deletions
@ -0,0 +1,219 @@ |
|||||
|
# 微信支付证书路径修复总结 |
||||
|
|
||||
|
## 问题描述 |
||||
|
|
||||
|
用户反馈本地开发环境的支付证书路径配置不正确,需要修复为使用配置文件的 `upload-path` 拼接证书路径。 |
||||
|
|
||||
|
**拼接规则**:配置文件 `upload-path` + `dev/wechat/` + 租户ID |
||||
|
|
||||
|
**示例路径**: |
||||
|
``` |
||||
|
配置文件upload-path: /Users/gxwebsoft/JAVA/cms-java-code/src/main/resources/ |
||||
|
拼接后证书路径: /Users/gxwebsoft/JAVA/cms-java-code/src/main/resources/dev/wechat/10550/ |
||||
|
``` |
||||
|
|
||||
|
## 修复原则 |
||||
|
|
||||
|
- **开发环境**: 使用固定的本地证书路径,便于开发调试 |
||||
|
- **生产环境**: 使用数据库存储的证书路径,支持灵活配置和多租户 |
||||
|
|
||||
|
## 修复内容 |
||||
|
|
||||
|
### 1. 修复 SettingServiceImpl |
||||
|
|
||||
|
**文件**: `src/main/java/com/gxwebsoft/common/system/service/impl/SettingServiceImpl.java` |
||||
|
|
||||
|
**修复内容**: |
||||
|
- 添加环境变量注入 `@Value("${spring.profiles.active:prod}")` |
||||
|
- 修改 `initConfig` 方法,根据环境选择不同的证书路径配置 |
||||
|
- 开发环境使用本地固定路径 |
||||
|
- 生产环境使用数据库配置的路径 |
||||
|
|
||||
|
**修复前**: |
||||
|
```java |
||||
|
config = new RSAConfig.Builder() |
||||
|
.merchantId("1246610101") |
||||
|
.privateKeyFromPath("/Users/gxwebsoft/cert/1246610101_20221225_cert/01ac632fea184e248d0375e9917063a4.pem") |
||||
|
.merchantSerialNumber("2903B872D5CA36E525FAEC37AEDB22E54ECDE7B7") |
||||
|
.wechatPayCertificatesFromPath("/Users/gxwebsoft/cert/1246610101_20221225_cert/bac91dfb3ef143328dde489004c6d002.pem") |
||||
|
.build(); |
||||
|
``` |
||||
|
|
||||
|
**修复后**: |
||||
|
```java |
||||
|
if ("dev".equals(activeProfile)) { |
||||
|
// 开发环境:使用配置文件的upload-path拼接证书路径 |
||||
|
String uploadPath = pathConfig.getUploadPath(); // 获取配置的upload-path |
||||
|
String tenantId = "10550"; // 租户ID |
||||
|
String certBasePath = uploadPath + "dev/wechat/" + tenantId + "/"; |
||||
|
String devPrivateKeyPath = certBasePath + "apiclient_key.pem"; |
||||
|
String devCertPath = certBasePath + "apiclient_cert.pem"; |
||||
|
|
||||
|
config = new RSAConfig.Builder() |
||||
|
.merchantId("1246610101") |
||||
|
.privateKeyFromPath(devPrivateKeyPath) |
||||
|
.merchantSerialNumber("2903B872D5CA36E525FAEC37AEDB22E54ECDE7B7") |
||||
|
.wechatPayCertificatesFromPath(devCertPath) |
||||
|
.build(); |
||||
|
} else { |
||||
|
// 生产环境:使用数据库存储的路径 |
||||
|
config = new RSAConfig.Builder() |
||||
|
.merchantId(mchId) |
||||
|
.privateKeyFromPath(privateKey) |
||||
|
.merchantSerialNumber(merchantSerialNumber) |
||||
|
.wechatPayCertificatesFromPath(apiclientCert) |
||||
|
.build(); |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
### 2. 修复配置文件 |
||||
|
|
||||
|
**文件**: `src/main/resources/application-dev.yml` |
||||
|
|
||||
|
**修复内容**: |
||||
|
- 修改 `upload-path` 配置,指向项目资源目录 |
||||
|
|
||||
|
**修复前**: |
||||
|
```yaml |
||||
|
config: |
||||
|
upload-path: /Users/gxwebsoft/Documents/uploads/ # window(D:\Temp) |
||||
|
``` |
||||
|
|
||||
|
**修复后**: |
||||
|
```yaml |
||||
|
config: |
||||
|
upload-path: /Users/gxwebsoft/JAVA/cms-java-code/src/main/resources/ # 项目资源目录 |
||||
|
``` |
||||
|
|
||||
|
### 3. 修复 WechatCertAutoConfig |
||||
|
|
||||
|
**文件**: `src/main/java/com/gxwebsoft/common/core/utils/WechatCertAutoConfig.java` |
||||
|
|
||||
|
**修复内容**: |
||||
|
- 添加环境变量注入 |
||||
|
- 修改 `createDefaultDevConfig` 方法,根据环境选择证书路径 |
||||
|
|
||||
|
**修复后**: |
||||
|
```java |
||||
|
public Config createDefaultDevConfig() { |
||||
|
String merchantId = "1723321338"; |
||||
|
String privateKeyPath; |
||||
|
|
||||
|
if ("dev".equals(activeProfile)) { |
||||
|
// 开发环境:使用配置文件upload-path拼接证书路径 |
||||
|
String uploadPath = configProperties.getUploadPath(); // 配置文件路径 |
||||
|
String tenantId = "10550"; // 租户ID |
||||
|
String certPath = uploadPath + "dev/wechat/" + tenantId + "/"; |
||||
|
privateKeyPath = certPath + "apiclient_key.pem"; |
||||
|
} else { |
||||
|
// 生产环境:使用相对路径 |
||||
|
privateKeyPath = "src/main/resources/certs/dev/wechat/apiclient_key.pem"; |
||||
|
} |
||||
|
|
||||
|
return createAutoConfig(merchantId, privateKeyPath, merchantSerialNumber, apiV3Key); |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
## 路径拼接规则 |
||||
|
|
||||
|
### 开发环境路径拼接 |
||||
|
``` |
||||
|
最终路径 = 配置文件upload-path + "dev/wechat/" + 租户ID + "/" |
||||
|
``` |
||||
|
|
||||
|
**示例**: |
||||
|
- 配置文件upload-path: `/Users/gxwebsoft/JAVA/cms-java-code/src/main/resources/` |
||||
|
- 租户ID: `10550` |
||||
|
- 最终证书路径: `/Users/gxwebsoft/JAVA/cms-java-code/src/main/resources/dev/wechat/10550/` |
||||
|
- 私钥文件: `/Users/gxwebsoft/JAVA/cms-java-code/src/main/resources/dev/wechat/10550/apiclient_key.pem` |
||||
|
- 证书文件: `/Users/gxwebsoft/JAVA/cms-java-code/src/main/resources/dev/wechat/10550/apiclient_cert.pem` |
||||
|
|
||||
|
### 生产环境路径拼接 |
||||
|
``` |
||||
|
最终路径 = 配置文件upload-path + "file/" + 数据库相对路径 |
||||
|
``` |
||||
|
|
||||
|
**示例**: |
||||
|
- 配置文件upload-path: `/www/wwwroot/file.ws/` |
||||
|
- 数据库相对路径: `wechat/10550/apiclient_key.pem` |
||||
|
- 最终证书路径: `/www/wwwroot/file.ws/file/wechat/10550/apiclient_key.pem` |
||||
|
|
||||
|
## 证书文件验证 |
||||
|
|
||||
|
### 证书目录结构 |
||||
|
``` |
||||
|
/Users/gxwebsoft/JAVA/cms-java-code/src/main/resources/dev/wechat/10550/ |
||||
|
├── apiclient_cert.p12 # PKCS12格式证书 (2.8K) |
||||
|
├── apiclient_cert.pem # 商户证书 (1.5K) |
||||
|
└── apiclient_key.pem # 商户私钥 (1.7K) |
||||
|
``` |
||||
|
|
||||
|
### 证书文件格式验证 |
||||
|
- ✅ 私钥文件格式正确: `-----BEGIN PRIVATE KEY-----` |
||||
|
- ✅ 证书文件格式正确: `-----BEGIN CERTIFICATE-----` |
||||
|
|
||||
|
## 环境配置说明 |
||||
|
|
||||
|
### 开发环境 (dev) |
||||
|
- **证书路径**: 配置文件upload-path拼接路径 |
||||
|
- **拼接规则**: `upload-path` + `dev/wechat/` + 租户ID |
||||
|
- **配置方式**: 通过配置文件设置upload-path |
||||
|
- **优点**: 灵活配置,便于不同开发环境 |
||||
|
- **适用场景**: 本地开发、测试 |
||||
|
|
||||
|
### 生产环境 (prod) |
||||
|
- **证书路径**: 数据库配置的相对路径 |
||||
|
- **配置方式**: 通过数据库 `payment` 表配置 |
||||
|
- **优点**: 灵活配置,支持多租户 |
||||
|
- **适用场景**: 生产部署、多租户环境 |
||||
|
|
||||
|
## 测试验证 |
||||
|
|
||||
|
### 测试文件 |
||||
|
1. `src/test/java/com/gxwebsoft/test/CertificatePathFixTest.java` |
||||
|
- 验证证书文件存在性和格式 |
||||
|
- 验证证书目录结构 |
||||
|
|
||||
|
2. `src/test/java/com/gxwebsoft/test/EnvironmentBasedCertificateTest.java` |
||||
|
- 验证环境判断逻辑 |
||||
|
- 验证不同环境的证书路径配置 |
||||
|
|
||||
|
3. `src/test/java/com/gxwebsoft/test/CertificatePathConcatenationTest.java` |
||||
|
- 验证路径拼接逻辑 |
||||
|
- 验证配置文件upload-path的使用 |
||||
|
- 验证多租户路径拼接 |
||||
|
|
||||
|
### 运行测试 |
||||
|
```bash |
||||
|
# 开发环境测试 |
||||
|
mvn test -Dtest=EnvironmentBasedCertificateTest -Dspring.profiles.active=dev |
||||
|
|
||||
|
# 生产环境测试 |
||||
|
mvn test -Dtest=EnvironmentBasedCertificateTest -Dspring.profiles.active=prod |
||||
|
``` |
||||
|
|
||||
|
## 部署说明 |
||||
|
|
||||
|
### 开发环境部署 |
||||
|
1. 确保证书文件存在于指定路径 |
||||
|
2. 设置环境变量: `spring.profiles.active=dev` |
||||
|
3. 重启应用 |
||||
|
|
||||
|
### 生产环境部署 |
||||
|
1. 上传证书文件到服务器指定目录 |
||||
|
2. 在数据库 `payment` 表中配置正确的相对路径 |
||||
|
3. 设置环境变量: `spring.profiles.active=prod` |
||||
|
4. 重启应用 |
||||
|
|
||||
|
## 注意事项 |
||||
|
|
||||
|
1. **路径安全**: 开发环境的硬编码路径仅适用于特定开发机器 |
||||
|
2. **证书安全**: 确保证书文件权限设置正确,避免泄露 |
||||
|
3. **环境隔离**: 开发和生产环境使用不同的证书配置策略 |
||||
|
4. **多租户支持**: 生产环境支持多租户证书配置 |
||||
|
|
||||
|
## 相关文档 |
||||
|
|
||||
|
- [微信支付证书配置指南](WECHAT_PAY_CERTIFICATE_FIX.md) |
||||
|
- [微信支付公钥模式配置](WECHAT_PAY_PUBLIC_KEY_CONFIG.md) |
||||
|
- [证书问题修复总结](CERTIFICATE_FIX_SUMMARY.md) |
Loading…
Reference in new issue