From 96caafaa4fd017c47b6a375a6633ca86f69b68ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=BF=A0=E6=9E=97?= <170083662@qq.com> Date: Sat, 26 Jul 2025 23:29:40 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B9=E9=80=A0=E6=94=AF=E4=BB=98=E8=AF=81?= =?UTF-8?q?=E4=B9=A6=E7=AE=A1=E7=90=86=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/quick-wechat-cert.sh | 23 ++- .../controller/WechatCertTestController.java | 157 ++++++++++++++++++ .../core/utils/WechatCertAutoConfig.java | 141 ++++++++++++++++ .../certs/dev/wechat/10550/pub_key-3.pem | 9 + 4 files changed, 323 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/gxwebsoft/common/core/controller/WechatCertTestController.java create mode 100644 src/main/java/com/gxwebsoft/common/core/utils/WechatCertAutoConfig.java create mode 100644 src/main/resources/certs/dev/wechat/10550/pub_key-3.pem diff --git a/scripts/quick-wechat-cert.sh b/scripts/quick-wechat-cert.sh index 20ae7e5..724f002 100755 --- a/scripts/quick-wechat-cert.sh +++ b/scripts/quick-wechat-cert.sh @@ -23,7 +23,11 @@ echo "================================" MERCHANT_ID="1723321338" API_V3_KEY="0kF5OlPr482EZwtn9zGufUcqa7ovgxRL" MERCHANT_SERIAL_NUMBER="2B933F7C35014A1C363642623E4A62364B34C4EB" -PRIVATE_KEY_PATH="src/main/resources/certs/dev/wechat/apiclient_key.pem" +# 检测脚本运行位置并设置正确的路径 +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" + +PRIVATE_KEY_PATH="$PROJECT_ROOT/src/main/resources/certs/dev/wechat/apiclient_key.pem" log_info "使用以下配置:" log_info "商户号: $MERCHANT_ID" @@ -33,6 +37,8 @@ log_info "私钥路径: $PRIVATE_KEY_PATH" # 检查私钥文件 if [[ ! -f "$PRIVATE_KEY_PATH" ]]; then log_warning "私钥文件不存在: $PRIVATE_KEY_PATH" + log_info "项目根目录: $PROJECT_ROOT" + log_info "脚本目录: $SCRIPT_DIR" exit 1 fi @@ -49,17 +55,17 @@ public class WechatAutoTest { String privateKeyPath = args[1]; String serialNumber = args[2]; String apiV3Key = args[3]; - + try { System.out.println("🔧 正在创建 RSAAutoCertificateConfig..."); - + Config config = new RSAAutoCertificateConfig.Builder() .merchantId(merchantId) .privateKeyFromPath(privateKeyPath) .merchantSerialNumber(serialNumber) .apiV3Key(apiV3Key) .build(); - + System.out.println("✅ 微信支付证书配置成功!"); System.out.println(""); System.out.println("📋 配置信息:"); @@ -73,7 +79,7 @@ public class WechatAutoTest { System.out.println("🚫 无需手动下载 wechatpay_cert.pem"); System.out.println(""); System.out.println("✨ 您的微信支付证书配置已完成!"); - + } catch (Exception e) { System.err.println("❌ 证书配置失败: " + e.getMessage()); System.err.println(""); @@ -87,7 +93,7 @@ public class WechatAutoTest { System.err.println("1. 登录微信商户平台 -> 账户中心 -> API安全"); System.err.println("2. 确认已申请使用微信支付公钥"); System.err.println("3. 检查APIv3密钥和证书序列号"); - + e.printStackTrace(); System.exit(1); } @@ -97,12 +103,15 @@ EOF log_info "创建测试程序..." +# 切换到项目根目录进行编译 +cd "$PROJECT_ROOT" + # 构建classpath CLASSPATH="target/classes" if [[ -f "pom.xml" ]]; then log_info "编译项目..." mvn compile -q > /dev/null 2>&1 || true - + # 获取依赖classpath DEPS_CP=$(mvn dependency:build-classpath -q -Dmdep.outputFile=/dev/stdout 2>/dev/null || echo "") if [[ -n "$DEPS_CP" ]]; then diff --git a/src/main/java/com/gxwebsoft/common/core/controller/WechatCertTestController.java b/src/main/java/com/gxwebsoft/common/core/controller/WechatCertTestController.java new file mode 100644 index 0000000..ff6b05e --- /dev/null +++ b/src/main/java/com/gxwebsoft/common/core/controller/WechatCertTestController.java @@ -0,0 +1,157 @@ +package com.gxwebsoft.common.core.controller; + +import com.gxwebsoft.common.core.utils.WechatCertAutoConfig; +import com.gxwebsoft.common.core.web.ApiResult; +import com.gxwebsoft.common.core.web.BaseController; +import com.wechat.pay.java.core.Config; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.Map; + +/** + * 微信支付证书自动配置测试控制器 + * + * @author 科技小王子 + * @since 2024-07-26 + */ +@Slf4j +@RestController +@RequestMapping("/api/wechat-cert-test") +@Api(tags = "微信支付证书自动配置测试") +public class WechatCertTestController extends BaseController { + + @Autowired + private WechatCertAutoConfig wechatCertAutoConfig; + + @ApiOperation("测试默认开发环境证书配置") + @PostMapping("/test-default") + public ApiResult> testDefaultConfig() { + Map result = new HashMap<>(); + + try { + log.info("开始测试默认开发环境证书配置..."); + + // 创建自动证书配置 + Config config = wechatCertAutoConfig.createDefaultDevConfig(); + + // 测试配置 + boolean testResult = wechatCertAutoConfig.testConfig(config); + + result.put("success", true); + result.put("configCreated", config != null); + result.put("testPassed", testResult); + result.put("message", "默认证书配置测试完成"); + result.put("instructions", wechatCertAutoConfig.getUsageInstructions()); + + log.info("✅ 默认证书配置测试成功"); + return success("测试成功", result); + + } catch (Exception e) { + log.error("❌ 默认证书配置测试失败: {}", e.getMessage(), e); + + result.put("success", false); + result.put("error", e.getMessage()); + result.put("message", "证书配置测试失败"); + result.put("troubleshooting", getTroubleshootingInfo()); + + return fail("测试失败: " + e.getMessage(), result); + } + } + + @ApiOperation("测试自定义证书配置") + @PostMapping("/test-custom") + public ApiResult> testCustomConfig( + @ApiParam("商户号") @RequestParam String merchantId, + @ApiParam("私钥文件路径") @RequestParam String privateKeyPath, + @ApiParam("证书序列号") @RequestParam String merchantSerialNumber, + @ApiParam("APIv3密钥") @RequestParam String apiV3Key) { + + Map result = new HashMap<>(); + + try { + log.info("开始测试自定义证书配置..."); + log.info("商户号: {}", merchantId); + log.info("私钥路径: {}", privateKeyPath); + + // 创建自动证书配置 + Config config = wechatCertAutoConfig.createAutoConfig( + merchantId, privateKeyPath, merchantSerialNumber, apiV3Key); + + // 测试配置 + boolean testResult = wechatCertAutoConfig.testConfig(config); + + result.put("success", true); + result.put("configCreated", config != null); + result.put("testPassed", testResult); + result.put("message", "自定义证书配置测试完成"); + result.put("merchantId", merchantId); + result.put("privateKeyPath", privateKeyPath); + + log.info("✅ 自定义证书配置测试成功"); + return success("测试成功", result); + + } catch (Exception e) { + log.error("❌ 自定义证书配置测试失败: {}", e.getMessage(), e); + + result.put("success", false); + result.put("error", e.getMessage()); + result.put("message", "证书配置测试失败"); + result.put("troubleshooting", getTroubleshootingInfo()); + + return fail("测试失败: " + e.getMessage(), result); + } + } + + @ApiOperation("获取使用说明") + @GetMapping("/instructions") + public ApiResult getInstructions() { + String instructions = wechatCertAutoConfig.getUsageInstructions(); + return success("获取使用说明成功", instructions); + } + + @ApiOperation("获取故障排除信息") + @GetMapping("/troubleshooting") + public ApiResult> getTroubleshooting() { + Map troubleshooting = getTroubleshootingInfo(); + return success("获取故障排除信息成功", troubleshooting); + } + + /** + * 获取故障排除信息 + */ + private Map getTroubleshootingInfo() { + Map info = new HashMap<>(); + + info.put("commonIssues", Map.of( + "404错误", "商户平台未开启API安全功能或未申请使用微信支付公钥", + "证书序列号错误", "请检查商户平台中的证书序列号是否正确", + "APIv3密钥错误", "请确认APIv3密钥是否正确设置", + "私钥文件不存在", "请检查私钥文件路径是否正确", + "网络连接问题", "请检查网络连接是否正常" + )); + + info.put("solutions", Map.of( + "开启API安全", "登录微信商户平台 -> 账户中心 -> API安全 -> 申请使用微信支付公钥", + "获取证书序列号", "在API安全页面查看或重新下载证书", + "设置APIv3密钥", "在API安全页面设置APIv3密钥", + "检查私钥文件", "确保apiclient_key.pem文件存在且路径正确" + )); + + info.put("advantages", Map.of( + "自动下载", "RSAAutoCertificateConfig会自动下载平台证书", + "自动更新", "证书过期时会自动更新", + "简化管理", "无需手动管理wechatpay_cert.pem文件", + "官方推荐", "微信支付官方推荐的证书管理方式" + )); + + info.put("documentation", "https://pay.weixin.qq.com/doc/v3/merchant/4012153196"); + + return info; + } +} diff --git a/src/main/java/com/gxwebsoft/common/core/utils/WechatCertAutoConfig.java b/src/main/java/com/gxwebsoft/common/core/utils/WechatCertAutoConfig.java new file mode 100644 index 0000000..0d90c69 --- /dev/null +++ b/src/main/java/com/gxwebsoft/common/core/utils/WechatCertAutoConfig.java @@ -0,0 +1,141 @@ +package com.gxwebsoft.common.core.utils; + +import com.wechat.pay.java.core.Config; +import com.wechat.pay.java.core.RSAAutoCertificateConfig; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * 微信支付证书自动配置工具类 + * 使用RSAAutoCertificateConfig实现证书自动管理 + * + * @author 科技小王子 + * @since 2024-07-26 + */ +@Slf4j +@Component +public class WechatCertAutoConfig { + + /** + * 创建微信支付自动证书配置 + * + * @param merchantId 商户号 + * @param privateKeyPath 私钥文件路径 + * @param merchantSerialNumber 商户证书序列号 + * @param apiV3Key APIv3密钥 + * @return 微信支付配置对象 + */ + public Config createAutoConfig(String merchantId, String privateKeyPath, + String merchantSerialNumber, String apiV3Key) { + try { + log.info("创建微信支付自动证书配置..."); + log.info("商户号: {}", merchantId); + log.info("私钥路径: {}", privateKeyPath); + log.info("证书序列号: {}", merchantSerialNumber); + + Config config = new RSAAutoCertificateConfig.Builder() + .merchantId(merchantId) + .privateKeyFromPath(privateKeyPath) + .merchantSerialNumber(merchantSerialNumber) + .apiV3Key(apiV3Key) + .build(); + + log.info("✅ 微信支付自动证书配置创建成功"); + log.info("🔄 系统将自动管理平台证书的下载和更新"); + + return config; + + } catch (Exception e) { + log.error("❌ 创建微信支付自动证书配置失败: {}", e.getMessage(), e); + + // 提供详细的错误诊断信息 + log.error("🔍 错误诊断:"); + log.error("1. 请检查商户平台是否已开启API安全功能"); + log.error("2. 请确认已申请使用微信支付公钥"); + log.error("3. 请验证APIv3密钥和证书序列号是否正确"); + log.error("4. 请检查网络连接是否正常"); + log.error("5. 请确认私钥文件路径是否正确: {}", privateKeyPath); + + throw new RuntimeException("微信支付自动证书配置失败: " + e.getMessage(), e); + } + } + + /** + * 使用默认开发环境配置创建自动证书配置 + * + * @return 微信支付配置对象 + */ + public Config createDefaultDevConfig() { + String merchantId = "1723321338"; + String privateKeyPath = "src/main/resources/certs/dev/wechat/apiclient_key.pem"; + String merchantSerialNumber = "2B933F7C35014A1C363642623E4A62364B34C4EB"; + String apiV3Key = "0kF5OlPr482EZwtn9zGufUcqa7ovgxRL"; + + return createAutoConfig(merchantId, privateKeyPath, merchantSerialNumber, apiV3Key); + } + + /** + * 测试证书配置是否正常 + * + * @param config 微信支付配置 + * @return 是否配置成功 + */ + public boolean testConfig(Config config) { + try { + // 这里可以添加一些基本的配置验证逻辑 + log.info("🧪 测试微信支付证书配置..."); + + if (config == null) { + log.error("配置对象为空"); + return false; + } + + log.info("✅ 证书配置测试通过"); + return true; + + } catch (Exception e) { + log.error("❌ 证书配置测试失败: {}", e.getMessage(), e); + return false; + } + } + + /** + * 获取配置使用说明 + * + * @return 使用说明 + */ + public String getUsageInstructions() { + return """ + 🚀 微信支付自动证书配置使用说明 + ================================ + + ✅ 优势: + 1. 自动下载微信支付平台证书 + 2. 证书过期时自动更新 + 3. 无需手动管理 wechatpay_cert.pem 文件 + 4. 符合微信支付官方最佳实践 + + 📝 使用方法: + + // 方法1: 使用默认开发环境配置 + Config config = wechatCertAutoConfig.createDefaultDevConfig(); + + // 方法2: 自定义配置 + Config config = wechatCertAutoConfig.createAutoConfig( + "商户号", + "私钥路径", + "证书序列号", + "APIv3密钥" + ); + + 🔧 前置条件: + 1. 微信商户平台已开启API安全功能 + 2. 已申请使用微信支付公钥 + 3. 私钥文件存在且路径正确 + 4. 网络连接正常 + + 📚 更多信息: + https://pay.weixin.qq.com/doc/v3/merchant/4012153196 + """; + } +} diff --git a/src/main/resources/certs/dev/wechat/10550/pub_key-3.pem b/src/main/resources/certs/dev/wechat/10550/pub_key-3.pem new file mode 100644 index 0000000..f225ce7 --- /dev/null +++ b/src/main/resources/certs/dev/wechat/10550/pub_key-3.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAty9bVrLUO+O4vVILMaDX +rmsVCxH2FcZE2zAKJuOSkxscjEcpEBIuXO0CqKbYRt/Pn61W12sj3/MnV6bm1h++ +ebdIMpwGRh9Dn3YXD7UzUF5DtQ1UT3LU2nJDLD27AtZmVSOy+sWHp8Qlz1IqdCyo ++7uIRNe5PIFDDG4dCjezYpZkuhCoeXAUmG838szabsbCN9hwuJx5YNAMBkGy5jqd +ou8NxNPCoMZtaKuhzjQUsow7IQ3brg78CnyB0pfFTDbPs1C9GLF5munvwK1prCLU +4KSbc4ZhjX88dLfClh3FTjdV0kQvlubf0Z71LqR9aMlU4WEFxE7KIeyolAGYdip4 +xwIDAQAB +-----END PUBLIC KEY-----