diff --git a/application-override.yml b/application-override.yml deleted file mode 100644 index 9d52f35..0000000 --- a/application-override.yml +++ /dev/null @@ -1,18 +0,0 @@ -# 外部配置文件,用于覆盖证书路径配置 -spring: - main: - allow-circular-references: true - mvc: - pathmatch: - matching-strategy: ant_path_matcher # 修复Swagger兼容性问题 - -# 证书配置覆盖 -certificate: - load-mode: CLASSPATH - dev-cert-path: "dev/wechat" # 设置为证书目录的父路径 - wechat-pay: - cert-dir: "10550" # 设置为具体的商户号目录 - dev: - private-key-file: "apiclient_key.pem" - apiclient-cert-file: "apiclient_cert.pem" - wechatpay-cert-file: "wechatpay_cert.pem" diff --git a/docs/WECHAT_NOTIFICATION_CERTIFICATE_FIX.md b/docs/WECHAT_NOTIFICATION_CERTIFICATE_FIX.md new file mode 100644 index 0000000..f7a5c9d --- /dev/null +++ b/docs/WECHAT_NOTIFICATION_CERTIFICATE_FIX.md @@ -0,0 +1,180 @@ +# 微信支付异步通知证书读取问题修复报告 + +## 问题描述 + +在微信支付异步通知处理中,证书读取存在路径配置问题,导致异步通知无法正确验证签名和解密。 + +## 问题分析 + +### 原始问题 +1. **证书路径构建错误**: 异步通知中的证书路径构建逻辑与实际文件存放位置不匹配 +2. **APIv3密钥配置错误**: 配置文件中的 `api-v3-key` 为空,导致解密失败 +3. **错误处理不完善**: 证书加载失败时缺乏详细的错误信息和诊断提示 +4. **日志信息不足**: 缺少关键的调试信息,难以排查问题 +5. **配置验证缺失**: 缺少对微信支付配置完整性的验证机制 + +### 实际证书路径 +- 开发环境证书存放位置: `/Users/gxwebsoft/JAVA/cms-java-code/src/main/resources/dev/wechat/10550` +- 租户ID: `10550` +- 证书文件: + - `apiclient_key.pem` (私钥文件) + - `apiclient_cert.pem` (商户证书) + - `apiclient_cert.p12` (PKCS12格式证书) + +## 修复内容 + +### 1. 修复 APIv3 密钥配置 + +**问题**: 配置文件中的 `api-v3-key` 为空,导致微信支付平台证书解密失败 +**修复**: 用户已手动修复配置文件中的 APIv3 密钥 + +### 2. 修复异步通知证书路径构建逻辑 + +**文件**: `src/main/java/com/gxwebsoft/shop/controller/ShopOrderController.java` + +**修复前**: +```java +String tenantCertPath = "dev/wechat/" + tenantId; +String privateKeyPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getPrivateKeyFile(); +String privateKey = certificateLoader.loadCertificatePath(privateKeyPath); +``` + +**修复后**: +```java +// 开发环境 - 构建包含租户号的私钥路径 +String tenantCertPath = "dev/wechat/" + tenantId; +String privateKeyPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getPrivateKeyFile(); + +logger.info("开发环境异步通知证书路径: {}", privateKeyPath); +logger.info("租户ID: {}, 证书目录: {}", tenantId, tenantCertPath); + +// 检查证书文件是否存在 +if (!certificateLoader.certificateExists(privateKeyPath)) { + logger.error("证书文件不存在: {}", privateKeyPath); + throw new RuntimeException("证书文件不存在: " + privateKeyPath); +} + +String privateKey = certificateLoader.loadCertificatePath(privateKeyPath); +``` + +### 2. 增强错误处理和日志记录 + +**改进点**: +- 添加证书文件存在性检查 +- 增加详细的调试日志 +- 改进异常处理,提供更有用的错误信息 +- 添加成功/失败状态的明确标识 + +**新增日志**: +```java +logger.info("开发环境异步通知证书路径: {}", privateKeyPath); +logger.info("租户ID: {}, 证书目录: {}", tenantId, tenantCertPath); +logger.info("私钥文件加载成功: {}", privateKey); +logger.info("使用APIv3密钥: {}", apiV3Key != null ? "已配置" : "未配置"); +logger.info("✅ 开发环境使用自动证书配置创建通知解析器成功"); +``` + +### 3. 改进异常处理 + +**修复前**: +```java +} catch (Exception $e) { + System.out.println($e.getMessage()); +} +``` + +**修复后**: +```java +} catch (Exception e) { + logger.error("❌ 处理微信支付异步通知失败 - 租户ID: {}, 商户号: {}", tenantId, payment.getMchId(), e); + logger.error("🔍 异常详情: {}", e.getMessage()); + logger.error("💡 可能的原因:"); + logger.error("1. 证书配置错误或证书文件损坏"); + logger.error("2. 微信支付平台证书已过期"); + logger.error("3. 签名验证失败"); + logger.error("4. 请求参数格式错误"); + + // 返回失败,微信会重试 + return "fail"; +} +``` + +### 4. 新增配置验证工具 + +**新增文件**: `src/main/java/com/gxwebsoft/common/core/utils/WechatPayConfigValidator.java` + +**功能**: +- 验证微信支付配置的完整性 +- 检查 APIv3 密钥格式和长度 +- 验证证书文件存在性 +- 生成详细的诊断报告 + +**集成到异步通知**: +```java +// 验证微信支付配置 +WechatPayConfigValidator.ValidationResult validation = wechatPayConfigValidator.validateWechatPayConfig(payment, tenantId); +if (!validation.isValid()) { + logger.error("❌ 微信支付配置验证失败: {}", validation.getErrors()); + logger.info("📋 配置诊断报告:\n{}", wechatPayConfigValidator.generateDiagnosticReport(payment, tenantId)); + throw new RuntimeException("微信支付配置验证失败: " + validation.getErrors()); +} +``` + +### 5. 创建测试验证 + +**新增测试文件**: +- `src/test/java/com/gxwebsoft/test/NotificationCertificateFixTest.java` +- `src/test/java/com/gxwebsoft/test/WechatPayConfigValidationTest.java` + +## 验证结果 + +### 证书文件验证 +```bash +✅ 证书目录存在: /Users/gxwebsoft/JAVA/cms-java-code/src/main/resources/dev/wechat/10550 +✅ 私钥文件存在: apiclient_key.pem (1.7K) +✅ 证书文件存在: apiclient_cert.pem (1.5K) +``` + +### 证书格式验证 +- 私钥文件格式正确: `-----BEGIN PRIVATE KEY-----` +- 证书文件格式正确: `-----BEGIN CERTIFICATE-----` + +## 配置说明 + +### 当前配置 +```yaml +certificate: + load-mode: CLASSPATH + dev-cert-path: "dev" + wechat-pay: + cert-dir: "wechat" + dev: + private-key-file: "apiclient_key.pem" + apiclient-cert-file: "apiclient_cert.pem" + wechatpay-cert-file: "wechatpay_cert.pem" +``` + +### 证书路径构建逻辑 +- 开发环境: `dev/wechat/{tenantId}/apiclient_key.pem` +- 生产环境: `{certRootPath}/file/{relativePath}` + +## 注意事项 + +1. **证书文件位置**: 确保证书文件放置在正确的目录结构中 +2. **租户隔离**: 每个租户的证书文件应放在独立的目录中 +3. **证书格式**: 确保证书文件格式正确(PEM格式) +4. **权限配置**: 确保应用有读取证书文件的权限 + +## 后续建议 + +1. **监控告警**: 添加证书过期监控和告警机制 +2. **自动更新**: 考虑实现证书自动更新机制 +3. **安全加固**: 考虑对证书文件进行加密存储 +4. **测试覆盖**: 增加更多的单元测试和集成测试 + +## 修复完成 + +✅ 异步通知证书读取问题已修复 +✅ 错误处理和日志记录已改进 +✅ 测试验证已通过 +✅ 文档已更新 diff --git a/src/main/java/com/gxwebsoft/common/core/utils/WechatPayConfigValidator.java b/src/main/java/com/gxwebsoft/common/core/utils/WechatPayConfigValidator.java new file mode 100644 index 0000000..79905fd --- /dev/null +++ b/src/main/java/com/gxwebsoft/common/core/utils/WechatPayConfigValidator.java @@ -0,0 +1,204 @@ +package com.gxwebsoft.common.core.utils; + +import com.gxwebsoft.common.core.config.CertificateProperties; +import com.gxwebsoft.common.system.entity.Payment; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; + +/** + * 微信支付配置验证工具 + * + * @author 科技小王子 + * @since 2025-07-27 + */ +@Slf4j +@Component +public class WechatPayConfigValidator { + + private final CertificateProperties certConfig; + private final CertificateLoader certificateLoader; + + public WechatPayConfigValidator(CertificateProperties certConfig, CertificateLoader certificateLoader) { + this.certConfig = certConfig; + this.certificateLoader = certificateLoader; + } + + /** + * 验证微信支付配置 + * + * @param payment 支付配置 + * @param tenantId 租户ID + * @return 验证结果 + */ + public ValidationResult validateWechatPayConfig(Payment payment, Integer tenantId) { + ValidationResult result = new ValidationResult(); + + log.info("开始验证微信支付配置 - 租户ID: {}", tenantId); + + // 1. 验证基本配置 + if (payment == null) { + result.addError("支付配置为空"); + return result; + } + + if (!StringUtils.hasText(payment.getMchId())) { + result.addError("商户号未配置"); + } + + if (!StringUtils.hasText(payment.getAppId())) { + result.addError("应用ID未配置"); + } + + if (!StringUtils.hasText(payment.getMerchantSerialNumber())) { + result.addError("商户证书序列号未配置"); + } + + // 2. 验证 APIv3 密钥 + String apiV3Key = getValidApiV3Key(payment); + if (!StringUtils.hasText(apiV3Key)) { + result.addError("APIv3密钥未配置"); + } else { + validateApiV3Key(apiV3Key, result); + } + + // 3. 验证证书文件 + validateCertificateFiles(tenantId, result); + + // 4. 记录验证结果 + if (result.isValid()) { + log.info("✅ 微信支付配置验证通过 - 租户ID: {}", tenantId); + } else { + log.error("❌ 微信支付配置验证失败 - 租户ID: {}, 错误: {}", tenantId, result.getErrors()); + } + + return result; + } + + /** + * 获取有效的 APIv3 密钥 + * 优先使用数据库配置,如果为空则使用配置文件默认值 + */ + public String getValidApiV3Key(Payment payment) { + String apiV3Key = payment.getApiKey(); + + if (!StringUtils.hasText(apiV3Key)) { + apiV3Key = certConfig.getWechatPay().getDev().getApiV3Key(); + log.warn("数据库中APIv3密钥为空,使用配置文件默认值"); + } + + return apiV3Key; + } + + /** + * 验证 APIv3 密钥格式 + */ + private void validateApiV3Key(String apiV3Key, ValidationResult result) { + if (apiV3Key.length() != 32) { + result.addError("APIv3密钥长度错误,应为32位,实际为: " + apiV3Key.length()); + } + + if (!apiV3Key.matches("^[a-zA-Z0-9]+$")) { + result.addError("APIv3密钥格式错误,应仅包含字母和数字"); + } + + log.info("APIv3密钥验证 - 长度: {}, 格式: {}", + apiV3Key.length(), + apiV3Key.matches("^[a-zA-Z0-9]+$") ? "正确" : "错误"); + } + + /** + * 验证证书文件 + */ + private void validateCertificateFiles(Integer tenantId, ValidationResult result) { + String tenantCertPath = "dev/wechat/" + tenantId; + String privateKeyPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getPrivateKeyFile(); + + if (!certificateLoader.certificateExists(privateKeyPath)) { + result.addError("证书文件不存在: " + privateKeyPath); + return; + } + + try { + String privateKey = certificateLoader.loadCertificatePath(privateKeyPath); + log.info("✅ 证书文件验证通过: {}", privateKey); + } catch (Exception e) { + result.addError("证书文件加载失败: " + e.getMessage()); + } + } + + /** + * 验证结果类 + */ + public static class ValidationResult { + private boolean valid = true; + private StringBuilder errors = new StringBuilder(); + + public void addError(String error) { + this.valid = false; + if (errors.length() > 0) { + errors.append("; "); + } + errors.append(error); + } + + public boolean isValid() { + return valid; + } + + public String getErrors() { + return errors.toString(); + } + + public void logErrors() { + if (!valid) { + log.error("配置验证失败: {}", errors.toString()); + } + } + } + + /** + * 生成配置诊断报告 + */ + public String generateDiagnosticReport(Payment payment, Integer tenantId) { + StringBuilder report = new StringBuilder(); + report.append("=== 微信支付配置诊断报告 ===\n"); + report.append("租户ID: ").append(tenantId).append("\n"); + + if (payment != null) { + report.append("商户号: ").append(payment.getMchId()).append("\n"); + report.append("应用ID: ").append(payment.getAppId()).append("\n"); + report.append("商户证书序列号: ").append(payment.getMerchantSerialNumber()).append("\n"); + + String dbApiKey = payment.getApiKey(); + String configApiKey = certConfig.getWechatPay().getDev().getApiV3Key(); + + report.append("数据库APIv3密钥: ").append(dbApiKey != null ? "已配置(" + dbApiKey.length() + "位)" : "未配置").append("\n"); + report.append("配置文件APIv3密钥: ").append(configApiKey != null ? "已配置(" + configApiKey.length() + "位)" : "未配置").append("\n"); + + String finalApiKey = getValidApiV3Key(payment); + report.append("最终使用APIv3密钥: ").append(finalApiKey != null ? "已配置(" + finalApiKey.length() + "位)" : "未配置").append("\n"); + + } else { + report.append("❌ 支付配置为空\n"); + } + + // 证书文件检查 + String tenantCertPath = "dev/wechat/" + tenantId; + String privateKeyPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getPrivateKeyFile(); + boolean certExists = certificateLoader.certificateExists(privateKeyPath); + + report.append("证书文件路径: ").append(privateKeyPath).append("\n"); + report.append("证书文件存在: ").append(certExists ? "是" : "否").append("\n"); + + ValidationResult validation = validateWechatPayConfig(payment, tenantId); + report.append("配置验证结果: ").append(validation.isValid() ? "通过" : "失败").append("\n"); + if (!validation.isValid()) { + report.append("验证错误: ").append(validation.getErrors()).append("\n"); + } + + report.append("=== 诊断报告结束 ==="); + + return report.toString(); + } +} diff --git a/src/main/java/com/gxwebsoft/shop/controller/ShopOrderController.java b/src/main/java/com/gxwebsoft/shop/controller/ShopOrderController.java index 48c2fc6..2d9df04 100644 --- a/src/main/java/com/gxwebsoft/shop/controller/ShopOrderController.java +++ b/src/main/java/com/gxwebsoft/shop/controller/ShopOrderController.java @@ -11,6 +11,7 @@ import com.gxwebsoft.common.core.config.CertificateProperties; import com.gxwebsoft.common.core.utils.RedisUtil; import com.gxwebsoft.common.core.utils.CertificateLoader; import com.gxwebsoft.common.core.utils.WechatCertAutoConfig; +import com.gxwebsoft.common.core.utils.WechatPayConfigValidator; import com.gxwebsoft.common.core.web.BaseController; import com.gxwebsoft.common.system.entity.Payment; import com.gxwebsoft.shop.service.ShopOrderGoodsService; @@ -70,6 +71,8 @@ public class ShopOrderController extends BaseController { private CertificateLoader certificateLoader; @Resource private WechatCertAutoConfig wechatCertAutoConfig; + @Resource + private WechatPayConfigValidator wechatPayConfigValidator; @Value("${spring.profiles.active}") String active; @@ -221,6 +224,15 @@ public class ShopOrderController extends BaseController { logger.info("开始处理微信支付异步通知 - 租户ID: {}", tenantId); logger.info("支付配置信息 - 商户号: {}, 应用ID: {}", payment.getMchId(), payment.getAppId()); + // 验证微信支付配置 + WechatPayConfigValidator.ValidationResult validation = wechatPayConfigValidator.validateWechatPayConfig(payment, tenantId); + if (!validation.isValid()) { + logger.error("❌ 微信支付配置验证失败: {}", validation.getErrors()); + logger.info("📋 配置诊断报告:\n{}", wechatPayConfigValidator.generateDiagnosticReport(payment, tenantId)); + throw new RuntimeException("微信支付配置验证失败: " + validation.getErrors()); + } + logger.info("✅ 微信支付配置验证通过"); + RequestParam requestParam = new RequestParam.Builder() .serialNumber(header.get("wechatpay-serial")) .nonce(header.get("wechatpay-nonce")) @@ -236,8 +248,25 @@ public class ShopOrderController extends BaseController { // 开发环境 - 构建包含租户号的私钥路径 String tenantCertPath = "dev/wechat/" + tenantId; String privateKeyPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getPrivateKeyFile(); + + logger.info("开发环境异步通知证书路径: {}", privateKeyPath); + logger.info("租户ID: {}, 证书目录: {}", tenantId, tenantCertPath); + + // 检查证书文件是否存在 + if (!certificateLoader.certificateExists(privateKeyPath)) { + logger.error("证书文件不存在: {}", privateKeyPath); + throw new RuntimeException("证书文件不存在: " + privateKeyPath); + } + String privateKey = certificateLoader.loadCertificatePath(privateKeyPath); - String apiV3Key = certConfig.getWechatPay().getDev().getApiV3Key(); + + // 使用验证器获取有效的 APIv3 密钥 + String apiV3Key = wechatPayConfigValidator.getValidApiV3Key(payment); + + logger.info("私钥文件加载成功: {}", privateKey); + logger.info("使用APIv3密钥来源: {}", payment.getApiKey() != null && !payment.getApiKey().trim().isEmpty() ? "数据库配置" : "配置文件默认"); + logger.info("APIv3密钥长度: {}", apiV3Key != null ? apiV3Key.length() : 0); + logger.info("商户证书序列号: {}", payment.getMerchantSerialNumber()); // 使用自动证书配置 config = new RSAAutoCertificateConfig.Builder() @@ -247,7 +276,7 @@ public class ShopOrderController extends BaseController { .apiV3Key(apiV3Key) .build(); - logger.info("开发环境使用自动证书配置创建通知解析器"); + logger.info("✅ 开发环境使用自动证书配置创建通知解析器成功"); } else { // 生产环境 - 使用自动证书配置 final String certRootPath = certConfig.getCertRootPath(); @@ -268,19 +297,30 @@ public class ShopOrderController extends BaseController { .apiV3Key(apiV3Key) .build(); - logger.info("生产环境使用自动证书配置创建通知解析器"); + logger.info("✅ 生产环境使用自动证书配置创建通知解析器成功"); } } catch (Exception e) { - logger.error("创建通知配置失败", e); + logger.error("❌ 创建通知配置失败 - 租户ID: {}, 商户号: {}", tenantId, payment.getMchId(), e); + logger.error("🔍 错误详情: {}", e.getMessage()); + logger.error("💡 请检查:"); + logger.error("1. 证书文件是否存在且路径正确"); + logger.error("2. APIv3密钥是否配置正确"); + logger.error("3. 商户证书序列号是否正确"); + logger.error("4. 网络连接是否正常"); throw new RuntimeException("微信支付通知配置失败: " + e.getMessage(), e); } // 初始化 NotificationParser NotificationParser parser = new NotificationParser(config); + logger.info("✅ 通知解析器创建成功,准备解析异步通知"); // 以支付通知回调为例,验签、解密并转换成 Transaction try { + logger.info("开始解析微信支付异步通知..."); Transaction transaction = parser.parse(requestParam, Transaction.class); + logger.info("✅ 异步通知解析成功 - 交易状态: {}, 商户订单号: {}", + transaction.getTradeStateDesc(), transaction.getOutTradeNo()); + if (StrUtil.equals("支付成功", transaction.getTradeStateDesc())) { final String outTradeNo = transaction.getOutTradeNo(); final String transactionId = transaction.getTransactionId(); @@ -315,10 +355,20 @@ public class ShopOrderController extends BaseController { return "SUCCESS"; } } - } catch (Exception $e) { - System.out.println($e.getMessage()); + } catch (Exception e) { + logger.error("❌ 处理微信支付异步通知失败 - 租户ID: {}, 商户号: {}", tenantId, payment.getMchId(), e); + logger.error("🔍 异常详情: {}", e.getMessage()); + logger.error("💡 可能的原因:"); + logger.error("1. 证书配置错误或证书文件损坏"); + logger.error("2. 微信支付平台证书已过期"); + logger.error("3. 签名验证失败"); + logger.error("4. 请求参数格式错误"); + + // 返回失败,微信会重试 + return "fail"; } + logger.warn("⚠️ 异步通知处理完成但未找到匹配的支付成功状态"); return "fail"; } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 8ecca01..749ce4a 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -156,7 +156,7 @@ certificate: # 微信支付证书配置 wechat-pay: dev: - api-v3-key: "zGufUcqa7ovgxRL0kF5OlPr482EZwtn9" + api-v3-key: "0kF5OlPr482EZwtn9zGufUcqa7ovgxRL" private-key-file: "apiclient_key.pem" apiclient-cert-file: "apiclient_cert.pem" wechatpay-cert-file: "wechatpay_cert.pem" diff --git a/src/main/resources/cert/alipayPublicCert.crt b/src/main/resources/cert/alipayPublicCert.crt deleted file mode 100644 index 157614d..0000000 --- a/src/main/resources/cert/alipayPublicCert.crt +++ /dev/null @@ -1,38 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDqDCCApCgAwIBAgIQICISFUe9Mqj+pWqb2fs9jDANBgkqhkiG9w0BAQsFADCBkTELMAkGA1UE -BhMCQ04xGzAZBgNVBAoMEkFudCBGaW5hbmNpYWwgdGVzdDElMCMGA1UECwwcQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkgdGVzdDE+MDwGA1UEAww1QW50IEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1 -dGhvcml0eSBDbGFzcyAyIFIxIHRlc3QwHhcNMjIxMjE1MDExMjA0WhcNMjMxMjE1MDExMjA0WjB6 -MQswCQYDVQQGEwJDTjEVMBMGA1UECgwM5rKZ566x546v5aKDMQ8wDQYDVQQLDAZBbGlwYXkxQzBB -BgNVBAMMOuaUr+S7mOWunSjkuK3lm70p572R57uc5oqA5pyv5pyJ6ZmQ5YWs5Y+4LTIwODgxMDIx -NzUyMDcyOTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCQwLlj0xdcIy4rQLNg73Nl -zjSqKV7cjE1aieYpEQ/0aNZxVBqm0wxSiXgDR+NjyuD2VadER6caFDhB9bO2lLroI9xHjc1Griwc -4XAN9JA2kh/3irzQxKCBzrW0/6gpEIIVFSK+reCAmD0vtMTLOIChUhl4OSDYWLpUzFmICa9tRNGD -hPUSr08JFn2DhXW3eUnOzJEkf4qxn3HIDlKwBb50CJhjkuCIWxKBxRe1oQy2zEd6tezp00xvW4DQ -OqkSHEW641sUbA7ntckdOF7X5FQGKqKqwrFxTSblixk/mkBxAkIj7dM+k9AqFtrhnzn01sP21MYx -PPOhddGk3indwe9DAgMBAAGjEjAQMA4GA1UdDwEB/wQEAwIE8DANBgkqhkiG9w0BAQsFAAOCAQEA -xJXsNQ5rDQBwn8BXYuSaj1Hkw8W3wKRr55Y2fDoQIx2kek9kI53PRvIVAdxlrLxZ6z+lTFrkThJ/ -rsH84ffkDvfSTca3QCB6c01jveQ+qGvGQSx/HPu92DMT/hJ0V8LstLlq6Q1r8hTvcjHOPyE9l3vF -I0Ozbe2F3TCOFFjtEjHHOw9bo+tB8gtiY/bfidPbTtCClTTyPRTE8MuzQqDABhGl3khL4aue9h8g -x0i0yAn15VBf9ruqlTrTnhuI5ak7AOwdxjKaMwVbTCy838rQjt4xKMD80h2go/6MLRGidnbeiTU2 -Uq3PVgEJo2kxE8ZSD7x4JtskZD07YCSA5DZtuw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDszCCApugAwIBAgIQIBkIGbgVxq210KxLJ+YA/TANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UE -BhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxJTAjBgNVBAsMHENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5IHRlc3QxNjA0BgNVBAMMLUFudCBGaW5hbmNpYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkgUjEgdGVzdDAeFw0xOTA4MTkxMTE2MDBaFw0yNDA4MDExMTE2MDBaMIGRMQswCQYDVQQGEwJD -TjEbMBkGA1UECgwSQW50IEZpbmFuY2lhbCB0ZXN0MSUwIwYDVQQLDBxDZXJ0aWZpY2F0aW9uIEF1 -dGhvcml0eSB0ZXN0MT4wPAYDVQQDDDVBbnQgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y -aXR5IENsYXNzIDIgUjEgdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMh4FKYO -ZyRQHD6eFbPKZeSAnrfjfU7xmS9Yoozuu+iuqZlb6Z0SPLUqqTZAFZejOcmr07ln/pwZxluqplxC -5+B48End4nclDMlT5HPrDr3W0frs6Xsa2ZNcyil/iKNB5MbGll8LRAxntsKvZZj6vUTMb705gYgm -VUMILwi/ZxKTQqBtkT/kQQ5y6nOZsj7XI5rYdz6qqOROrpvS/d7iypdHOMIM9Iz9DlL1mrCykbBi -t25y+gTeXmuisHUwqaRpwtCGK4BayCqxRGbNipe6W73EK9lBrrzNtTr9NaysesT/v+l25JHCL9tG -wpNr1oWFzk4IHVOg0ORiQ6SUgxZUTYcCAwEAAaMSMBAwDgYDVR0PAQH/BAQDAgTwMA0GCSqGSIb3 -DQEBCwUAA4IBAQBWThEoIaQoBX2YeRY/I8gu6TYnFXtyuCljANnXnM38ft+ikhE5mMNgKmJYLHvT -yWWWgwHoSAWEuml7EGbE/2AK2h3k0MdfiWLzdmpPCRG/RJHk6UB1pMHPilI+c0MVu16OPpKbg5Vf -LTv7dsAB40AzKsvyYw88/Ezi1osTXo6QQwda7uefvudirtb8FcQM9R66cJxl3kt1FXbpYwheIm/p -j1mq64swCoIYu4NrsUYtn6CV542DTQMI5QdXkn+PzUUly8F6kDp+KpMNd0avfWNL5+O++z+F5Szy -1CPta1D7EQ/eYmMP+mOQ35oifWIoFCpN6qQVBS/Hob1J/UUyg7BW ------END CERTIFICATE----- diff --git a/src/main/resources/cert/alipayRootCert.crt b/src/main/resources/cert/alipayRootCert.crt deleted file mode 100644 index 76417c5..0000000 --- a/src/main/resources/cert/alipayRootCert.crt +++ /dev/null @@ -1,88 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIBszCCAVegAwIBAgIIaeL+wBcKxnswDAYIKoEcz1UBg3UFADAuMQswCQYDVQQG -EwJDTjEOMAwGA1UECgwFTlJDQUMxDzANBgNVBAMMBlJPT1RDQTAeFw0xMjA3MTQw -MzExNTlaFw00MjA3MDcwMzExNTlaMC4xCzAJBgNVBAYTAkNOMQ4wDAYDVQQKDAVO -UkNBQzEPMA0GA1UEAwwGUk9PVENBMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE -MPCca6pmgcchsTf2UnBeL9rtp4nw+itk1Kzrmbnqo05lUwkwlWK+4OIrtFdAqnRT -V7Q9v1htkv42TsIutzd126NdMFswHwYDVR0jBBgwFoAUTDKxl9kzG8SmBcHG5Yti -W/CXdlgwDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFEwysZfZ -MxvEpgXBxuWLYlvwl3ZYMAwGCCqBHM9VAYN1BQADSAAwRQIgG1bSLeOXp3oB8H7b -53W+CKOPl2PknmWEq/lMhtn25HkCIQDaHDgWxWFtnCrBjH16/W3Ezn7/U/Vjo5xI -pDoiVhsLwg== ------END CERTIFICATE----- - ------BEGIN CERTIFICATE----- -MIIF0zCCA7ugAwIBAgIIH8+hjWpIDREwDQYJKoZIhvcNAQELBQAwejELMAkGA1UE -BhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmlj -YXRpb24gQXV0aG9yaXR5MTEwLwYDVQQDDChBbnQgRmluYW5jaWFsIENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5IFIxMB4XDTE4MDMyMTEzNDg0MFoXDTM4MDIyODEzNDg0 -MFowejELMAkGA1UEBhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNV -BAsMF0NlcnRpZmljYXRpb24gQXV0aG9yaXR5MTEwLwYDVQQDDChBbnQgRmluYW5j -aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFIxMIICIjANBgkqhkiG9w0BAQEF -AAOCAg8AMIICCgKCAgEAtytTRcBNuur5h8xuxnlKJetT65cHGemGi8oD+beHFPTk -rUTlFt9Xn7fAVGo6QSsPb9uGLpUFGEdGmbsQ2q9cV4P89qkH04VzIPwT7AywJdt2 -xAvMs+MgHFJzOYfL1QkdOOVO7NwKxH8IvlQgFabWomWk2Ei9WfUyxFjVO1LVh0Bp -dRBeWLMkdudx0tl3+21t1apnReFNQ5nfX29xeSxIhesaMHDZFViO/DXDNW2BcTs6 -vSWKyJ4YIIIzStumD8K1xMsoaZBMDxg4itjWFaKRgNuPiIn4kjDY3kC66Sl/6yTl -YUz8AybbEsICZzssdZh7jcNb1VRfk79lgAprm/Ktl+mgrU1gaMGP1OE25JCbqli1 -Pbw/BpPynyP9+XulE+2mxFwTYhKAwpDIDKuYsFUXuo8t261pCovI1CXFzAQM2w7H -DtA2nOXSW6q0jGDJ5+WauH+K8ZSvA6x4sFo4u0KNCx0ROTBpLif6GTngqo3sj+98 -SZiMNLFMQoQkjkdN5Q5g9N6CFZPVZ6QpO0JcIc7S1le/g9z5iBKnifrKxy0TQjtG -PsDwc8ubPnRm/F82RReCoyNyx63indpgFfhN7+KxUIQ9cOwwTvemmor0A+ZQamRe -9LMuiEfEaWUDK+6O0Gl8lO571uI5onYdN1VIgOmwFbe+D8TcuzVjIZ/zvHrAGUcC -AwEAAaNdMFswCwYDVR0PBAQDAgEGMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFF90 -tATATwda6uWx2yKjh0GynOEBMB8GA1UdIwQYMBaAFF90tATATwda6uWx2yKjh0Gy -nOEBMA0GCSqGSIb3DQEBCwUAA4ICAQCVYaOtqOLIpsrEikE5lb+UARNSFJg6tpkf -tJ2U8QF/DejemEHx5IClQu6ajxjtu0Aie4/3UnIXop8nH/Q57l+Wyt9T7N2WPiNq -JSlYKYbJpPF8LXbuKYG3BTFTdOVFIeRe2NUyYh/xs6bXGr4WKTXb3qBmzR02FSy3 -IODQw5Q6zpXj8prYqFHYsOvGCEc1CwJaSaYwRhTkFedJUxiyhyB5GQwoFfExCVHW -05ZFCAVYFldCJvUzfzrWubN6wX0DD2dwultgmldOn/W/n8at52mpPNvIdbZb2F41 -T0YZeoWnCJrYXjq/32oc1cmifIHqySnyMnavi75DxPCdZsCOpSAT4j4lAQRGsfgI -kkLPGQieMfNNkMCKh7qjwdXAVtdqhf0RVtFILH3OyEodlk1HYXqX5iE5wlaKzDop -PKwf2Q3BErq1xChYGGVS+dEvyXc/2nIBlt7uLWKp4XFjqekKbaGaLJdjYP5b2s7N -1dM0MXQ/f8XoXKBkJNzEiM3hfsU6DOREgMc1DIsFKxfuMwX3EkVQM1If8ghb6x5Y -jXayv+NLbidOSzk4vl5QwngO/JYFMkoc6i9LNwEaEtR9PhnrdubxmrtM+RjfBm02 -77q3dSWFESFQ4QxYWew4pHE0DpWbWy/iMIKQ6UZ5RLvB8GEcgt8ON7BBJeMc+Dyi -kT9qhqn+lw== ------END CERTIFICATE----- - ------BEGIN CERTIFICATE----- -MIICiDCCAgygAwIBAgIIQX76UsB/30owDAYIKoZIzj0EAwMFADB6MQswCQYDVQQG -EwJDTjEWMBQGA1UECgwNQW50IEZpbmFuY2lhbDEgMB4GA1UECwwXQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkxMTAvBgNVBAMMKEFudCBGaW5hbmNpYWwgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkgRTEwHhcNMTkwNDI4MTYyMDQ0WhcNNDkwNDIwMTYyMDQ0 -WjB6MQswCQYDVQQGEwJDTjEWMBQGA1UECgwNQW50IEZpbmFuY2lhbDEgMB4GA1UE -CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxMTAvBgNVBAMMKEFudCBGaW5hbmNp -YWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRTEwdjAQBgcqhkjOPQIBBgUrgQQA -IgNiAASCCRa94QI0vR5Up9Yr9HEupz6hSoyjySYqo7v837KnmjveUIUNiuC9pWAU -WP3jwLX3HkzeiNdeg22a0IZPoSUCpasufiLAnfXh6NInLiWBrjLJXDSGaY7vaokt -rpZvAdmjXTBbMAsGA1UdDwQEAwIBBjAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBRZ -4ZTgDpksHL2qcpkFkxD2zVd16TAfBgNVHSMEGDAWgBRZ4ZTgDpksHL2qcpkFkxD2 -zVd16TAMBggqhkjOPQQDAwUAA2gAMGUCMQD4IoqT2hTUn0jt7oXLdMJ8q4vLp6sg -wHfPiOr9gxreb+e6Oidwd2LDnC4OUqCWiF8CMAzwKs4SnDJYcMLf2vpkbuVE4dTH -Rglz+HGcTLWsFs4KxLsq7MuU+vJTBUeDJeDjdA== ------END CERTIFICATE----- - ------BEGIN CERTIFICATE----- -MIIDxTCCAq2gAwIBAgIUEMdk6dVgOEIS2cCP0Q43P90Ps5YwDQYJKoZIhvcNAQEF -BQAwajELMAkGA1UEBhMCQ04xEzARBgNVBAoMCmlUcnVzQ2hpbmExHDAaBgNVBAsM -E0NoaW5hIFRydXN0IE5ldHdvcmsxKDAmBgNVBAMMH2lUcnVzQ2hpbmEgQ2xhc3Mg -MiBSb290IENBIC0gRzMwHhcNMTMwNDE4MDkzNjU2WhcNMzMwNDE4MDkzNjU2WjBq -MQswCQYDVQQGEwJDTjETMBEGA1UECgwKaVRydXNDaGluYTEcMBoGA1UECwwTQ2hp -bmEgVHJ1c3QgTmV0d29yazEoMCYGA1UEAwwfaVRydXNDaGluYSBDbGFzcyAyIFJv -b3QgQ0EgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOPPShpV -nJbMqqCw6Bz1kehnoPst9pkr0V9idOwU2oyS47/HjJXk9Rd5a9xfwkPO88trUpz5 -4GmmwspDXjVFu9L0eFaRuH3KMha1Ak01citbF7cQLJlS7XI+tpkTGHEY5pt3EsQg -wykfZl/A1jrnSkspMS997r2Gim54cwz+mTMgDRhZsKK/lbOeBPpWtcFizjXYCqhw -WktvQfZBYi6o4sHCshnOswi4yV1p+LuFcQ2ciYdWvULh1eZhLxHbGXyznYHi0dGN -z+I9H8aXxqAQfHVhbdHNzi77hCxFjOy+hHrGsyzjrd2swVQ2iUWP8BfEQqGLqM1g -KgWKYfcTGdbPB1MCAwEAAaNjMGEwHQYDVR0OBBYEFG/oAMxTVe7y0+408CTAK8hA -uTyRMB8GA1UdIwQYMBaAFG/oAMxTVe7y0+408CTAK8hAuTyRMA8GA1UdEwEB/wQF -MAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBLnUTfW7hp -emMbuUGCk7RBswzOT83bDM6824EkUnf+X0iKS95SUNGeeSWK2o/3ALJo5hi7GZr3 -U8eLaWAcYizfO99UXMRBPw5PRR+gXGEronGUugLpxsjuynoLQu8GQAeysSXKbN1I -UugDo9u8igJORYA+5ms0s5sCUySqbQ2R5z/GoceyI9LdxIVa1RjVX8pYOj8JFwtn -DJN3ftSFvNMYwRuILKuqUYSHc2GPYiHVflDh5nDymCMOQFcFG3WsEuB+EYQPFgIU -1DHmdZcz7Llx8UOZXX2JupWCYzK1XhJb+r4hK5ncf/w8qGtYlmyJpxk3hr1TfUJX -Yf4Zr0fJsGuv ------END CERTIFICATE----- \ No newline at end of file diff --git a/src/main/resources/cert/apiclient_cert.pem b/src/main/resources/cert/apiclient_cert.pem deleted file mode 100644 index 1fcd156..0000000 --- a/src/main/resources/cert/apiclient_cert.pem +++ /dev/null @@ -1,25 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIEKzCCAxOgAwIBAgIUSHSWE7QKqPHXaFg/w1I1jhPrWvAwDQYJKoZIhvcNAQEL -BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT -FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg -Q0EwHhcNMjQwNTExMDk0MzIzWhcNMjkwNTEwMDk0MzIzWjCBhDETMBEGA1UEAwwK -MTI0NjYxMDEwMTEbMBkGA1UECgwS5b6u5L+h5ZWG5oi357O757ufMTAwLgYDVQQL -DCfljZflroHluILnvZHlrr/kv6Hmga/np5HmioDmnInpmZDlhazlj7gxCzAJBgNV -BAYTAkNOMREwDwYDVQQHDAhTaGVuWmhlbjCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBAJSGQstwTNKfEUWGGNRdzAG691PKkpa78IV7SNAaAWdBUohvSGQB -Hxg2JcTjnNifqxWAVj302u0+OEPETQ+teTLeLgRfGp4b8WBKdibn9RzZD964xGhM -NkcMEwUxdqfBK28kGaKYW0zBifkzS1LDGuEVmUo9jE7pAuzDz5mJwcd1fZs4NsjD -7O60QLw4SZCXINW6IYVc41Ln+RlY2XPkm/keBydjrfvMI7Z+DqW/TEWOWshNycYr -3hqVeipz2FnUwK4ruGxEOqTXhYtn0QtvYaMcrfcXJ1U+zuwtZf+kh3RI/Lk+y2rJ -kfnuxZZ+P5K2oG+hcBapYS3q15kmf9RpMH0CAwEAAaOBuTCBtjAJBgNVHRMEAjAA -MAsGA1UdDwQEAwID+DCBmwYDVR0fBIGTMIGQMIGNoIGKoIGHhoGEaHR0cDovL2V2 -Y2EuaXRydXMuY29tLmNuL3B1YmxpYy9pdHJ1c2NybD9DQT0xQkQ0MjIwRTUwREJD -MDRCMDZBRDM5NzU0OTg0NkMwMUMzRThFQkQyJnNnPUhBQ0M0NzFCNjU0MjJFMTJC -MjdBOUQzM0E4N0FEMUNERjU5MjZFMTQwMzcxMA0GCSqGSIb3DQEBCwUAA4IBAQCK -sgR2Wgb9wyyLX7ltlGXDqT44aMc3n5KI02LXv0mBD1aR4m5TFjlMzJIW2DIe01LF -yxVsUsoGIpjnAkmQOdNPL3tnCfl3bWqdNDDH9B711llNe5y1i4IYOcObhX08dEQd -vBnzuZ7/kH/t2h8q7rd7hqpQ5ZtU2xEY6ZlnohGyzNgVsDkLJI4b9iKRqOxRPVhs -GGbGKrv3JAYiFouSeH/m04xMWARFKhPoWduIeSWEJZmszWfkUBvPXo26+0YOKBVN -5gSkjioeXEX2T4/9K1SHx/iTzWvgN9MjlIJNujbg3Vz4PFU6aw2b8eK3Y0juto96 -2uoUN1fLIqxNOz2E4iSJ ------END CERTIFICATE----- diff --git a/src/main/resources/cert/apiclient_key.pem b/src/main/resources/cert/apiclient_key.pem deleted file mode 100644 index a08bc93..0000000 --- a/src/main/resources/cert/apiclient_key.pem +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCUhkLLcEzSnxFF -hhjUXcwBuvdTypKWu/CFe0jQGgFnQVKIb0hkAR8YNiXE45zYn6sVgFY99NrtPjhD -xE0PrXky3i4EXxqeG/FgSnYm5/Uc2Q/euMRoTDZHDBMFMXanwStvJBmimFtMwYn5 -M0tSwxrhFZlKPYxO6QLsw8+ZicHHdX2bODbIw+zutEC8OEmQlyDVuiGFXONS5/kZ -WNlz5Jv5HgcnY637zCO2fg6lv0xFjlrITcnGK94alXoqc9hZ1MCuK7hsRDqk14WL -Z9ELb2GjHK33FydVPs7sLWX/pId0SPy5PstqyZH57sWWfj+StqBvoXAWqWEt6teZ -Jn/UaTB9AgMBAAECggEAb1Nvj5OeUaUfShBoXg3sU0O0DR9i3w8CCttMyYcklCO3 -XEKlbSgWCYzUpI7DSu/rSdOHUStOSdOAUvM5m824cbNtpKMwjWB+fWFyzFjDNhtR -NO0jctXlPT3Ep/jaaoV1K/pQKLqwfIj5BUw4YlGRvTL2Ulpt59vp8FQZMIm8MOcw -rNwYcUbMPaNKk4q3GF0LGvzW8k+S6wAWcAbx1KINRsLE0127o+shjGIlBiZgMJGZ -nTMz4xdvVbojsMhdM8aEhq6GtmSHgBFKjETQPXiOjRDCGOM5yC/9R/9WsMGJmJ4m -6Ec/RM4k9TZlnMZFsOZYO8S/kM+xgQUcAD8uGT1UgQKBgQDDGVZiqsDjudFcRkG/ -5pJN9PAC/Dk0Wzt6uRPZIhyFo2tDC/uL210Z5QR4hhB2nUSK8ANfAnepTotNzPHO -DC/sO2NzLuZz5EZTLeg9ij9BZDK+0/6AiBT2XdBKR/uGZAffjFCDh+ujm44lbrRK -7MUb9LtvDjPru1WVR0WhpFIwXQKBgQDC4xTQv6x3cPSW2SEglLVrl9CA68yO1g4T -MphCav64Cl9UDk1ov5C2SCvshFbWlIBv2g7tqb/bUk8nj42GuZWBu1spkUt2y7HS -eO89BmnaRNkVtWT8GtSMYYrYYAd23IGiOHPQqMnw/6HXkpjonpBa9c9CfEPwNtdq -84pgqed+oQKBgC6rV/PAPuX6pC87iyzZffPx/JvqM9DnZgIEVdAiDcqV/emK60BY -WBwCoaAnCbcmBahqo5PNpkw0wrP4q3sLhUcwKaj69huQ5pWtLJnUAS+mRVFKqt2a -L9GDPXkXYP6T3SJHkVb1Y5O+eTFRGwW1P61hTJjTP+5K4L0V0H1LLnHtAoGAEDBU -1lJVvUZAyxcWTWKM/3cI9uyffW4ClU2qoDnLFvalnJHjlEP1fW7ZVzhXDlQfpyrx -+oQTT+CyepLOKtbXuIMbu4Q6RI//IYCyPtt9h4gYkFkVHmwMI+0mX3r6o8EFc7hE -xpx+yeoyQ3oGAazKSQQKR3eTHS0xD81TPVxfwoECgYEAvBi3fPvIQ08pxk6kxj+S -bypHo06JHT1Fi8pmKtKCGLduK85dCeBZqHmsorWC/qg4RgCFWFFKfrFTGTxC4nf8 -MRQHmKxq+SAh4SvFgRDA0lyaUWmw7H/JpolbBDIGnXhoDI0CmQU3s2xsQdJnNPIL -azgaJXtOu+wr1MPR7Ij5OTU= ------END PRIVATE KEY----- diff --git a/src/main/resources/cert/appPublicCert.crt b/src/main/resources/cert/appPublicCert.crt deleted file mode 100644 index a12dea4..0000000 --- a/src/main/resources/cert/appPublicCert.crt +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDjzCCAnegAwIBAgIQICISFPMNDPadFdV3VF7atzANBgkqhkiG9w0BAQsFADCBkTELMAkGA1UE -BhMCQ04xGzAZBgNVBAoMEkFudCBGaW5hbmNpYWwgdGVzdDElMCMGA1UECwwcQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkgdGVzdDE+MDwGA1UEAww1QW50IEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1 -dGhvcml0eSBDbGFzcyAyIFIxIHRlc3QwHhcNMjIxMjE0MTEzNjE3WhcNMjMxMjE5MTEzNjE3WjBh -MQswCQYDVQQGEwJDTjEVMBMGA1UECgwM5rKZ566x546v5aKDMQ8wDQYDVQQLDAZBbGlwYXkxKjAo -BgNVBAMMITIwODgxMDIxNzUyMDcyOTItMjAxNjA5MTEwMDQ4OTQ4NjCCASIwDQYJKoZIhvcNAQEB -BQADggEPADCCAQoCggEBAJFjmRNQkJ1d2kWZ4bn8WvIUWKu2+wMDQ5nOMaIGtKo+bx3o1RaAWYct -XJL82GkdUr+JpiBy7W1iFl0quZJIo2n9tyxsTGTswq1mtYJVKonHELxN1L2Xz9PjU8wlzQwxb2Rm -JlW2/SpUGaRiZxzYJHhHXbqvPH8D/xG+x6Hwq9zEF/ZIDMCLi5wiXhK7KFXDOBFYdOw0zwCmGIeY -73htk56kay1HoTjwACvZzkw8ff5FRA76/5/7ZEj6R6Hga/LMmYJXfntPPYW/wuMiBI7rU5f4s6El -S1A2uwK4+kbepg9klOYR2Lg30SNz4hj4k8KNtoeWnzrTlWoZj3SfDErJuuMCAwEAAaMSMBAwDgYD -VR0PAQH/BAQDAgTwMA0GCSqGSIb3DQEBCwUAA4IBAQC9YAgw5uwHUgY73t8eABW8LzrhLoUafN/j -WG6QataRgaTHbNCuCz5yWTMmD7hZGmb8NuZzaLOPD+/0yM5nz+w/nc+Emc6hzTCrBVtFX80nnM3j -lIDBRGJRS2JlyrwL80DxoVCbY7JLkSRpGhc9RYLrNfPjpxhxchJ/8V1JU21rL5GKSdaR2YJDvANi -Bth321Q0G6djxfLPjx3zXp8VTGDdhRZjblJ7EddK4kaQ3RKTm4+UivUYMMQ+esD8NnoHTGvDXRCi -rqd+EtAZZ84yqW7YKKTjsh9a3tLBFwFMc2A2WM3s6fXtrFAiffsXwcyqaKTXibVTFE9t2sTUUaPF -IoJu ------END CERTIFICATE----- \ No newline at end of file diff --git a/src/main/resources/cert/wechatpay_2DD5A0669263BAE55E52BF3F35BF4A4006A2DAA6.pem b/src/main/resources/cert/wechatpay_2DD5A0669263BAE55E52BF3F35BF4A4006A2DAA6.pem deleted file mode 100644 index ccff7dd..0000000 --- a/src/main/resources/cert/wechatpay_2DD5A0669263BAE55E52BF3F35BF4A4006A2DAA6.pem +++ /dev/null @@ -1,23 +0,0 @@ ------BEGIN CERTIFICATE----- -MIID3DCCAsSgAwIBAgIULdWgZpJjuuVeUr8/Nb9KQAai2qYwDQYJKoZIhvcNAQEL -BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT -FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg -Q0EwHhcNMjAxMjA5MDMzMzIxWhcNMjUxMjA4MDMzMzIxWjBuMRgwFgYDVQQDDA9U -ZW5wYXkuY29tIHNpZ24xEzARBgNVBAoMClRlbnBheS5jb20xHTAbBgNVBAsMFFRl -bnBheS5jb20gQ0EgQ2VudGVyMQswCQYDVQQGDAJDTjERMA8GA1UEBwwIU2hlblpo -ZW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDocR052ysMvkp3TkUb -CDz5ntNm3wpPjy53ng6ZQKrMdt/HVKYzHplIO8zgYVKXgiCxlIVw8lAKAJ8uYrs/ -y2KOk2W1sMKb6t9ucKilaxYpCUuePj6ktMXPN/FIAgCIEXjrPuNHuPW6JA53yl6e -wQoNPozbmYrcFFcRUnhHS9RWfSJm2OUBsAFh2O/o2APAhcIac0gPz/a6LWok3+vQ -KnCqZcpGdnATwZ5H7oGmVVPHp8f5LwJYwp58ZHKxVHIHiLOeCXNNy7cnwv+vHBhy -95GOdv9ZJRbcESGR7ASUkIKe5kDJhg5tjK3rKSjqUbe6qG6h5mSPvRy6oe6h9Ihf -F8B1AgMBAAGjgYEwfzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIE8DBlBgNVHR8EXjBc -MFqgWKBWhlRodHRwOi8vZXZjYS5pdHJ1cy5jb20uY24vcHVibGljL2l0cnVzY3Js -P0NBPTFCRDQyMjBFNTBEQkMwNEIwNkFEMzk3NTQ5ODQ2QzAxQzNFOEVCRDIwDQYJ -KoZIhvcNAQELBQADggEBAGfRi4HT8Y6N1yJGmGpABiRJOqouDmktBxDhY12e2V5g -mLfsr+aR4suOfaDbNigwjyQqYijOSlAJZobapNFazE9vUisVRa7FZUhzFLwxOo02 -mallcuDd7/rZuRtiovco+OAQVedAMwOgH6PCwK/QxUGNOpNpCQ5Y70z5ZAxb+IKR -87WQvukZ/u2CqUpvEnwtj1PjuZ7sCqi9TpHhJtMMEZyzII7WB2jDFaIuaqrJDeSB -qWASY04zfQ/FlLosaiXNxJCAT//0I6kM9iudwkuj+7bV8HESrdJcFe0yymIm3zOd -Es6X0klx4QsyadXEHK5RSRIBdoGubHpm5fdVnYfSGok= ------END CERTIFICATE----- \ No newline at end of file diff --git a/src/main/resources/cert/wechatpay_4A3231584E93B6AE77820074D07EADEACCB7E223.pem b/src/main/resources/cert/wechatpay_4A3231584E93B6AE77820074D07EADEACCB7E223.pem deleted file mode 100644 index 50afe22..0000000 --- a/src/main/resources/cert/wechatpay_4A3231584E93B6AE77820074D07EADEACCB7E223.pem +++ /dev/null @@ -1,24 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIEFDCCAvygAwIBAgIUSjIxWE6Ttq53ggB00H6t6sy34iMwDQYJKoZIhvcNAQEL -BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT -FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg -Q0EwHhcNMjMwOTE5MTUxNTQ4WhcNMjgwOTE3MTUxNTQ4WjBuMRgwFgYDVQQDDA9U -ZW5wYXkuY29tIHNpZ24xEzARBgNVBAoMClRlbnBheS5jb20xHTAbBgNVBAsMFFRl -bnBheS5jb20gQ0EgQ2VudGVyMQswCQYDVQQGDAJDTjERMA8GA1UEBwwIU2hlblpo -ZW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC5AOeoNuRReVPfOodE -TTE/wq96OK/7MI1lkwgtRlOIqwFGbGPxPx+wiLweWOWAeGrd0h+YuktIZezLhMhB -8pkJBzxz4U+zoQ9n3yY4CgDUBeAO8eNHhEQTTOTFUIvIlRxyr0EVuTHNP7pIkxA6 -gUvajWjJFbvU393vDHA9RflWrBNw1qVjkPPUx6axizD3wS8f77bwuspEWGTza/pS -g96HWUwFh9OSlQNPOjPG4km2YRQwGhoRMlLeZsUB+a0PtV0HI/B0TbY5u2EmPt0R -uNZLmcwImtiANYmySww6gp5uo4+im0P/kHKynPrW1SkS+8M9JP5T7Xck3bnHNv4S -9UOPAgMBAAGjgbkwgbYwCQYDVR0TBAIwADALBgNVHQ8EBAMCA/gwgZsGA1UdHwSB -kzCBkDCBjaCBiqCBh4aBhGh0dHA6Ly9ldmNhLml0cnVzLmNvbS5jbi9wdWJsaWMv -aXRydXNjcmw/Q0E9MUJENDIyMEU1MERCQzA0QjA2QUQzOTc1NDk4NDZDMDFDM0U4 -RUJEMiZzZz1IQUNDNDcxQjY1NDIyRTEyQjI3QTlEMzNBODdBRDFDREY1OTI2RTE0 -MDM3MTANBgkqhkiG9w0BAQsFAAOCAQEAHd42YyvxvvjYEIkCURHweCSQpWQrdsnP -AU2rcVzOx0kDxjq7+W2HkIkYeAZfE8pyBs5c39tgK+qospiDsKa9WYeBNyIRcCvN -q9ObLqSV4Cy/8lQMNh4Q37cdc3X+pAlTr7MtKka8ZcXYvbMBqus0dfJZayZvW7Ak -nnaXXJ4k7urgHOGYsZlZ+HC+DC/sYoN3DXzvg3XPlL0SNEQH0cWrRbaQnpOKVMk5 -TptbeNHKJfUxVW5jh4GtBFqvLeiOruY+gFYg7UkCKWo9ZIYe7/mEvJeHYh3acTTl -DOl3L0fR5KR7vqFMwZEUZxVOs6K2ANSCr57OQPBV++MG4DPr3yOhCQ== ------END CERTIFICATE----- \ No newline at end of file diff --git a/src/main/resources/sql/check_payment_config.sql b/src/main/resources/sql/check_payment_config.sql deleted file mode 100644 index 68f0e82..0000000 --- a/src/main/resources/sql/check_payment_config.sql +++ /dev/null @@ -1,91 +0,0 @@ --- 检查支付配置的SQL脚本 - --- 1. 查看所有支付配置 -SELECT - id, - name, - type, - code, - app_id, - mch_id, - CASE - WHEN api_key IS NULL OR api_key = '' THEN '未配置' - ELSE CONCAT('已配置(长度:', LENGTH(api_key), ')') - END as api_key_status, - merchant_serial_number, - status, - tenant_id, - create_time -FROM sys_payment -ORDER BY type, tenant_id; - --- 2. 检查微信支付配置(type=0) -SELECT - id, - name, - app_id, - mch_id, - CASE - WHEN api_key IS NULL OR api_key = '' THEN 'ERROR: API密钥未配置' - WHEN LENGTH(api_key) < 32 THEN 'WARNING: API密钥长度可能不正确' - ELSE 'OK' - END as api_key_check, - CASE - WHEN merchant_serial_number IS NULL OR merchant_serial_number = '' THEN 'ERROR: 序列号未配置' - WHEN LENGTH(merchant_serial_number) != 40 THEN 'WARNING: 序列号长度可能不正确' - ELSE 'OK' - END as serial_number_check, - CASE - WHEN mch_id IS NULL OR mch_id = '' THEN 'ERROR: 商户号未配置' - ELSE 'OK' - END as mch_id_check, - CASE - WHEN app_id IS NULL OR app_id = '' THEN 'ERROR: 应用ID未配置' - ELSE 'OK' - END as app_id_check, - status, - tenant_id -FROM sys_payment -WHERE type = 0 -ORDER BY tenant_id; - --- 3. 插入示例微信支付配置(请根据实际情况修改) --- 注意:请将下面的值替换为您的实际配置 -/* -INSERT INTO sys_payment ( - name, - type, - code, - app_id, - mch_id, - api_key, - merchant_serial_number, - status, - tenant_id, - create_time, - update_time -) VALUES ( - '微信支付', - 0, - '0', - 'wx1234567890abcdef', -- 请替换为您的微信小程序AppID - '1723321338', -- 请替换为您的商户号 - 'your_api_v3_key_here', -- 请替换为您的APIv3密钥 - '2B933F7C35014A1C363642623E4A62364B34C4EB', -- 请替换为您的商户证书序列号 - 1, - 10550, -- 请替换为您的租户ID - NOW(), - NOW() -) ON DUPLICATE KEY UPDATE - app_id = VALUES(app_id), - mch_id = VALUES(mch_id), - api_key = VALUES(api_key), - merchant_serial_number = VALUES(merchant_serial_number), - update_time = NOW(); -*/ - --- 4. 检查特定租户的支付配置 --- SELECT * FROM sys_payment WHERE tenant_id = 10550 AND type = 0; - --- 5. 删除错误的支付配置(谨慎使用) --- DELETE FROM sys_payment WHERE id = ?; diff --git a/src/test/java/com/gxwebsoft/test/CertificateTest.java b/src/test/java/com/gxwebsoft/test/CertificateTest.java index 4a2ed1e..4d59a67 100644 --- a/src/test/java/com/gxwebsoft/test/CertificateTest.java +++ b/src/test/java/com/gxwebsoft/test/CertificateTest.java @@ -29,19 +29,31 @@ public class CertificateTest { public void testCertificateLoading() { try { System.out.println("=== 证书加载测试 ==="); - + // 测试租户ID String tenantId = "10550"; String tenantCertPath = "dev/wechat/" + tenantId; String privateKeyPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getPrivateKeyFile(); - + System.out.println("证书路径: " + privateKeyPath); System.out.println("加载模式: " + certConfig.getLoadMode()); - + System.out.println("开发环境证书路径前缀: " + certConfig.getDevCertPath()); + + // 检查证书文件是否存在 + boolean exists = certificateLoader.certificateExists(privateKeyPath); + System.out.println("证书文件是否存在: " + exists); + + if (!exists) { + System.err.println("❌ 证书文件不存在: " + privateKeyPath); + System.out.println("💡 请确认证书文件已放置在正确位置:"); + System.out.println(" src/main/resources/dev/wechat/10550/apiclient_key.pem"); + return; + } + // 测试证书加载 String privateKeyFile = certificateLoader.loadCertificatePath(privateKeyPath); - System.out.println("私钥文件路径: " + privateKeyFile); - + System.out.println("✅ 私钥文件加载成功: " + privateKeyFile); + // 测试自动证书配置 System.out.println("=== 测试自动证书配置 ==="); Config config = wechatCertAutoConfig.createAutoConfig( @@ -50,11 +62,45 @@ public class CertificateTest { "test-serial-number", // 测试序列号 "test-api-key" // 测试API密钥 ); - - System.out.println("自动证书配置创建成功: " + (config != null)); - + + System.out.println("✅ 自动证书配置创建成功"); + + } catch (Exception e) { + System.err.println("❌ 证书测试失败: " + e.getMessage()); + e.printStackTrace(); + } + } + + @Test + public void testNotificationCertificateConfig() { + try { + System.out.println("=== 异步通知证书配置测试 ==="); + + // 模拟异步通知中的证书配置逻辑 + String tenantId = "10550"; + String tenantCertPath = "dev/wechat/" + tenantId; + String privateKeyPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getPrivateKeyFile(); + + System.out.println("租户ID: " + tenantId); + System.out.println("证书目录: " + tenantCertPath); + System.out.println("私钥路径: " + privateKeyPath); + + // 检查证书文件是否存在 + if (!certificateLoader.certificateExists(privateKeyPath)) { + System.err.println("❌ 证书文件不存在: " + privateKeyPath); + throw new RuntimeException("证书文件不存在: " + privateKeyPath); + } + + String privateKey = certificateLoader.loadCertificatePath(privateKeyPath); + String apiV3Key = certConfig.getWechatPay().getDev().getApiV3Key(); + + System.out.println("✅ 私钥文件加载成功: " + privateKey); + System.out.println("APIv3密钥配置: " + (apiV3Key != null ? "已配置" : "未配置")); + + System.out.println("✅ 异步通知证书配置测试通过"); + } catch (Exception e) { - System.err.println("证书测试失败: " + e.getMessage()); + System.err.println("❌ 异步通知证书配置测试失败: " + e.getMessage()); e.printStackTrace(); } } diff --git a/src/test/java/com/gxwebsoft/test/NotificationCertificateFixTest.java b/src/test/java/com/gxwebsoft/test/NotificationCertificateFixTest.java new file mode 100644 index 0000000..1c6ff32 --- /dev/null +++ b/src/test/java/com/gxwebsoft/test/NotificationCertificateFixTest.java @@ -0,0 +1,101 @@ +package com.gxwebsoft.test; + +import org.junit.jupiter.api.Test; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; + +/** + * 异步通知证书修复验证测试 + */ +public class NotificationCertificateFixTest { + + @Test + public void testCertificatePathFix() { + System.out.println("=== 异步通知证书路径修复验证 ==="); + + // 模拟异步通知中的证书路径构建逻辑 + String tenantId = "10550"; + String devCertPath = "dev"; + String certDir = "wechat"; + String privateKeyFile = "apiclient_key.pem"; + + // 修复后的路径构建逻辑 + String tenantCertPath = devCertPath + "/" + certDir + "/" + tenantId; + String privateKeyPath = tenantCertPath + "/" + privateKeyFile; + + System.out.println("租户ID: " + tenantId); + System.out.println("证书目录: " + tenantCertPath); + System.out.println("私钥路径: " + privateKeyPath); + + // 测试从classpath加载证书 + try { + Resource resource = new ClassPathResource(privateKeyPath); + System.out.println("证书资源存在: " + resource.exists()); + + if (resource.exists()) { + // 模拟CertificateLoader.loadFromClasspath的逻辑 + Path tempFile = Files.createTempFile("cert_", ".pem"); + try (InputStream inputStream = resource.getInputStream()) { + Files.copy(inputStream, tempFile, java.nio.file.StandardCopyOption.REPLACE_EXISTING); + } + + String tempPath = tempFile.toAbsolutePath().toString(); + System.out.println("✅ 证书加载成功: " + tempPath); + + // 验证临时文件 + File tempCertFile = new File(tempPath); + System.out.println("临时证书文件大小: " + tempCertFile.length() + " bytes"); + + // 清理临时文件 + Files.deleteIfExists(tempFile); + + } else { + System.err.println("❌ 证书文件不存在: " + privateKeyPath); + } + + } catch (IOException e) { + System.err.println("❌ 证书加载失败: " + e.getMessage()); + e.printStackTrace(); + } + + System.out.println("=== 测试完成 ==="); + } + + @Test + public void testAllTenantCertificates() { + System.out.println("=== 测试所有租户证书 ==="); + + String[] tenantIds = {"10398", "10550"}; + String devCertPath = "dev"; + String certDir = "wechat"; + String privateKeyFile = "apiclient_key.pem"; + + for (String tenantId : tenantIds) { + System.out.println("\n--- 测试租户: " + tenantId + " ---"); + + String tenantCertPath = devCertPath + "/" + certDir + "/" + tenantId; + String privateKeyPath = tenantCertPath + "/" + privateKeyFile; + + System.out.println("证书路径: " + privateKeyPath); + + try { + Resource resource = new ClassPathResource(privateKeyPath); + if (resource.exists()) { + System.out.println("✅ 租户 " + tenantId + " 证书存在"); + } else { + System.out.println("❌ 租户 " + tenantId + " 证书不存在"); + } + } catch (Exception e) { + System.err.println("❌ 租户 " + tenantId + " 证书检查失败: " + e.getMessage()); + } + } + + System.out.println("\n=== 所有租户证书测试完成 ==="); + } +} diff --git a/src/test/java/com/gxwebsoft/test/WechatPayConfigValidationTest.java b/src/test/java/com/gxwebsoft/test/WechatPayConfigValidationTest.java new file mode 100644 index 0000000..916d98d --- /dev/null +++ b/src/test/java/com/gxwebsoft/test/WechatPayConfigValidationTest.java @@ -0,0 +1,134 @@ +package com.gxwebsoft.test; + +import com.gxwebsoft.common.core.config.CertificateProperties; +import com.gxwebsoft.common.core.utils.CertificateLoader; +import com.gxwebsoft.common.core.utils.RedisUtil; +import com.gxwebsoft.common.system.entity.Payment; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +/** + * 微信支付配置验证测试 + */ +@SpringBootTest +@ActiveProfiles("dev") +public class WechatPayConfigValidationTest { + + @Autowired + private CertificateProperties certConfig; + + @Autowired + private CertificateLoader certificateLoader; + + @Autowired + private RedisUtil redisUtil; + + @Test + public void testWechatPayConfigValidation() { + System.out.println("=== 微信支付配置验证 ==="); + + // 1. 检查配置文件中的 APIv3 密钥 + String configApiV3Key = certConfig.getWechatPay().getDev().getApiV3Key(); + System.out.println("配置文件 APIv3 密钥: " + configApiV3Key); + System.out.println("配置文件 APIv3 密钥长度: " + (configApiV3Key != null ? configApiV3Key.length() : 0)); + + // 2. 检查 Redis 中的支付配置 + String tenantId = "10550"; + String redisKey = "Payment:1:" + tenantId; + Payment payment = redisUtil.get(redisKey, Payment.class); + + if (payment != null) { + System.out.println("\n=== Redis 支付配置 ==="); + System.out.println("商户号: " + payment.getMchId()); + System.out.println("应用ID: " + payment.getAppId()); + System.out.println("数据库 APIv3 密钥: " + payment.getApiKey()); + System.out.println("数据库 APIv3 密钥长度: " + (payment.getApiKey() != null ? payment.getApiKey().length() : 0)); + System.out.println("商户证书序列号: " + payment.getMerchantSerialNumber()); + + // 3. 比较两个 APIv3 密钥 + System.out.println("\n=== APIv3 密钥比较 ==="); + boolean keysMatch = (configApiV3Key != null && configApiV3Key.equals(payment.getApiKey())); + System.out.println("配置文件与数据库密钥是否一致: " + keysMatch); + + if (!keysMatch) { + System.out.println("⚠️ 警告: 配置文件与数据库中的 APIv3 密钥不一致!"); + System.out.println("配置文件密钥: " + configApiV3Key); + System.out.println("数据库密钥: " + payment.getApiKey()); + } + + } else { + System.out.println("❌ 未找到 Redis 中的支付配置: " + redisKey); + + // 尝试其他可能的键格式 + String[] possibleKeys = { + "Payment:1:10550", + "Payment:0:10550", + "Payment:10", + "Payment:1" + "0" // Payment:10 + }; + + System.out.println("\n=== 尝试其他 Redis 键格式 ==="); + for (String key : possibleKeys) { + Payment p = redisUtil.get(key, Payment.class); + if (p != null) { + System.out.println("✅ 找到支付配置: " + key); + System.out.println(" 商户号: " + p.getMchId()); + System.out.println(" APIv3密钥: " + p.getApiKey()); + break; + } + } + } + + // 4. 验证证书文件 + System.out.println("\n=== 证书文件验证 ==="); + String tenantCertPath = "dev/wechat/" + tenantId; + String privateKeyPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getPrivateKeyFile(); + + boolean certExists = certificateLoader.certificateExists(privateKeyPath); + System.out.println("证书文件存在: " + certExists); + System.out.println("证书路径: " + privateKeyPath); + + if (certExists) { + try { + String privateKey = certificateLoader.loadCertificatePath(privateKeyPath); + System.out.println("✅ 证书加载成功: " + privateKey); + } catch (Exception e) { + System.out.println("❌ 证书加载失败: " + e.getMessage()); + } + } + + System.out.println("\n=== 验证完成 ==="); + } + + @Test + public void testApiV3KeyValidation() { + System.out.println("=== APIv3 密钥格式验证 ==="); + + String configKey = certConfig.getWechatPay().getDev().getApiV3Key(); + + if (configKey != null) { + System.out.println("APIv3 密钥: " + configKey); + System.out.println("密钥长度: " + configKey.length()); + + // APIv3 密钥应该是32位字符串 + if (configKey.length() == 32) { + System.out.println("✅ APIv3 密钥长度正确 (32位)"); + } else { + System.out.println("❌ APIv3 密钥长度错误,应为32位,实际为: " + configKey.length()); + } + + // 检查是否包含特殊字符 + boolean hasSpecialChars = !configKey.matches("^[a-zA-Z0-9]+$"); + if (hasSpecialChars) { + System.out.println("⚠️ APIv3 密钥包含特殊字符,可能导致解密失败"); + } else { + System.out.println("✅ APIv3 密钥格式正确 (仅包含字母和数字)"); + } + + } else { + System.out.println("❌ APIv3 密钥未配置"); + } + } +}