feat(payment): 添加支付配置诊断和测试接口
- 新增支付配置诊断SQL脚本 - 添加测试控制器和微信支付诊断控制器 - 实现支付配置检查、快速测试和缓存清理等功能 -优化支付服务和订单创建流程- 更新相关实体和DTO以支持新功能
This commit is contained in:
@@ -0,0 +1,302 @@
|
||||
package com.gxwebsoft.common.core.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.service.PaymentCacheService;
|
||||
import com.gxwebsoft.common.system.entity.Payment;
|
||||
import com.gxwebsoft.common.system.service.PaymentService;
|
||||
import com.gxwebsoft.common.system.param.PaymentParam;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 测试控制器
|
||||
* 用于测试LocalDateTime序列化
|
||||
*
|
||||
* @author WebSoft
|
||||
* @since 2025-01-12
|
||||
*/
|
||||
@Tag(name = "测试接口")
|
||||
@RestController
|
||||
@RequestMapping("/api/test")
|
||||
public class TestController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private PaymentCacheService paymentCacheService;
|
||||
|
||||
@Autowired
|
||||
private PaymentService paymentService;
|
||||
|
||||
@Operation(summary = "测试LocalDateTime序列化")
|
||||
@GetMapping("/datetime")
|
||||
public ApiResult<Map<String, Object>> testDateTime() {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
// 使用字符串格式避免序列化问题
|
||||
result.put("currentTime", LocalDateTime.now().toString());
|
||||
result.put("currentTimeFormatted", LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
||||
result.put("message", "LocalDateTime序列化测试");
|
||||
result.put("timestamp", System.currentTimeMillis());
|
||||
return success(result);
|
||||
}
|
||||
|
||||
@Operation(summary = "基础诊断 - 不依赖支付服务")
|
||||
@GetMapping("/basic-debug/{tenantId}")
|
||||
public ApiResult<String> basicDebug(@PathVariable Integer tenantId) {
|
||||
try {
|
||||
System.out.println("=== 基础诊断开始 ===");
|
||||
System.out.println("接收到的租户ID: " + tenantId);
|
||||
|
||||
if (tenantId == null) {
|
||||
return fail("租户ID为null",null);
|
||||
}
|
||||
|
||||
return success("基础诊断通过,租户ID: " + tenantId,null);
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("基础诊断异常: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
return fail("基础诊断异常: " + e.getMessage(),null);
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "快速诊断支付配置")
|
||||
@GetMapping("/payment-debug/{tenantId}")
|
||||
public ApiResult<String> debugPaymentConfig(@PathVariable Integer tenantId) {
|
||||
try {
|
||||
System.out.println("=== 开始诊断租户 " + tenantId + " 的支付配置 ===");
|
||||
|
||||
// 检查基础参数
|
||||
if (tenantId == null) {
|
||||
return fail("租户ID为null",null);
|
||||
}
|
||||
|
||||
// 检查服务是否可用
|
||||
if (paymentCacheService == null) {
|
||||
return fail("PaymentCacheService未注入",null);
|
||||
}
|
||||
|
||||
System.out.println("准备调用 paymentCacheService.getWechatPayConfig(" + tenantId + ")");
|
||||
|
||||
// 获取支付配置
|
||||
Payment payment = null;
|
||||
try {
|
||||
payment = paymentCacheService.getWechatPayConfig(tenantId);
|
||||
System.out.println("成功调用 getWechatPayConfig,结果: " + (payment != null ? "非null" : "null"));
|
||||
} catch (Exception e) {
|
||||
System.err.println("调用 getWechatPayConfig 异常: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
return fail("获取支付配置异常: " + e.getMessage() + " (类型: " + e.getClass().getName() + ")",null);
|
||||
}
|
||||
|
||||
if (payment == null) {
|
||||
System.out.println("❌ 支付配置不存在");
|
||||
return fail("支付配置不存在,租户ID: " + tenantId,null);
|
||||
}
|
||||
|
||||
// 构建诊断信息字符串,避免序列化问题
|
||||
StringBuilder diagnosis = new StringBuilder();
|
||||
diagnosis.append("=== 支付配置诊断结果 ===\n");
|
||||
diagnosis.append("租户ID: ").append(tenantId).append("\n");
|
||||
diagnosis.append("商户号: ").append(payment.getMchId()).append("\n");
|
||||
diagnosis.append("应用ID: ").append(payment.getAppId()).append("\n");
|
||||
diagnosis.append("证书序列号: ").append(payment.getMerchantSerialNumber()).append("\n");
|
||||
diagnosis.append("API密钥: ").append(payment.getApiKey() != null ? "已配置(长度:" + payment.getApiKey().length() + ")" : "未配置").append("\n");
|
||||
diagnosis.append("状态: ").append(payment.getStatus()).append("\n");
|
||||
diagnosis.append("私钥文件: ").append(payment.getApiclientKey()).append("\n");
|
||||
diagnosis.append("证书文件: ").append(payment.getApiclientCert()).append("\n");
|
||||
diagnosis.append("公钥文件: ").append(payment.getPubKey()).append("\n");
|
||||
diagnosis.append("公钥ID: ").append(payment.getPubKeyId()).append("\n");
|
||||
|
||||
// 检查问题
|
||||
StringBuilder issues = new StringBuilder();
|
||||
if (payment.getMchId() == null || payment.getMchId().trim().isEmpty()) {
|
||||
issues.append("❌ 商户号为空\n");
|
||||
}
|
||||
if (payment.getAppId() == null || payment.getAppId().trim().isEmpty()) {
|
||||
issues.append("❌ 应用ID为空\n");
|
||||
}
|
||||
if (payment.getMerchantSerialNumber() == null || payment.getMerchantSerialNumber().trim().isEmpty()) {
|
||||
issues.append("❌ 证书序列号为空\n");
|
||||
}
|
||||
if (payment.getApiKey() == null || payment.getApiKey().trim().isEmpty()) {
|
||||
issues.append("❌ API密钥为空\n");
|
||||
} else if (payment.getApiKey().length() != 32) {
|
||||
issues.append("❌ API密钥长度错误(").append(payment.getApiKey().length()).append("位)\n");
|
||||
}
|
||||
if (payment.getStatus() == null || !payment.getStatus()) {
|
||||
issues.append("❌ 支付配置未启用\n");
|
||||
}
|
||||
|
||||
if (issues.length() > 0) {
|
||||
diagnosis.append("\n=== 发现的问题 ===\n");
|
||||
diagnosis.append(issues.toString());
|
||||
} else {
|
||||
diagnosis.append("\n✅ 配置检查通过,无问题发现");
|
||||
}
|
||||
|
||||
// 打印到控制台
|
||||
System.out.println(diagnosis.toString());
|
||||
|
||||
if (issues.length() > 0) {
|
||||
return fail(diagnosis.toString(),null);
|
||||
} else {
|
||||
return success(diagnosis.toString(),null);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
String errorMsg = "诊断失败: " + e.getMessage() + " (类型: " + e.getClass().getName() + ")";
|
||||
System.err.println(errorMsg);
|
||||
e.printStackTrace();
|
||||
return fail(errorMsg,null);
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "直接数据库查询支付配置")
|
||||
@GetMapping("/db-payment-check/{tenantId}")
|
||||
public ApiResult<String> checkPaymentFromDB(@PathVariable Integer tenantId) {
|
||||
try {
|
||||
System.out.println("=== 直接数据库查询支付配置 ===");
|
||||
System.out.println("租户ID: " + tenantId);
|
||||
|
||||
if (tenantId == null) {
|
||||
return fail("租户ID为null",null);
|
||||
}
|
||||
|
||||
if (paymentService == null) {
|
||||
return fail("PaymentService未注入",null);
|
||||
}
|
||||
|
||||
// 直接查询数据库,不使用缓存
|
||||
PaymentParam param = new PaymentParam();
|
||||
param.setType(0); // 微信支付
|
||||
param.setTenantId(tenantId);
|
||||
|
||||
System.out.println("准备查询数据库,参数: type=0, tenantId=" + tenantId);
|
||||
|
||||
java.util.List<Payment> payments = paymentService.listRel(param);
|
||||
|
||||
System.out.println("查询结果数量: " + (payments != null ? payments.size() : "null"));
|
||||
|
||||
if (payments == null || payments.isEmpty()) {
|
||||
return fail("数据库中没有找到租户 " + tenantId + " 的微信支付配置",null);
|
||||
}
|
||||
|
||||
Payment payment = payments.get(0);
|
||||
|
||||
StringBuilder result = new StringBuilder();
|
||||
result.append("=== 数据库查询结果 ===\n");
|
||||
result.append("租户ID: ").append(payment.getTenantId()).append("\n");
|
||||
result.append("支付方式: ").append(payment.getName()).append("\n");
|
||||
result.append("类型: ").append(payment.getType()).append("\n");
|
||||
result.append("商户号: ").append(payment.getMchId()).append("\n");
|
||||
result.append("应用ID: ").append(payment.getAppId()).append("\n");
|
||||
result.append("证书序列号: ").append(payment.getMerchantSerialNumber()).append("\n");
|
||||
result.append("API密钥状态: ").append(payment.getApiKey() != null ? "已配置(长度:" + payment.getApiKey().length() + ")" : "未配置").append("\n");
|
||||
result.append("状态: ").append(payment.getStatus()).append("\n");
|
||||
result.append("是否删除: ").append(payment.getDeleted()).append("\n");
|
||||
|
||||
System.out.println(result.toString());
|
||||
|
||||
return success(result.toString(),null);
|
||||
|
||||
} catch (Exception e) {
|
||||
String errorMsg = "数据库查询异常: " + e.getMessage() + " (类型: " + e.getClass().getName() + ")";
|
||||
System.err.println(errorMsg);
|
||||
e.printStackTrace();
|
||||
return fail(errorMsg,null);
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "清理支付配置缓存")
|
||||
@GetMapping("/clear-payment-cache/{tenantId}")
|
||||
public String clearPaymentCache(@PathVariable Integer tenantId) {
|
||||
try {
|
||||
System.out.println("=== 清理支付配置缓存 ===");
|
||||
System.out.println("租户ID: " + tenantId);
|
||||
|
||||
if (tenantId == null) {
|
||||
return "错误: 租户ID为null";
|
||||
}
|
||||
|
||||
// 清理可能的缓存键
|
||||
paymentCacheService.removePaymentConfig("0", tenantId); // 微信支付
|
||||
paymentCacheService.removePaymentConfig("wechat", tenantId); // 可能的其他格式
|
||||
|
||||
String result = "✅ 缓存已清理,租户ID: " + tenantId;
|
||||
System.out.println(result);
|
||||
return result;
|
||||
|
||||
} catch (Exception e) {
|
||||
String errorMsg = "❌ 清理缓存异常: " + e.getMessage();
|
||||
System.err.println(errorMsg);
|
||||
e.printStackTrace();
|
||||
return errorMsg;
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "最简单的测试接口")
|
||||
@GetMapping("/simple-test")
|
||||
public String simpleTest() {
|
||||
return "✅ 测试接口正常工作,时间: " + System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@Operation(summary = "测试支付配置是否存在")
|
||||
@GetMapping("/check-payment-exists/{tenantId}")
|
||||
public String checkPaymentExists(@PathVariable Integer tenantId) {
|
||||
try {
|
||||
System.out.println("=== 检查支付配置是否存在 ===");
|
||||
System.out.println("租户ID: " + tenantId);
|
||||
|
||||
if (tenantId == null) {
|
||||
return "❌ 租户ID为null";
|
||||
}
|
||||
|
||||
if (paymentService == null) {
|
||||
return "❌ PaymentService未注入";
|
||||
}
|
||||
|
||||
// 使用最简单的查询
|
||||
PaymentParam param = new PaymentParam();
|
||||
param.setType(0);
|
||||
param.setTenantId(tenantId);
|
||||
|
||||
java.util.List<Payment> payments = paymentService.listRel(param);
|
||||
|
||||
if (payments == null) {
|
||||
return "❌ 查询结果为null";
|
||||
}
|
||||
|
||||
if (payments.isEmpty()) {
|
||||
return "❌ 没有找到支付配置,租户ID: " + tenantId;
|
||||
}
|
||||
|
||||
Payment payment = payments.get(0);
|
||||
StringBuilder result = new StringBuilder();
|
||||
result.append("✅ 找到支付配置\n");
|
||||
result.append("租户ID: ").append(payment.getTenantId()).append("\n");
|
||||
result.append("商户号: ").append(payment.getMchId() != null ? payment.getMchId() : "NULL").append("\n");
|
||||
result.append("应用ID: ").append(payment.getAppId() != null ? payment.getAppId() : "NULL").append("\n");
|
||||
result.append("状态: ").append(payment.getStatus()).append("\n");
|
||||
|
||||
return result.toString();
|
||||
|
||||
} catch (Exception e) {
|
||||
String error = "❌ 检查异常: " + e.getMessage();
|
||||
System.err.println(error);
|
||||
e.printStackTrace();
|
||||
return error;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
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.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
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")
|
||||
@Tag(name = "微信支付证书自动配置测试")
|
||||
public class WechatCertTestController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private WechatCertAutoConfig wechatCertAutoConfig;
|
||||
|
||||
@Operation(summary = "测试默认开发环境证书配置")
|
||||
@PostMapping("/test-default")
|
||||
public ApiResult<Map<String, Object>> testDefaultConfig() {
|
||||
Map<String, Object> 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);
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "测试自定义证书配置")
|
||||
@PostMapping("/test-custom")
|
||||
public ApiResult<Map<String, Object>> testCustomConfig(
|
||||
@Parameter(description = "商户号") @RequestParam String merchantId,
|
||||
@Parameter(description = "私钥文件路径") @RequestParam String privateKeyPath,
|
||||
@Parameter(description = "证书序列号") @RequestParam String merchantSerialNumber,
|
||||
@Parameter(description = "APIv3密钥") @RequestParam String apiV3Key) {
|
||||
|
||||
Map<String, Object> 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);
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "获取使用说明")
|
||||
@GetMapping("/instructions")
|
||||
public ApiResult<String> getInstructions() {
|
||||
String instructions = wechatCertAutoConfig.getUsageInstructions();
|
||||
return success("获取使用说明成功", instructions);
|
||||
}
|
||||
|
||||
@Operation(summary = "获取故障排除信息")
|
||||
@GetMapping("/troubleshooting")
|
||||
public ApiResult<Map<String, Object>> getTroubleshooting() {
|
||||
Map<String, Object> troubleshooting = getTroubleshootingInfo();
|
||||
return success("获取故障排除信息成功", troubleshooting);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取故障排除信息
|
||||
*/
|
||||
private Map<String, Object> getTroubleshootingInfo() {
|
||||
Map<String, Object> 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;
|
||||
}
|
||||
|
||||
@Operation(summary = "检查商户平台配置状态")
|
||||
@PostMapping("/check-merchant-config")
|
||||
public ApiResult<Map<String, Object>> checkMerchantConfig(
|
||||
@RequestParam String merchantId,
|
||||
@RequestParam String privateKeyPath,
|
||||
@RequestParam String merchantSerialNumber,
|
||||
@RequestParam String apiV3Key) {
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
|
||||
try {
|
||||
log.info("开始检查商户平台配置状态...");
|
||||
log.info("商户号: {}", merchantId);
|
||||
|
||||
// 尝试创建自动证书配置
|
||||
Config config = wechatCertAutoConfig.createAutoConfig(
|
||||
merchantId, privateKeyPath, merchantSerialNumber, apiV3Key);
|
||||
|
||||
result.put("success", true);
|
||||
result.put("configCreated", true);
|
||||
result.put("message", "商户平台配置正常,自动证书配置创建成功");
|
||||
result.put("merchantId", merchantId);
|
||||
result.put("recommendation", "配置正常,可以正常使用微信支付功能");
|
||||
|
||||
log.info("✅ 商户平台配置检查成功");
|
||||
return success("配置检查成功", result);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("❌ 商户平台配置检查失败: {}", e.getMessage(), e);
|
||||
|
||||
result.put("success", false);
|
||||
result.put("configCreated", false);
|
||||
result.put("error", e.getMessage());
|
||||
result.put("merchantId", merchantId);
|
||||
|
||||
// 分析错误类型并提供解决方案
|
||||
if (e.getMessage().contains("404") || e.getMessage().contains("RESOURCE_NOT_EXISTS")) {
|
||||
result.put("errorType", "商户平台配置问题");
|
||||
result.put("solution", "请在微信支付商户平台完成以下配置:\n" +
|
||||
"1. 登录商户平台:https://pay.weixin.qq.com/\n" +
|
||||
"2. 进入:产品中心 → 开发配置 → API安全\n" +
|
||||
"3. 申请API证书\n" +
|
||||
"4. 申请使用微信支付公钥\n" +
|
||||
"5. 确保API证书和微信支付公钥状态为\"已生效\"");
|
||||
result.put("documentUrl", "https://pay.weixin.qq.com/doc/v3/merchant/4012153196");
|
||||
} else {
|
||||
result.put("errorType", "其他配置问题");
|
||||
result.put("solution", "请检查商户号、证书序列号、API密钥等配置是否正确");
|
||||
}
|
||||
|
||||
return success("配置检查完成(发现问题)", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import com.gxwebsoft.common.core.utils.WechatPayCertificateDiagnostic;
|
||||
import com.gxwebsoft.common.core.utils.WechatPayConfigChecker;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.system.entity.Payment;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@@ -37,7 +36,7 @@ public class WechatPayDiagnosticController extends com.gxwebsoft.common.core.web
|
||||
private com.gxwebsoft.common.core.service.PaymentCacheService paymentCacheService;
|
||||
|
||||
@Autowired
|
||||
private com.gxwebsoft.common.core.utils.WechatPayConfigChecker configChecker;
|
||||
private WechatPayConfigChecker configChecker;
|
||||
|
||||
@Value("${spring.profiles.active:dev}")
|
||||
private String activeProfile;
|
||||
|
||||
@@ -62,6 +62,7 @@ public class SecurityConfig {
|
||||
"/api/mp/mp/component_verify_ticket",
|
||||
"/api/mp/mp/callback",
|
||||
"/api/shop/test/**",
|
||||
"/api/test/payment-debug/**",
|
||||
"/api/shop/wx-login/**",
|
||||
"/api/shop/wx-native-pay/**",
|
||||
"/api/shop/wx-pay/**",
|
||||
|
||||
@@ -70,11 +70,15 @@ public class PaymentCacheService {
|
||||
}
|
||||
|
||||
Payment dbPayment = payments.get(0);
|
||||
|
||||
// 清理时间字段,避免序列化问题
|
||||
Payment cachePayment = cleanPaymentForCache(dbPayment);
|
||||
|
||||
// 将查询结果缓存到 Payment:1* 格式
|
||||
redisUtil.set(primaryKey, dbPayment);
|
||||
redisUtil.set(primaryKey, cachePayment);
|
||||
log.debug("支付配置已缓存到: {}", primaryKey);
|
||||
|
||||
return dbPayment;
|
||||
return dbPayment; // 返回原始对象,不影响业务逻辑
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,4 +132,43 @@ public class PaymentCacheService {
|
||||
public Payment getAlipayConfig(Integer tenantId) {
|
||||
return getPaymentConfig(1, tenantId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理Payment对象用于缓存
|
||||
* 移除可能导致序列化问题的时间字段
|
||||
*/
|
||||
private Payment cleanPaymentForCache(Payment original) {
|
||||
if (original == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Payment cleaned = new Payment();
|
||||
// 复制所有业务相关字段
|
||||
cleaned.setId(original.getId());
|
||||
cleaned.setName(original.getName());
|
||||
cleaned.setType(original.getType());
|
||||
cleaned.setCode(original.getCode());
|
||||
cleaned.setImage(original.getImage());
|
||||
cleaned.setWechatType(original.getWechatType());
|
||||
cleaned.setAppId(original.getAppId());
|
||||
cleaned.setMchId(original.getMchId());
|
||||
cleaned.setApiKey(original.getApiKey());
|
||||
cleaned.setApiclientCert(original.getApiclientCert());
|
||||
cleaned.setApiclientKey(original.getApiclientKey());
|
||||
cleaned.setPubKey(original.getPubKey());
|
||||
cleaned.setPubKeyId(original.getPubKeyId());
|
||||
cleaned.setMerchantSerialNumber(original.getMerchantSerialNumber());
|
||||
cleaned.setNotifyUrl(original.getNotifyUrl());
|
||||
cleaned.setComments(original.getComments());
|
||||
cleaned.setSortNumber(original.getSortNumber());
|
||||
cleaned.setStatus(original.getStatus());
|
||||
cleaned.setDeleted(original.getDeleted());
|
||||
cleaned.setTenantId(original.getTenantId());
|
||||
|
||||
// 不设置时间字段,避免序列化问题
|
||||
// cleaned.setCreateTime(null);
|
||||
// cleaned.setUpdateTime(null);
|
||||
|
||||
return cleaned;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.gxwebsoft.common.system.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 支付配置缓存DTO
|
||||
* 专门用于Redis缓存,不包含时间字段,避免序列化问题
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-01-13
|
||||
*/
|
||||
@Data
|
||||
public class PaymentCacheDTO implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Integer id;
|
||||
private String name;
|
||||
private Integer type;
|
||||
private String code;
|
||||
private String image;
|
||||
private Integer wechatType;
|
||||
private String appId;
|
||||
private String mchId;
|
||||
private String apiKey;
|
||||
private String apiclientCert;
|
||||
private String apiclientKey;
|
||||
private String pubKey;
|
||||
private String pubKeyId;
|
||||
private String merchantSerialNumber;
|
||||
private String notifyUrl;
|
||||
private String comments;
|
||||
private Integer sortNumber;
|
||||
private Boolean status;
|
||||
private Integer deleted;
|
||||
private Integer tenantId;
|
||||
|
||||
// 不包含 createTime 和 updateTime 字段,避免序列化问题
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import lombok.EqualsAndHashCode;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
/**
|
||||
* 支付方式
|
||||
@@ -89,11 +90,11 @@ public class Payment implements Serializable {
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "注册时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonIgnore // 缓存时忽略此字段
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonIgnore // 缓存时忽略此字段
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
|
||||
@@ -122,13 +122,35 @@ public class ShopOrderServiceImpl extends ServiceImpl<ShopOrderMapper, ShopOrder
|
||||
@Override
|
||||
public HashMap<String, String> createWxOrder(ShopOrder order) {
|
||||
try {
|
||||
// 后台微信支付配置信息
|
||||
final Payment payment = getPayment(order);
|
||||
System.out.println("=== 开始创建微信支付订单 ===");
|
||||
System.out.println("订单号: " + order.getOrderNo());
|
||||
System.out.println("租户ID: " + order.getTenantId());
|
||||
System.out.println("支付类型: " + order.getPayType());
|
||||
System.out.println("订单金额: " + order.getTotalPrice());
|
||||
System.out.println("用户OpenID: " + order.getOpenid());
|
||||
|
||||
// 检查订单基本信息
|
||||
if (order.getTenantId() == null) {
|
||||
throw new RuntimeException("订单租户ID为null");
|
||||
}
|
||||
if (order.getOrderNo() == null || order.getOrderNo().trim().isEmpty()) {
|
||||
throw new RuntimeException("订单号为空");
|
||||
}
|
||||
if (order.getTotalPrice() == null) {
|
||||
throw new RuntimeException("订单金额为null");
|
||||
}
|
||||
if (order.getOpenid() == null || order.getOpenid().trim().isEmpty()) {
|
||||
throw new RuntimeException("用户OpenID为空");
|
||||
}
|
||||
|
||||
// 后台微信支付配置信息
|
||||
final Payment payment = getPayment(order);
|
||||
System.out.println("支付配置: " + (payment != null ? "已获取" : "未获取"));
|
||||
|
||||
if (payment == null) {
|
||||
throw new RuntimeException("支付配置为null,租户ID: " + order.getTenantId());
|
||||
}
|
||||
|
||||
// 返回的订单数据
|
||||
final HashMap<String, String> orderInfo = new HashMap<>();
|
||||
// 构建service
|
||||
@@ -141,19 +163,41 @@ public class ShopOrderServiceImpl extends ServiceImpl<ShopOrderMapper, ShopOrder
|
||||
final BigDecimal multiply = decimal.multiply(new BigDecimal(100));
|
||||
Integer money = multiply.intValue();
|
||||
|
||||
System.out.println("=== 构建支付请求参数 ===");
|
||||
|
||||
// 检查支付配置的关键字段
|
||||
if (payment.getAppId() == null || payment.getAppId().trim().isEmpty()) {
|
||||
throw new RuntimeException("支付配置中应用ID为null或空");
|
||||
}
|
||||
if (payment.getMchId() == null || payment.getMchId().trim().isEmpty()) {
|
||||
throw new RuntimeException("支付配置中商户号为null或空");
|
||||
}
|
||||
|
||||
PrepayRequest request = new PrepayRequest();
|
||||
Amount amount = new Amount();
|
||||
amount.setTotal(money);
|
||||
amount.setCurrency("CNY");
|
||||
request.setAmount(amount);
|
||||
|
||||
System.out.println("设置应用ID: " + payment.getAppId());
|
||||
request.setAppid(payment.getAppId());
|
||||
|
||||
System.out.println("设置商户号: " + payment.getMchId());
|
||||
request.setMchid(payment.getMchId());
|
||||
|
||||
// 微信支付description字段限制127字节,需要截断处理
|
||||
String description = com.gxwebsoft.common.core.utils.WechatPayUtils.processDescription(order.getComments());
|
||||
System.out.println("设置描述: " + description);
|
||||
request.setDescription(description);
|
||||
|
||||
System.out.println("设置订单号: " + order.getOrderNo());
|
||||
request.setOutTradeNo(order.getOrderNo());
|
||||
|
||||
System.out.println("设置附加数据: " + order.getTenantId().toString());
|
||||
request.setAttach(order.getTenantId().toString());
|
||||
|
||||
final Payer payer = new Payer();
|
||||
System.out.println("设置用户OpenID: " + order.getOpenid());
|
||||
payer.setOpenid(order.getOpenid());
|
||||
request.setPayer(payer);
|
||||
request.setNotifyUrl(config.getServerUrl() + "/system/wx-pay/notify/" + order.getTenantId()); // 默认回调地址
|
||||
|
||||
Reference in New Issue
Block a user