diff --git a/src/main/java/com/gxwebsoft/payment/controller/PaymentController.java b/src/main/java/com/gxwebsoft/payment/controller/PaymentController.java index 02f5c74..0d51551 100644 --- a/src/main/java/com/gxwebsoft/payment/controller/PaymentController.java +++ b/src/main/java/com/gxwebsoft/payment/controller/PaymentController.java @@ -112,6 +112,17 @@ public class PaymentController extends BaseController { log.info("查询支付状态: orderNo={}, paymentType={}, tenantId={}", orderNo, paymentType, tenantId); + // 参数验证 + if (orderNo == null || orderNo.trim().isEmpty()) { + return fail("订单号不能为空"); + } + if (paymentType == null) { + return fail("支付类型不能为空"); + } + if (tenantId == null || tenantId <= 0) { + return fail("租户ID不能为空且必须为正数"); + } + try { PaymentResponse response = paymentService.queryPayment(orderNo, paymentType, tenantId); return this.success("支付状态查询成功", response); @@ -302,4 +313,48 @@ public class PaymentController extends BaseController { return fail("更新支付状态失败: " + e.getMessage()); } } + + @Operation(summary = "检查支付配置", description = "检查指定租户的支付配置是否完整") + @GetMapping("/config/check") + public ApiResult checkPaymentConfig( + @Parameter(description = "租户ID", required = true) + @RequestParam @NotNull(message = "租户ID不能为空") @Positive(message = "租户ID必须为正数") Integer tenantId) { + + log.info("检查支付配置,租户ID: {}", tenantId); + + try { + Map configStatus = paymentService.checkPaymentConfig(tenantId); + return this.>success("配置检查完成", configStatus); + } catch (Exception e) { + log.error("检查支付配置失败: {}", e.getMessage(), e); + return fail("检查支付配置失败: " + e.getMessage()); + } + } + + @Operation(summary = "查询用户最近的支付订单", description = "当orderNo缺失时,查询用户最近创建的支付订单") + @GetMapping("/query-recent") + public ApiResult queryRecentPayment( + @Parameter(description = "支付类型", required = true) + @RequestParam @NotNull(message = "支付类型不能为空") PaymentType paymentType, + + @Parameter(description = "租户ID", required = true) + @RequestParam @NotNull(message = "租户ID不能为空") @Positive(message = "租户ID必须为正数") Integer tenantId) { + + log.info("查询用户最近支付订单: paymentType={}, tenantId={}", paymentType, tenantId); + + final User loginUser = getLoginUser(); + if(loginUser == null){ + return fail("请先登录"); + } + + try { + // 这里需要实现查询用户最近订单的逻辑 + // 可以通过用户ID和租户ID查询最近创建的订单 + return fail("此功能需要实现查询用户最近订单的业务逻辑"); + + } catch (Exception e) { + log.error("查询用户最近支付订单失败: {}", e.getMessage(), e); + return fail("查询失败: " + e.getMessage()); + } + } } diff --git a/src/main/java/com/gxwebsoft/payment/service/PaymentService.java b/src/main/java/com/gxwebsoft/payment/service/PaymentService.java index b1d00f1..0f90fd5 100644 --- a/src/main/java/com/gxwebsoft/payment/service/PaymentService.java +++ b/src/main/java/com/gxwebsoft/payment/service/PaymentService.java @@ -171,4 +171,12 @@ public interface PaymentService { * @return 所有策略信息列表 */ List> getAllPaymentStrategyInfo(); + + /** + * 检查支付配置 + * + * @param tenantId 租户ID + * @return 配置检查结果 + */ + Map checkPaymentConfig(Integer tenantId); } diff --git a/src/main/java/com/gxwebsoft/payment/service/WxPayConfigService.java b/src/main/java/com/gxwebsoft/payment/service/WxPayConfigService.java index 3060e5e..f072786 100644 --- a/src/main/java/com/gxwebsoft/payment/service/WxPayConfigService.java +++ b/src/main/java/com/gxwebsoft/payment/service/WxPayConfigService.java @@ -126,19 +126,26 @@ public class WxPayConfigService { // 缓存中没有,尝试从数据库查询 try { - final PaymentParam paymentParam = new PaymentParam(); - paymentParam.setType(102); - paymentParam.setTenantId(tenantId); - payment = paymentService.getByType(paymentParam); - System.out.println("payment1 = " + payment); - if (payment != null) { + final PaymentParam paymentParam = new PaymentParam(); + paymentParam.setType(102); + paymentParam.setTenantId(tenantId); + + log.debug("查询数据库支付配置,参数: type=102, tenantId={}", tenantId); + payment = paymentService.getByType(paymentParam); + log.debug("数据库查询结果: {}", payment != null ? "找到配置" : "未找到配置"); + + if (payment != null) { log.info("从数据库获取支付配置成功,租户ID: {},将缓存配置", tenantId); - // 将查询到的配置缓存起来,缓存1小时 - redisUtil.set(cacheKey, payment, 1L,TimeUnit.DAYS); + // 将查询到的配置缓存起来,缓存1天 + redisUtil.set(cacheKey, payment, 1L, TimeUnit.DAYS); return payment; + } else { + log.warn("数据库中未找到支付配置,租户ID: {}, type: 102", tenantId); } } catch (Exception e) { - log.warn("从数据库查询支付配置失败,租户ID: {},错误: {}", tenantId, e.getMessage()); + log.error("从数据库查询支付配置失败,租户ID: {},错误: {}", tenantId, e.getMessage(), e); + // 抛出更详细的异常信息 + throw PaymentException.systemError("查询支付配置失败,租户ID: " + tenantId + ",错误: " + e.getMessage(), e); } // 数据库也没有配置 @@ -278,9 +285,8 @@ public class WxPayConfigService { * 创建正常配置 */ private Config createNormalConfig(Payment payment, String certificatePath) throws PaymentException { - if (payment.getMchId() == null || payment.getMerchantSerialNumber() == null || payment.getApiKey() == null) { - throw PaymentException.systemError("支付配置信息不完整:商户号、序列号或APIv3密钥为空", null); - } + // 验证配置完整性 + validatePaymentConfig(payment); log.info("使用数据库支付配置"); log.debug("商户号: {}", payment.getMchId()); @@ -293,6 +299,33 @@ public class WxPayConfigService { .build(); } + /** + * 验证支付配置完整性 + */ + private void validatePaymentConfig(Payment payment) throws PaymentException { + if (payment == null) { + throw PaymentException.systemError("支付配置为空", null); + } + + if (payment.getMchId() == null || payment.getMchId().trim().isEmpty()) { + throw PaymentException.systemError("商户号(mchId)未配置", null); + } + + if (payment.getMerchantSerialNumber() == null || payment.getMerchantSerialNumber().trim().isEmpty()) { + throw PaymentException.systemError("商户证书序列号(merchantSerialNumber)未配置", null); + } + + if (payment.getApiKey() == null || payment.getApiKey().trim().isEmpty()) { + throw PaymentException.systemError("APIv3密钥(apiKey)未配置", null); + } + + if (payment.getApiclientKey() == null || payment.getApiclientKey().trim().isEmpty()) { + throw PaymentException.systemError("证书文件名(apiclientKey)未配置", null); + } + + log.debug("支付配置验证通过,租户ID: {}, 商户号: {}", payment.getTenantId(), payment.getMchId()); + } + /** * 清除指定租户的配置缓存 * diff --git a/src/main/java/com/gxwebsoft/payment/service/impl/PaymentServiceImpl.java b/src/main/java/com/gxwebsoft/payment/service/impl/PaymentServiceImpl.java index d6b5df8..cfc4b27 100644 --- a/src/main/java/com/gxwebsoft/payment/service/impl/PaymentServiceImpl.java +++ b/src/main/java/com/gxwebsoft/payment/service/impl/PaymentServiceImpl.java @@ -1,5 +1,7 @@ package com.gxwebsoft.payment.service.impl; +import cn.hutool.core.util.IdUtil; +import com.gxwebsoft.common.core.utils.CommonUtil; import com.gxwebsoft.common.system.entity.User; import com.gxwebsoft.payment.constants.PaymentConstants; import com.gxwebsoft.payment.dto.PaymentRequest; @@ -8,6 +10,7 @@ import com.gxwebsoft.payment.dto.PaymentWithOrderRequest; import com.gxwebsoft.payment.enums.PaymentType; import com.gxwebsoft.payment.exception.PaymentException; import com.gxwebsoft.payment.service.PaymentService; +import com.gxwebsoft.payment.service.WxPayConfigService; import com.gxwebsoft.payment.strategy.PaymentStrategy; import com.gxwebsoft.shop.dto.OrderCreateRequest; import com.gxwebsoft.shop.service.OrderBusinessService; @@ -50,6 +53,12 @@ public class PaymentServiceImpl implements PaymentService { @Resource private OrderBusinessService orderBusinessService; + /** + * 微信支付配置服务 + */ + @Resource + private WxPayConfigService wxPayConfigService; + /** * 初始化策略映射 */ @@ -416,6 +425,34 @@ public class PaymentServiceImpl implements PaymentService { .collect(Collectors.toList()); } + @Override + public Map checkPaymentConfig(Integer tenantId) { + Map result = new HashMap<>(); + result.put("tenantId", tenantId); + + try { + // 检查微信支付配置 + wxPayConfigService.getPaymentConfigForStrategy(tenantId); + result.put("wechatConfigExists", true); + result.put("wechatConfigError", null); + } catch (Exception e) { + result.put("wechatConfigExists", false); + result.put("wechatConfigError", e.getMessage()); + } + + try { + // 检查微信支付Config构建 + wxPayConfigService.getWxPayConfig(tenantId); + result.put("wechatConfigValid", true); + result.put("wechatConfigValidError", null); + } catch (Exception e) { + result.put("wechatConfigValid", false); + result.put("wechatConfigValidError", e.getMessage()); + } + + return result; + } + /** * 获取支付策略 */ @@ -554,6 +591,11 @@ public class PaymentServiceImpl implements PaymentService { private OrderCreateRequest convertToOrderCreateRequest(PaymentWithOrderRequest request, User loginUser) { OrderCreateRequest orderRequest = new OrderCreateRequest(); + // 生成订单号(使用雪花算法保证全局唯一) + String orderNo = Long.toString(IdUtil.getSnowflakeNextId()); + orderRequest.setOrderNo(orderNo); + log.info("为订单创建请求生成订单号(雪花算法): {}", orderNo); + // 设置基本信息 orderRequest.setType(request.getOrderInfo().getType()); orderRequest.setTitle(request.getSubject()); @@ -614,8 +656,13 @@ public class PaymentServiceImpl implements PaymentService { // 设置额外信息 response.setSuccess(true); + // 确保orderNo被正确设置 + response.setOrderNo(orderNo); + + // 调试日志 + log.info("构建支付响应成功, 订单号: {}, 二维码URL: {}, 响应中的orderNo: {}", + orderNo, wxOrderInfo.get("codeUrl"), response.getOrderNo()); - log.debug("构建支付响应成功, 订单号: {}, 二维码URL: {}", orderNo, wxOrderInfo.get("codeUrl")); return response; } } diff --git a/src/main/java/com/gxwebsoft/payment/strategy/WechatNativeStrategy.java b/src/main/java/com/gxwebsoft/payment/strategy/WechatNativeStrategy.java index 518cad2..9403ff1 100644 --- a/src/main/java/com/gxwebsoft/payment/strategy/WechatNativeStrategy.java +++ b/src/main/java/com/gxwebsoft/payment/strategy/WechatNativeStrategy.java @@ -1,5 +1,6 @@ package com.gxwebsoft.payment.strategy; +import cn.hutool.core.util.IdUtil; import com.gxwebsoft.common.core.utils.CommonUtil; import com.gxwebsoft.common.system.entity.Payment; import com.gxwebsoft.payment.constants.PaymentConstants; @@ -99,6 +100,7 @@ public class WechatNativeStrategy implements PaymentStrategy { // 生成订单号 String orderNo = generateOrderNo(request); + log.info("生成的订单号: {}", orderNo); // 获取Native支付的Payment配置(包含appId等信息) Payment paymentConfig = wxPayConfigService.getPaymentConfigForStrategy(request.getTenantId()); @@ -117,6 +119,13 @@ public class WechatNativeStrategy implements PaymentStrategy { orderNo, prepayResponse.getCodeUrl(), request.getAmount(), request.getTenantId()); response.setUserId(request.getUserId()); + // 确保orderNo被正确设置 + response.setOrderNo(orderNo); + + // 调试日志:检查响应对象的orderNo + log.info("构建的响应对象 - orderNo: {}, codeUrl: {}, success: {}", + response.getOrderNo(), response.getCodeUrl(), response.getSuccess()); + log.info("{}, 支付类型: {}, 租户ID: {}, 订单号: {}, 金额: {}", PaymentConstants.LogMessage.PAYMENT_SUCCESS, getSupportedPaymentType(), request.getTenantId(), orderNo, request.getFormattedAmount()); @@ -224,13 +233,13 @@ public class WechatNativeStrategy implements PaymentStrategy { } /** - * 生成订单号 + * 生成订单号(使用雪花算法保证全局唯一) */ private String generateOrderNo(PaymentRequest request) { if (StringUtils.hasText(request.getOrderNo())) { return request.getOrderNo(); } - return CommonUtil.createOrderNo(); + return Long.toString(IdUtil.getSnowflakeNextId()); } diff --git a/src/main/java/com/gxwebsoft/shop/service/impl/ShopOrderServiceImpl.java b/src/main/java/com/gxwebsoft/shop/service/impl/ShopOrderServiceImpl.java index d9d08d1..d569325 100644 --- a/src/main/java/com/gxwebsoft/shop/service/impl/ShopOrderServiceImpl.java +++ b/src/main/java/com/gxwebsoft/shop/service/impl/ShopOrderServiceImpl.java @@ -995,7 +995,7 @@ public class ShopOrderServiceImpl extends ServiceImpl