修复微信支付,兼容公钥模块
This commit is contained in:
192
docs/CERTIFICATE_FIX_SUMMARY.md
Normal file
192
docs/CERTIFICATE_FIX_SUMMARY.md
Normal file
@@ -0,0 +1,192 @@
|
||||
# 微信支付证书问题修复总结
|
||||
|
||||
## 问题描述
|
||||
|
||||
**错误信息**:`创建支付订单失败:创建支付订单失败:Cannot invoke "java.security.cert.X509Certificate.getSerialNumber()" because "certificate" is null`
|
||||
|
||||
**错误代码**:1
|
||||
|
||||
## 问题分析
|
||||
|
||||
这个错误发生在微信支付SDK使用 `RSAAutoCertificateConfig` 自动证书配置时,SDK尝试自动下载微信支付平台证书但失败,导致证书对象为null,进而在调用 `getSerialNumber()` 方法时抛出空指针异常。
|
||||
|
||||
## 已实施的修复方案
|
||||
|
||||
### 1. 增强错误处理和自动回退机制
|
||||
|
||||
**文件**:`src/main/java/com/gxwebsoft/shop/service/impl/ShopOrderServiceImpl.java`
|
||||
|
||||
**修复内容**:
|
||||
- 在开发环境和生产环境都增加了详细的错误诊断
|
||||
- 实现了自动回退机制:当 `RSAAutoCertificateConfig` 失败时,自动回退到 `RSAConfig` 或 `RSAPublicKeyConfig`
|
||||
- 增加了特定的证书错误检测和处理逻辑
|
||||
- 提供了详细的错误信息和修复建议
|
||||
|
||||
### 2. 创建证书诊断工具
|
||||
|
||||
**文件**:`src/main/java/com/gxwebsoft/common/core/utils/WechatPayCertificateDiagnostic.java`
|
||||
|
||||
**功能**:
|
||||
- 全面诊断微信支付证书配置
|
||||
- 检查基本配置(商户号、应用ID、APIv3密钥、证书序列号)
|
||||
- 验证证书文件存在性和有效性
|
||||
- 检查证书内容和序列号匹配
|
||||
- 生成详细的诊断报告和修复建议
|
||||
|
||||
### 3. 创建证书修复工具
|
||||
|
||||
**文件**:`src/main/java/com/gxwebsoft/common/core/utils/WechatPayCertificateFixer.java`
|
||||
|
||||
**功能**:
|
||||
- 自动检测和修复常见的证书配置问题
|
||||
- 验证证书文件路径和内容
|
||||
- 检查序列号匹配性
|
||||
- 提供自动修复建议
|
||||
|
||||
### 4. 创建诊断API接口
|
||||
|
||||
**文件**:`src/main/java/com/gxwebsoft/common/core/controller/WechatPayDiagnosticController.java`
|
||||
|
||||
**提供的API**:
|
||||
- `GET /system/wechat-pay-diagnostic/diagnose/{tenantId}` - 诊断特定租户的证书配置
|
||||
- `GET /system/wechat-pay-diagnostic/solutions` - 获取证书问题解决方案
|
||||
- `POST /system/wechat-pay-diagnostic/test/{tenantId}` - 测试证书配置
|
||||
- `GET /system/wechat-pay-diagnostic/environment` - 获取环境信息
|
||||
- `GET /system/wechat-pay-diagnostic/guide` - 获取证书配置指南
|
||||
|
||||
### 5. 集成诊断功能
|
||||
|
||||
在支付服务中集成了证书诊断功能,每次创建支付订单时都会运行诊断,提供详细的配置信息和错误分析。
|
||||
|
||||
## 使用方法
|
||||
|
||||
### 1. 自动诊断
|
||||
|
||||
系统在创建支付订单时会自动运行诊断,查看控制台输出:
|
||||
|
||||
```
|
||||
=== 微信支付证书诊断报告 ===
|
||||
租户ID: 10550
|
||||
商户号: 1723321338
|
||||
应用ID: wx1234567890abcdef
|
||||
商户证书序列号: 2B933F7C35014A1C363642623E4A62364B34C4EB
|
||||
APIv3密钥: 已配置(32位)
|
||||
证书文件路径: dev/wechat/10550/apiclient_key.pem
|
||||
证书文件存在: 是
|
||||
配置验证结果: 通过
|
||||
```
|
||||
|
||||
### 2. 手动诊断
|
||||
|
||||
使用诊断API进行手动检查:
|
||||
|
||||
```bash
|
||||
# 诊断特定租户
|
||||
curl -X GET "http://localhost:9200/system/wechat-pay-diagnostic/diagnose/10550" \
|
||||
-H "Authorization: Bearer YOUR_TOKEN"
|
||||
|
||||
# 获取解决方案
|
||||
curl -X GET "http://localhost:9200/system/wechat-pay-diagnostic/solutions"
|
||||
|
||||
# 测试证书配置
|
||||
curl -X POST "http://localhost:9200/system/wechat-pay-diagnostic/test/10550" \
|
||||
-H "Authorization: Bearer YOUR_TOKEN"
|
||||
```
|
||||
|
||||
### 3. 查看配置指南
|
||||
|
||||
访问 `GET /system/wechat-pay-diagnostic/guide` 获取完整的证书配置指南。
|
||||
|
||||
## 常见问题解决
|
||||
|
||||
### 1. 商户平台配置
|
||||
|
||||
确保在微信商户平台完成以下配置:
|
||||
1. 开启API安全功能
|
||||
2. 申请使用微信支付公钥
|
||||
3. 下载商户证书文件
|
||||
4. 设置32位APIv3密钥
|
||||
|
||||
### 2. 证书文件配置
|
||||
|
||||
**开发环境**:
|
||||
```
|
||||
src/main/resources/dev/wechat/{tenantId}/
|
||||
├── apiclient_key.pem # 必需:商户私钥
|
||||
└── apiclient_cert.pem # 可选:商户证书
|
||||
```
|
||||
|
||||
**生产环境**:
|
||||
- 将证书文件上传到服务器指定目录
|
||||
- 在数据库中配置正确的文件路径
|
||||
|
||||
### 3. 数据库配置
|
||||
|
||||
在 `payment` 表中确保以下字段正确配置:
|
||||
- `mch_id`: 商户号
|
||||
- `app_id`: 应用ID
|
||||
- `merchant_serial_number`: 商户证书序列号
|
||||
- `api_key`: APIv3密钥(32位)
|
||||
|
||||
## 技术特性
|
||||
|
||||
### 1. 自动回退机制
|
||||
|
||||
当自动证书配置失败时,系统会自动尝试以下回退方案:
|
||||
1. `RSAAutoCertificateConfig` (首选)
|
||||
2. `RSAPublicKeyConfig` (如果有公钥配置)
|
||||
3. `RSAConfig` (如果有商户证书文件)
|
||||
|
||||
### 2. 详细错误诊断
|
||||
|
||||
系统会检测特定的错误类型并提供针对性的解决方案:
|
||||
- X509Certificate相关错误
|
||||
- 404错误(API安全未开启)
|
||||
- 证书序列号错误
|
||||
- APIv3密钥错误
|
||||
- 网络连接问题
|
||||
|
||||
### 3. 环境适配
|
||||
|
||||
支持开发环境和生产环境的不同配置方式:
|
||||
- 开发环境:从classpath加载证书
|
||||
- 生产环境:从文件系统或Docker挂载卷加载证书
|
||||
|
||||
## 监控和维护
|
||||
|
||||
### 1. 日志监控
|
||||
|
||||
关注以下日志信息:
|
||||
- 证书诊断报告
|
||||
- 自动回退日志
|
||||
- 错误详情和建议
|
||||
|
||||
### 2. 定期检查
|
||||
|
||||
建议定期执行以下检查:
|
||||
- 证书有效期
|
||||
- 配置完整性
|
||||
- 网络连接状态
|
||||
|
||||
### 3. 更新维护
|
||||
|
||||
- 定期更新微信支付SDK版本
|
||||
- 监控微信支付平台公告
|
||||
- 及时更新过期证书
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [微信支付证书问题修复指南](./WECHAT_PAY_CERTIFICATE_FIX.md)
|
||||
- [微信支付官方文档](https://pay.weixin.qq.com/doc/v3/merchant/4012153196)
|
||||
- [API安全配置指南](https://pay.weixin.qq.com/doc/v3/merchant/4012153196)
|
||||
|
||||
## 总结
|
||||
|
||||
通过实施以上修复方案,系统现在具备了:
|
||||
1. **自动错误检测和诊断**
|
||||
2. **智能回退机制**
|
||||
3. **详细的错误信息和修复建议**
|
||||
4. **完整的诊断和修复工具**
|
||||
5. **API接口支持**
|
||||
|
||||
这些改进大大提高了微信支付证书问题的可诊断性和可修复性,减少了因证书配置问题导致的支付失败。
|
||||
144
docs/FINAL_FIX_SUMMARY.md
Normal file
144
docs/FINAL_FIX_SUMMARY.md
Normal file
@@ -0,0 +1,144 @@
|
||||
# 微信支付公钥路径修复总结
|
||||
|
||||
## 问题描述
|
||||
|
||||
**错误信息**:`公钥文件不存在: /20250114/0f65a8517c284acb90aa83dd0c23e8f6.pem`
|
||||
|
||||
**根本原因**:开发环境的路径拼接逻辑不正确
|
||||
|
||||
## 修复方案
|
||||
|
||||
### 🔧 已修复的逻辑
|
||||
|
||||
**开发环境**:
|
||||
- 固定使用文件名:`wechatpay_public_key.pem`
|
||||
- 路径格式:`dev/wechat/{tenantId}/wechatpay_public_key.pem`
|
||||
- 实际路径:`/Users/gxwebsoft/JAVA/cms-java-code/src/main/resources/dev/wechat/10547/wechatpay_public_key.pem`
|
||||
|
||||
**生产环境**:
|
||||
- 直接使用数据库中 `pubKey` 字段存储的完整路径
|
||||
- 不进行任何路径拼接
|
||||
|
||||
### 📋 代码逻辑
|
||||
|
||||
```java
|
||||
// 开发环境
|
||||
if ("dev".equals(active)) {
|
||||
// 固定使用 wechatpay_public_key.pem
|
||||
String tenantCertPath = "dev/wechat/" + order.getTenantId();
|
||||
String pubKeyPath = tenantCertPath + "/wechatpay_public_key.pem";
|
||||
|
||||
if (certificateLoader.certificateExists(pubKeyPath)) {
|
||||
String pubKeyFile = certificateLoader.loadCertificatePath(pubKeyPath);
|
||||
// 使用 RSAPublicKeyConfig
|
||||
}
|
||||
}
|
||||
|
||||
// 生产环境
|
||||
else {
|
||||
if (payment.getPubKey() != null && !payment.getPubKey().isEmpty()) {
|
||||
// 直接使用数据库中的路径
|
||||
String pubKeyFile = certificateLoader.loadCertificatePath(payment.getPubKey());
|
||||
// 使用 RSAPublicKeyConfig
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 🎯 预期日志输出
|
||||
|
||||
**开发环境成功**:
|
||||
```
|
||||
=== 检测到公钥配置,使用RSA公钥模式 ===
|
||||
公钥文件: 20250114/0f65a8517c284acb90aa83dd0c23e8f6.pem
|
||||
公钥ID: YOUR_PUBLIC_KEY_ID
|
||||
开发环境公钥文件路径: dev/wechat/10547/wechatpay_public_key.pem
|
||||
✅ 开发环境公钥文件加载成功: /Users/gxwebsoft/JAVA/cms-java-code/src/main/resources/dev/wechat/10547/wechatpay_public_key.pem
|
||||
✅ 开发环境RSA公钥配置成功
|
||||
```
|
||||
|
||||
**生产环境成功**:
|
||||
```
|
||||
=== 生产环境检测到公钥配置,使用RSA公钥模式 ===
|
||||
公钥文件路径: /path/to/production/public_key.pem
|
||||
公钥ID: YOUR_PUBLIC_KEY_ID
|
||||
✅ 生产环境公钥文件加载成功: /actual/file/path
|
||||
✅ 生产环境RSA公钥配置成功
|
||||
```
|
||||
|
||||
### 📁 文件结构要求
|
||||
|
||||
**开发环境**:
|
||||
```
|
||||
src/main/resources/dev/wechat/10547/
|
||||
├── apiclient_key.pem # 商户私钥
|
||||
├── apiclient_cert.pem # 商户证书
|
||||
└── wechatpay_public_key.pem # 微信支付平台公钥(固定文件名)
|
||||
```
|
||||
|
||||
**生产环境**:
|
||||
- 文件可以放在任何位置
|
||||
- 数据库中的 `pubKey` 字段存储完整的相对路径
|
||||
- 例如:`/wechat/10547/public_key.pem`
|
||||
|
||||
### 🚀 测试步骤
|
||||
|
||||
1. **确认文件存在**:
|
||||
```bash
|
||||
ls -la /Users/gxwebsoft/JAVA/cms-java-code/src/main/resources/dev/wechat/10547/wechatpay_public_key.pem
|
||||
```
|
||||
|
||||
2. **确认数据库配置**:
|
||||
```sql
|
||||
SELECT tenant_id, pub_key, pub_key_id
|
||||
FROM sys_payment
|
||||
WHERE tenant_id = 10547 AND type = 0;
|
||||
```
|
||||
|
||||
3. **重新测试支付订单创建**
|
||||
|
||||
### 🔍 故障排除
|
||||
|
||||
**如果仍然报错**:
|
||||
|
||||
1. **检查文件是否存在**:
|
||||
```bash
|
||||
ls -la /Users/gxwebsoft/JAVA/cms-java-code/src/main/resources/dev/wechat/10547/
|
||||
```
|
||||
|
||||
2. **检查文件权限**:
|
||||
```bash
|
||||
chmod 644 /Users/gxwebsoft/JAVA/cms-java-code/src/main/resources/dev/wechat/10547/wechatpay_public_key.pem
|
||||
```
|
||||
|
||||
3. **查看详细日志**:
|
||||
- 关注 "开发环境公钥文件路径" 的输出
|
||||
- 确认路径是否正确
|
||||
|
||||
4. **如果公钥ID不正确**:
|
||||
```sql
|
||||
UPDATE sys_payment SET
|
||||
pub_key_id = 'CORRECT_PUBLIC_KEY_ID'
|
||||
WHERE tenant_id = 10547 AND type = 0;
|
||||
```
|
||||
|
||||
### 📊 配置优先级
|
||||
|
||||
1. **RSA公钥配置**(最高优先级)
|
||||
- 开发环境:固定使用 `wechatpay_public_key.pem`
|
||||
- 生产环境:使用数据库路径
|
||||
|
||||
2. **RSA自动证书配置**
|
||||
- 当没有公钥配置时使用
|
||||
|
||||
3. **RSA手动证书配置**
|
||||
- 作为最后的回退方案
|
||||
|
||||
### ✅ 修复完成
|
||||
|
||||
现在系统应该能够:
|
||||
1. 在开发环境正确找到 `wechatpay_public_key.pem` 文件
|
||||
2. 在生产环境使用数据库中配置的路径
|
||||
3. 成功创建RSA公钥配置
|
||||
4. 避免 `X509Certificate.getSerialNumber() null` 错误
|
||||
|
||||
请重新测试支付订单创建功能!
|
||||
216
docs/SOLUTION_SUMMARY.md
Normal file
216
docs/SOLUTION_SUMMARY.md
Normal file
@@ -0,0 +1,216 @@
|
||||
# 微信支付证书问题解决方案总结
|
||||
|
||||
## 问题现状
|
||||
|
||||
**错误信息**:`Cannot invoke "java.security.cert.X509Certificate.getSerialNumber()" because "certificate" is null`
|
||||
|
||||
**根本原因**:微信支付SDK在使用自动证书配置时无法下载平台证书,导致证书对象为null。
|
||||
|
||||
## 解决方案:使用公钥模式
|
||||
|
||||
### 🎯 推荐方案:RSA公钥配置
|
||||
|
||||
我们已经实现了智能配置检测,系统会按以下优先级选择配置方式:
|
||||
|
||||
1. **RSA公钥配置**(最稳定,推荐)
|
||||
2. **RSA自动证书配置**(需要网络连接)
|
||||
3. **RSA手动证书配置**(回退方案)
|
||||
|
||||
### 📋 配置步骤
|
||||
|
||||
#### 1. 准备公钥文件
|
||||
|
||||
将微信支付平台公钥文件放置到:
|
||||
```
|
||||
src/main/resources/dev/wechat/10547/
|
||||
├── apiclient_key.pem # 商户私钥(已有)
|
||||
├── apiclient_cert.pem # 商户证书(已有)
|
||||
└── wechatpay_public_key.pem # 微信支付平台公钥(新增)
|
||||
```
|
||||
|
||||
#### 2. 数据库配置
|
||||
|
||||
执行以下SQL更新支付配置:
|
||||
|
||||
```sql
|
||||
-- 查看当前配置
|
||||
SELECT id, tenant_id, mch_id, app_id, merchant_serial_number,
|
||||
pub_key, pub_key_id, api_key
|
||||
FROM sys_payment
|
||||
WHERE tenant_id = 10547 AND type = 0;
|
||||
|
||||
-- 更新公钥配置
|
||||
UPDATE sys_payment SET
|
||||
pub_key = 'wechatpay_public_key.pem',
|
||||
pub_key_id = 'YOUR_ACTUAL_PUBLIC_KEY_ID' -- 请替换为实际的公钥ID
|
||||
WHERE tenant_id = 10547 AND type = 0;
|
||||
```
|
||||
|
||||
#### 3. 验证配置
|
||||
|
||||
使用新增的API接口验证配置:
|
||||
|
||||
```bash
|
||||
# 快速检查配置状态
|
||||
GET /system/wechat-pay-diagnostic/check/10547
|
||||
|
||||
# 获取详细配置建议
|
||||
GET /system/wechat-pay-diagnostic/advice/10547
|
||||
```
|
||||
|
||||
### 🔧 已实现的功能
|
||||
|
||||
#### 1. 智能配置检测
|
||||
|
||||
系统会自动检测数据库中的公钥配置:
|
||||
|
||||
```java
|
||||
// 检测逻辑
|
||||
if (payment.getPubKey() != null && !payment.getPubKey().isEmpty() &&
|
||||
payment.getPubKeyId() != null && !payment.getPubKeyId().isEmpty()) {
|
||||
// 使用RSA公钥配置
|
||||
config = new RSAPublicKeyConfig.Builder()...
|
||||
} else {
|
||||
// 回退到自动证书配置
|
||||
config = wechatCertAutoConfig.createAutoConfig()...
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. 详细日志输出
|
||||
|
||||
配置成功时的日志:
|
||||
```
|
||||
=== 检测到公钥配置,使用RSA公钥模式 ===
|
||||
公钥文件: wechatpay_public_key.pem
|
||||
公钥ID: PUB_KEY_ID_0112422897022025011300326200001208
|
||||
公钥文件路径: /path/to/wechatpay_public_key.pem
|
||||
✅ 开发环境RSA公钥配置成功
|
||||
```
|
||||
|
||||
#### 3. 配置诊断API
|
||||
|
||||
新增的API接口:
|
||||
|
||||
| 接口 | 功能 | 说明 |
|
||||
|------|------|------|
|
||||
| `GET /system/wechat-pay-diagnostic/check/{tenantId}` | 快速配置检查 | 检查配置完整性和文件存在性 |
|
||||
| `GET /system/wechat-pay-diagnostic/advice/{tenantId}` | 获取配置建议 | 生成详细的配置建议和修复步骤 |
|
||||
| `GET /system/wechat-pay-diagnostic/diagnose/{tenantId}` | 全面诊断 | 完整的证书诊断报告 |
|
||||
|
||||
#### 4. 配置检查工具
|
||||
|
||||
`WechatPayConfigChecker` 提供:
|
||||
- 配置完整性检查
|
||||
- 文件存在性验证
|
||||
- 配置模式识别
|
||||
- 问题诊断和建议
|
||||
|
||||
### 📊 配置状态检查
|
||||
|
||||
使用配置检查API可以获得详细的状态报告:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "配置检查通过",
|
||||
"data": {
|
||||
"tenantId": 10547,
|
||||
"environment": "dev",
|
||||
"configMode": "公钥模式",
|
||||
"configComplete": true,
|
||||
"hasError": false,
|
||||
"recommendation": "✅ 配置完整,建议使用当前配置",
|
||||
"configDetails": {
|
||||
"merchantId": "1723321338",
|
||||
"appId": "wx1234567890abcdef",
|
||||
"hasPublicKey": true,
|
||||
"publicKeyExists": true,
|
||||
"privateKeyExists": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 🚀 立即行动
|
||||
|
||||
#### 方案A:使用公钥模式(推荐)
|
||||
|
||||
1. **获取公钥文件和ID**:
|
||||
- 从微信商户平台或技术支持获取
|
||||
- 或使用现有的公钥文件
|
||||
|
||||
2. **放置文件**:
|
||||
```bash
|
||||
# 将公钥文件复制到指定位置
|
||||
cp wechatpay_public_key.pem src/main/resources/dev/wechat/10547/
|
||||
```
|
||||
|
||||
3. **更新数据库**:
|
||||
```sql
|
||||
UPDATE sys_payment SET
|
||||
pub_key = 'wechatpay_public_key.pem',
|
||||
pub_key_id = 'YOUR_PUBLIC_KEY_ID'
|
||||
WHERE tenant_id = 10547 AND type = 0;
|
||||
```
|
||||
|
||||
4. **测试验证**:
|
||||
- 重新尝试创建支付订单
|
||||
- 查看日志确认使用公钥模式
|
||||
|
||||
#### 方案B:修复自动证书配置
|
||||
|
||||
如果暂时无法获取公钥,可以:
|
||||
|
||||
1. **检查商户平台设置**:
|
||||
- 确保已开启API安全功能
|
||||
- 申请使用微信支付公钥
|
||||
|
||||
2. **验证网络连接**:
|
||||
- 确保服务器可以访问微信支付API
|
||||
- 检查防火墙和代理设置
|
||||
|
||||
3. **使用诊断工具**:
|
||||
```bash
|
||||
GET /system/wechat-pay-diagnostic/diagnose/10547
|
||||
```
|
||||
|
||||
### 📈 优势对比
|
||||
|
||||
| 配置方式 | 稳定性 | 网络依赖 | 配置难度 | 推荐指数 |
|
||||
|---------|--------|----------|----------|----------|
|
||||
| RSA公钥配置 | ⭐⭐⭐⭐⭐ | 无 | ⭐⭐ | 🔥🔥🔥🔥🔥 |
|
||||
| RSA自动证书配置 | ⭐⭐⭐ | 高 | ⭐ | ⭐⭐⭐ |
|
||||
| RSA手动证书配置 | ⭐⭐⭐ | 无 | ⭐⭐⭐⭐ | ⭐⭐ |
|
||||
|
||||
### 🎯 预期结果
|
||||
|
||||
配置完成后,您应该看到:
|
||||
|
||||
1. **日志输出**:
|
||||
```
|
||||
=== 检测到公钥配置,使用RSA公钥模式 ===
|
||||
✅ 开发环境RSA公钥配置成功
|
||||
```
|
||||
|
||||
2. **支付订单创建成功**:
|
||||
- 不再出现证书null错误
|
||||
- 支付流程正常进行
|
||||
|
||||
3. **配置检查通过**:
|
||||
```
|
||||
GET /system/wechat-pay-diagnostic/check/10547
|
||||
返回:配置检查通过
|
||||
```
|
||||
|
||||
### 📞 技术支持
|
||||
|
||||
如果仍有问题,请:
|
||||
|
||||
1. 使用诊断API获取详细信息
|
||||
2. 查看完整的错误日志
|
||||
3. 提供配置检查结果
|
||||
4. 联系技术支持团队
|
||||
|
||||
---
|
||||
|
||||
**总结**:通过使用公钥模式,可以彻底解决 `X509Certificate.getSerialNumber() null` 错误,提供更稳定可靠的微信支付服务。
|
||||
165
docs/WECHAT_PAY_CERTIFICATE_FIX.md
Normal file
165
docs/WECHAT_PAY_CERTIFICATE_FIX.md
Normal file
@@ -0,0 +1,165 @@
|
||||
# 微信支付证书问题修复指南
|
||||
|
||||
## 问题描述
|
||||
|
||||
错误信息:`创建支付订单失败:创建支付订单失败:Cannot invoke "java.security.cert.X509Certificate.getSerialNumber()" because "certificate" is null`
|
||||
|
||||
## 问题原因
|
||||
|
||||
这个错误通常发生在使用微信支付SDK的 `RSAAutoCertificateConfig` 时,SDK尝试自动下载微信支付平台证书但失败,导致证书对象为null。
|
||||
|
||||
常见原因包括:
|
||||
1. 商户平台未开启API安全功能
|
||||
2. 未申请使用微信支付公钥
|
||||
3. 网络连接问题
|
||||
4. 商户证书序列号错误
|
||||
5. APIv3密钥配置错误
|
||||
|
||||
## 解决方案
|
||||
|
||||
### 1. 商户平台配置
|
||||
|
||||
#### 步骤1:开启API安全功能
|
||||
1. 登录 [微信商户平台](https://pay.weixin.qq.com)
|
||||
2. 进入【账户中心】->【API安全】
|
||||
3. 点击【申请使用微信支付公钥】
|
||||
4. 按照指引完成申请流程
|
||||
|
||||
#### 步骤2:下载证书文件
|
||||
1. 在API安全页面下载商户证书
|
||||
2. 获取以下文件:
|
||||
- `apiclient_cert.pem` (商户证书)
|
||||
- `apiclient_key.pem` (商户私钥)
|
||||
3. 记录商户证书序列号
|
||||
|
||||
#### 步骤3:设置APIv3密钥
|
||||
1. 在API安全页面设置APIv3密钥
|
||||
2. 密钥必须是32位字符串(字母和数字组合)
|
||||
3. 妥善保管密钥,不要泄露
|
||||
|
||||
### 2. 开发环境配置
|
||||
|
||||
#### 证书文件放置
|
||||
将证书文件放置到以下目录:
|
||||
```
|
||||
src/main/resources/dev/wechat/{tenantId}/
|
||||
├── apiclient_key.pem # 必需:商户私钥
|
||||
└── apiclient_cert.pem # 可选:商户证书(自动配置不需要)
|
||||
```
|
||||
|
||||
例如,租户ID为10550的证书路径:
|
||||
```
|
||||
src/main/resources/dev/wechat/10550/
|
||||
├── apiclient_key.pem
|
||||
└── apiclient_cert.pem
|
||||
```
|
||||
|
||||
#### 数据库配置
|
||||
在 `payment` 表中配置以下信息:
|
||||
- `mch_id`: 商户号
|
||||
- `app_id`: 应用ID
|
||||
- `merchant_serial_number`: 商户证书序列号
|
||||
- `api_key`: APIv3密钥(32位)
|
||||
|
||||
### 3. 生产环境配置
|
||||
|
||||
#### 证书文件上传
|
||||
将证书文件上传到服务器指定目录,通常是:
|
||||
```
|
||||
/www/wwwroot/file.ws/file/{相对路径}/
|
||||
```
|
||||
|
||||
#### 数据库配置
|
||||
在 `payment` 表中配置证书文件的相对路径:
|
||||
- `apiclient_key`: 私钥文件相对路径
|
||||
- `apiclient_cert`: 商户证书文件相对路径
|
||||
|
||||
### 4. 代码修复
|
||||
|
||||
系统已经实现了自动回退机制:
|
||||
|
||||
1. **优先使用自动证书配置**:`RSAAutoCertificateConfig`
|
||||
2. **自动回退到手动配置**:如果自动配置失败,会回退到 `RSAConfig` 或 `RSAPublicKeyConfig`
|
||||
3. **详细错误诊断**:提供具体的错误信息和修复建议
|
||||
|
||||
### 5. 诊断工具
|
||||
|
||||
#### 使用证书诊断API
|
||||
```bash
|
||||
# 诊断特定租户的证书配置
|
||||
GET /system/wechat-pay-diagnostic/diagnose/{tenantId}
|
||||
|
||||
# 获取解决方案
|
||||
GET /system/wechat-pay-diagnostic/solutions
|
||||
|
||||
# 测试证书配置
|
||||
POST /system/wechat-pay-diagnostic/test/{tenantId}
|
||||
```
|
||||
|
||||
#### 查看诊断日志
|
||||
在应用日志中查看详细的诊断信息:
|
||||
```
|
||||
=== 微信支付证书诊断报告 ===
|
||||
租户ID: 10550
|
||||
商户号: 1723321338
|
||||
应用ID: wx1234567890abcdef
|
||||
商户证书序列号: 2B933F7C35014A1C363642623E4A62364B34C4EB
|
||||
APIv3密钥: 已配置(32位)
|
||||
证书文件路径: dev/wechat/10550/apiclient_key.pem
|
||||
证书文件存在: 是
|
||||
配置验证结果: 通过
|
||||
```
|
||||
|
||||
## 常见问题排查
|
||||
|
||||
### Q1: 404错误
|
||||
**原因**:商户平台未开启API安全功能
|
||||
**解决**:按照上述步骤1开启API安全功能
|
||||
|
||||
### Q2: 证书序列号不匹配
|
||||
**原因**:数据库中配置的序列号与实际证书不符
|
||||
**解决**:
|
||||
1. 在商户平台查看正确的序列号
|
||||
2. 更新数据库中的 `merchant_serial_number` 字段
|
||||
|
||||
### Q3: APIv3密钥错误
|
||||
**原因**:密钥长度不是32位或包含非法字符
|
||||
**解决**:
|
||||
1. 重新设置32位APIv3密钥
|
||||
2. 确保只包含字母和数字
|
||||
|
||||
### Q4: 私钥文件不存在
|
||||
**原因**:证书文件路径错误或文件未上传
|
||||
**解决**:
|
||||
1. 检查文件路径是否正确
|
||||
2. 确保文件已正确放置
|
||||
|
||||
### Q5: 网络连接问题
|
||||
**原因**:服务器无法访问微信支付API
|
||||
**解决**:
|
||||
1. 检查网络连接
|
||||
2. 确保防火墙允许HTTPS出站连接
|
||||
3. 检查代理设置
|
||||
|
||||
## 最佳实践
|
||||
|
||||
1. **使用自动证书配置**:推荐使用 `RSAAutoCertificateConfig`,可自动管理平台证书
|
||||
2. **定期检查证书有效期**:避免证书过期导致的问题
|
||||
3. **妥善保管私钥**:确保私钥文件安全,不要泄露
|
||||
4. **使用HTTPS**:所有支付相关通信都应使用HTTPS
|
||||
5. **监控日志**:定期查看支付相关日志,及时发现问题
|
||||
|
||||
## 技术支持
|
||||
|
||||
如果按照以上步骤仍无法解决问题,请:
|
||||
|
||||
1. 查看完整的错误日志
|
||||
2. 使用诊断API获取详细信息
|
||||
3. 检查微信商户平台的配置状态
|
||||
4. 联系技术支持团队
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [微信支付官方文档](https://pay.weixin.qq.com/doc/v3/merchant/4012153196)
|
||||
- [API安全配置指南](https://pay.weixin.qq.com/doc/v3/merchant/4012153196)
|
||||
- [证书和回调报文验证](https://pay.weixin.qq.com/doc/v3/wechatpay/wechatpay4_1.shtml)
|
||||
198
docs/WECHAT_PAY_PUBLIC_KEY_CONFIG.md
Normal file
198
docs/WECHAT_PAY_PUBLIC_KEY_CONFIG.md
Normal file
@@ -0,0 +1,198 @@
|
||||
# 微信支付公钥模式配置指南
|
||||
|
||||
## 概述
|
||||
|
||||
如果您的后台系统使用了微信支付公钥模式,系统现在支持自动检测并优先使用公钥配置。这种模式比自动证书配置更稳定,不依赖网络下载平台证书。
|
||||
|
||||
## 配置步骤
|
||||
|
||||
### 1. 获取公钥文件
|
||||
|
||||
从微信商户平台下载或获取以下文件:
|
||||
- 微信支付平台公钥文件(通常以 `.pem` 结尾)
|
||||
- 公钥ID(一个字符串标识符)
|
||||
|
||||
### 2. 放置公钥文件
|
||||
|
||||
将公钥文件放置到对应租户的证书目录:
|
||||
|
||||
```
|
||||
src/main/resources/dev/wechat/{tenantId}/
|
||||
├── apiclient_key.pem # 商户私钥(必需)
|
||||
├── apiclient_cert.pem # 商户证书(可选)
|
||||
└── wechatpay_public_key.pem # 微信支付平台公钥(新增)
|
||||
```
|
||||
|
||||
例如,租户ID为10547的目录结构:
|
||||
```
|
||||
src/main/resources/dev/wechat/10547/
|
||||
├── apiclient_key.pem
|
||||
├── apiclient_cert.pem
|
||||
└── wechatpay_public_key.pem
|
||||
```
|
||||
|
||||
### 3. 数据库配置
|
||||
|
||||
在 `sys_payment` 表中配置公钥相关字段:
|
||||
|
||||
```sql
|
||||
UPDATE sys_payment SET
|
||||
pub_key = 'wechatpay_public_key.pem',
|
||||
pub_key_id = 'YOUR_PUBLIC_KEY_ID'
|
||||
WHERE tenant_id = 10547 AND type = 0;
|
||||
```
|
||||
|
||||
**字段说明**:
|
||||
- `pub_key`: 公钥文件名
|
||||
- `pub_key_id`: 微信支付平台提供的公钥ID
|
||||
|
||||
### 4. 验证配置
|
||||
|
||||
运行测试来验证配置是否正确:
|
||||
|
||||
```bash
|
||||
# 运行公钥配置测试
|
||||
mvn test -Dtest=WechatPayPublicKeyTest#testPublicKeyConfiguration
|
||||
```
|
||||
|
||||
## 配置优先级
|
||||
|
||||
系统会按以下优先级选择配置方式:
|
||||
|
||||
1. **RSA公钥配置**(最高优先级)
|
||||
- 条件:数据库中配置了 `pub_key` 和 `pub_key_id`
|
||||
- 优势:稳定、不依赖网络、配置简单
|
||||
|
||||
2. **RSA自动证书配置**
|
||||
- 条件:公钥配置不可用时
|
||||
- 优势:自动管理平台证书
|
||||
- 劣势:依赖网络连接和商户平台API安全设置
|
||||
|
||||
3. **RSA手动证书配置**(回退方案)
|
||||
- 条件:自动配置失败时
|
||||
- 需要:商户证书文件
|
||||
|
||||
## 示例配置
|
||||
|
||||
### 开发环境示例
|
||||
|
||||
**目录结构**:
|
||||
```
|
||||
src/main/resources/dev/wechat/10547/
|
||||
├── apiclient_key.pem
|
||||
├── apiclient_cert.pem
|
||||
└── wechatpay_public_key.pem
|
||||
```
|
||||
|
||||
**数据库配置**:
|
||||
```sql
|
||||
-- 查看当前配置
|
||||
SELECT id, tenant_id, mch_id, app_id, merchant_serial_number,
|
||||
pub_key, pub_key_id, api_key
|
||||
FROM sys_payment
|
||||
WHERE tenant_id = 10547 AND type = 0;
|
||||
|
||||
-- 更新公钥配置
|
||||
UPDATE sys_payment SET
|
||||
pub_key = 'wechatpay_public_key.pem',
|
||||
pub_key_id = 'PUB_KEY_ID_0112422897022025011300326200001208'
|
||||
WHERE tenant_id = 10547 AND type = 0;
|
||||
```
|
||||
|
||||
### 生产环境示例
|
||||
|
||||
**证书文件路径**:
|
||||
```
|
||||
/www/wwwroot/file.ws/file/wechat/10547/
|
||||
├── apiclient_key.pem
|
||||
├── apiclient_cert.pem
|
||||
└── wechatpay_public_key.pem
|
||||
```
|
||||
|
||||
**数据库配置**:
|
||||
```sql
|
||||
UPDATE sys_payment SET
|
||||
apiclient_key = '/wechat/10547/apiclient_key.pem',
|
||||
apiclient_cert = '/wechat/10547/apiclient_cert.pem',
|
||||
pub_key = '/wechat/10547/wechatpay_public_key.pem',
|
||||
pub_key_id = 'PUB_KEY_ID_0112422897022025011300326200001208'
|
||||
WHERE tenant_id = 10547 AND type = 0;
|
||||
```
|
||||
|
||||
## 日志输出
|
||||
|
||||
配置成功后,您会在日志中看到:
|
||||
|
||||
```
|
||||
=== 检测到公钥配置,使用RSA公钥模式 ===
|
||||
公钥文件: wechatpay_public_key.pem
|
||||
公钥ID: PUB_KEY_ID_0112422897022025011300326200001208
|
||||
公钥文件路径: /path/to/wechatpay_public_key.pem
|
||||
✅ 开发环境RSA公钥配置成功
|
||||
```
|
||||
|
||||
如果没有公钥配置,系统会尝试自动证书配置:
|
||||
|
||||
```
|
||||
=== 尝试创建自动证书配置 ===
|
||||
商户号: 1723321338
|
||||
私钥路径: /path/to/apiclient_key.pem
|
||||
序列号: 2B933F7C35014A1C363642623E4A62364B34C4EB
|
||||
API密钥长度: 32
|
||||
```
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 1. 公钥文件不存在
|
||||
|
||||
**错误信息**:
|
||||
```
|
||||
❌ 公钥文件不存在: dev/wechat/10547/wechatpay_public_key.pem
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
- 检查文件路径是否正确
|
||||
- 确认文件已放置在正确位置
|
||||
- 验证文件名与数据库配置一致
|
||||
|
||||
### 2. 公钥ID错误
|
||||
|
||||
**错误信息**:
|
||||
```
|
||||
❌ RSA公钥配置失败: Invalid public key ID
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
- 检查公钥ID是否正确
|
||||
- 确认公钥ID与公钥文件匹配
|
||||
- 联系微信支付技术支持获取正确的公钥ID
|
||||
|
||||
### 3. 数据库配置缺失
|
||||
|
||||
**现象**:系统跳过公钥配置,直接尝试自动证书配置
|
||||
|
||||
**解决方案**:
|
||||
```sql
|
||||
-- 检查当前配置
|
||||
SELECT pub_key, pub_key_id FROM sys_payment WHERE tenant_id = 10547 AND type = 0;
|
||||
|
||||
-- 如果字段为空,进行配置
|
||||
UPDATE sys_payment SET
|
||||
pub_key = 'wechatpay_public_key.pem',
|
||||
pub_key_id = 'YOUR_PUBLIC_KEY_ID'
|
||||
WHERE tenant_id = 10547 AND type = 0;
|
||||
```
|
||||
|
||||
## 优势对比
|
||||
|
||||
| 配置方式 | 稳定性 | 网络依赖 | 配置复杂度 | 推荐度 |
|
||||
|---------|--------|----------|------------|--------|
|
||||
| RSA公钥配置 | 高 | 无 | 低 | ⭐⭐⭐⭐⭐ |
|
||||
| RSA自动证书配置 | 中 | 高 | 低 | ⭐⭐⭐ |
|
||||
| RSA手动证书配置 | 中 | 无 | 高 | ⭐⭐ |
|
||||
|
||||
## 总结
|
||||
|
||||
使用公钥模式可以有效避免 `X509Certificate.getSerialNumber() null` 错误,因为它不依赖自动下载平台证书。建议优先使用此配置方式。
|
||||
|
||||
如果您已经有公钥文件和公钥ID,按照本指南配置后,系统会自动使用更稳定的公钥模式。
|
||||
31
docs/fix_public_key_path.sql
Normal file
31
docs/fix_public_key_path.sql
Normal file
@@ -0,0 +1,31 @@
|
||||
-- 修复租户10547的公钥路径配置
|
||||
|
||||
-- 1. 查看当前配置
|
||||
SELECT
|
||||
id,
|
||||
tenant_id,
|
||||
mch_id,
|
||||
pub_key,
|
||||
pub_key_id
|
||||
FROM sys_payment
|
||||
WHERE tenant_id = 10547 AND type = 0;
|
||||
|
||||
-- 2. 修复公钥路径配置
|
||||
UPDATE sys_payment SET
|
||||
pub_key = 'wechatpay_public_key.pem'
|
||||
WHERE tenant_id = 10547 AND type = 0;
|
||||
|
||||
-- 3. 验证修复结果
|
||||
SELECT
|
||||
id,
|
||||
tenant_id,
|
||||
mch_id,
|
||||
pub_key,
|
||||
pub_key_id,
|
||||
CASE
|
||||
WHEN pub_key = 'wechatpay_public_key.pem'
|
||||
THEN '✅ 路径已修复'
|
||||
ELSE '❌ 路径仍有问题'
|
||||
END AS path_status
|
||||
FROM sys_payment
|
||||
WHERE tenant_id = 10547 AND type = 0;
|
||||
63
docs/update_payment_public_key.sql
Normal file
63
docs/update_payment_public_key.sql
Normal file
@@ -0,0 +1,63 @@
|
||||
-- 微信支付公钥配置SQL脚本
|
||||
-- 适用于租户ID: 10547
|
||||
|
||||
-- 1. 查看当前支付配置
|
||||
SELECT
|
||||
id,
|
||||
tenant_id,
|
||||
mch_id,
|
||||
app_id,
|
||||
merchant_serial_number,
|
||||
pub_key,
|
||||
pub_key_id,
|
||||
api_key,
|
||||
apiclient_key,
|
||||
apiclient_cert
|
||||
FROM sys_payment
|
||||
WHERE tenant_id = 10547 AND type = 0;
|
||||
|
||||
-- 2. 更新公钥配置(请根据实际情况修改公钥ID)
|
||||
UPDATE sys_payment SET
|
||||
pub_key = 'wechatpay_public_key.pem',
|
||||
pub_key_id = 'PUB_KEY_ID_0112422897022025011300326200001208' -- 请替换为实际的公钥ID
|
||||
WHERE tenant_id = 10547 AND type = 0;
|
||||
|
||||
-- 3. 验证更新结果
|
||||
SELECT
|
||||
id,
|
||||
tenant_id,
|
||||
mch_id,
|
||||
app_id,
|
||||
merchant_serial_number,
|
||||
pub_key,
|
||||
pub_key_id,
|
||||
CASE
|
||||
WHEN pub_key IS NOT NULL AND pub_key != '' AND pub_key_id IS NOT NULL AND pub_key_id != ''
|
||||
THEN '✅ 公钥配置完整'
|
||||
ELSE '❌ 公钥配置不完整'
|
||||
END AS config_status
|
||||
FROM sys_payment
|
||||
WHERE tenant_id = 10547 AND type = 0;
|
||||
|
||||
-- 4. 如果需要清除公钥配置(回退到自动证书模式)
|
||||
-- UPDATE sys_payment SET
|
||||
-- pub_key = NULL,
|
||||
-- pub_key_id = NULL
|
||||
-- WHERE tenant_id = 10547 AND type = 0;
|
||||
|
||||
-- 5. 检查所有租户的公钥配置状态
|
||||
SELECT
|
||||
tenant_id,
|
||||
mch_id,
|
||||
CASE
|
||||
WHEN pub_key IS NOT NULL AND pub_key != '' AND pub_key_id IS NOT NULL AND pub_key_id != ''
|
||||
THEN '公钥模式'
|
||||
WHEN merchant_serial_number IS NOT NULL AND merchant_serial_number != ''
|
||||
THEN '自动证书模式'
|
||||
ELSE '配置不完整'
|
||||
END AS payment_mode,
|
||||
pub_key,
|
||||
pub_key_id
|
||||
FROM sys_payment
|
||||
WHERE type = 0
|
||||
ORDER BY tenant_id;
|
||||
Reference in New Issue
Block a user