diff --git a/src/main/java/com/gxwebsoft/payment/service/WxPayConfigService.java b/src/main/java/com/gxwebsoft/payment/service/WxPayConfigService.java index f072786..94f8b1a 100644 --- a/src/main/java/com/gxwebsoft/payment/service/WxPayConfigService.java +++ b/src/main/java/com/gxwebsoft/payment/service/WxPayConfigService.java @@ -116,7 +116,7 @@ public class WxPayConfigService { * 优先从缓存获取,缓存没有则查询数据库,最后兜底到开发环境测试配置 */ private Payment getPaymentConfig(Integer tenantId) throws PaymentException { - String cacheKey = "Payment:wxPay:" + tenantId; + String cacheKey = "Payment:1:" + tenantId; Payment payment = redisUtil.get(cacheKey, Payment.class); System.out.println("payment = " + payment); if (payment != null) { @@ -136,6 +136,14 @@ public class WxPayConfigService { if (payment != null) { log.info("从数据库获取支付配置成功,租户ID: {},将缓存配置", tenantId); + + // 开发环境下,如果apiclientKey为空,设置默认值 + if ("dev".equals(activeProfile) && + (payment.getApiclientKey() == null || payment.getApiclientKey().trim().isEmpty())) { + log.warn("开发环境:数据库配置中apiclientKey为空,使用默认值,租户ID: {}", tenantId); + payment.setApiclientKey("apiclient_key.pem"); + } + // 将查询到的配置缓存起来,缓存1天 redisUtil.set(cacheKey, payment, 1L, TimeUnit.DAYS); return payment; @@ -244,9 +252,10 @@ public class WxPayConfigService { testPayment.setTenantId(tenantId); testPayment.setType(102); // Native支付 testPayment.setAppId("wxa67c676fc445590e"); // 开发环境测试AppID - testPayment.setMchId("1246610101"); // 开发环境测试商户号 - testPayment.setMerchantSerialNumber("48749613B40AA8F1D768583FC352358E13EB5AF0"); + testPayment.setMchId("1723321338"); // 租户10550的商户号 + testPayment.setMerchantSerialNumber("2B933F7C35014A1C363642623E4A62364B34C4EB"); // 证书序列号 testPayment.setApiKey(certificateProperties.getWechatPay().getDev().getApiV3Key()); + testPayment.setApiclientKey("apiclient_key.pem"); // 设置证书文件名 testPayment.setNotifyUrl("http://frps-10550.s209.websoft.top/api/payment/notify"); testPayment.setName("微信Native支付-开发环境"); testPayment.setStatus(true); // 启用 @@ -261,8 +270,8 @@ public class WxPayConfigService { * 创建开发环境测试配置 */ private Config createDevTestConfig(String certificatePath) throws PaymentException { - String testMerchantId = "1246610101"; - String testMerchantSerialNumber = "48749613B40AA8F1D768583FC352358E13EB5AF0"; + String testMerchantId = "1723321338"; // 租户10550的商户号 + String testMerchantSerialNumber = "2B933F7C35014A1C363642623E4A62364B34C4EB"; // 证书序列号 String testApiV3Key = certificateProperties.getWechatPay().getDev().getApiV3Key(); if (testApiV3Key == null || testApiV3Key.trim().isEmpty()) { @@ -270,8 +279,10 @@ public class WxPayConfigService { } log.info("使用开发环境测试配置"); - log.debug("测试商户号: {}", testMerchantId); - log.debug("测试序列号: {}", testMerchantSerialNumber); + log.info("测试商户号: {}", testMerchantId); + log.info("测试序列号: {}", testMerchantSerialNumber); + log.info("证书路径: {}", certificatePath); + log.info("APIv3密钥长度: {}", testApiV3Key.length()); return new RSAAutoCertificateConfig.Builder() .merchantId(testMerchantId) @@ -319,8 +330,14 @@ public class WxPayConfigService { throw PaymentException.systemError("APIv3密钥(apiKey)未配置", null); } + // 开发环境下,如果apiclientKey为空,给一个警告但不抛异常 + // 生产环境必须有apiclientKey if (payment.getApiclientKey() == null || payment.getApiclientKey().trim().isEmpty()) { - throw PaymentException.systemError("证书文件名(apiclientKey)未配置", null); + if ("dev".equals(activeProfile)) { + log.warn("开发环境:证书文件名(apiclientKey)未配置,将使用默认值"); + } else { + 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 cfc4b27..a01dafe 100644 --- a/src/main/java/com/gxwebsoft/payment/service/impl/PaymentServiceImpl.java +++ b/src/main/java/com/gxwebsoft/payment/service/impl/PaymentServiceImpl.java @@ -457,7 +457,14 @@ public class PaymentServiceImpl implements PaymentService { * 获取支付策略 */ private PaymentStrategy getPaymentStrategy(PaymentType paymentType) throws PaymentException { - PaymentStrategy strategy = strategyMap.get(paymentType); + // 如果是WECHAT支付类型,转换为WECHAT_NATIVE + // 因为WECHAT是一个通用类型,实际的支付策略是WECHAT_NATIVE + PaymentType actualPaymentType = paymentType; + if (paymentType == PaymentType.WECHAT) { + actualPaymentType = PaymentType.WECHAT_NATIVE; + } + + PaymentStrategy strategy = strategyMap.get(actualPaymentType); if (strategy == null) { throw PaymentException.unsupportedPayment("不支持的支付类型: " + paymentType, paymentType); } diff --git a/src/main/java/com/gxwebsoft/payment/strategy/WechatNativeStrategy.java b/src/main/java/com/gxwebsoft/payment/strategy/WechatNativeStrategy.java index 36a7d89..e5d6b1d 100644 --- a/src/main/java/com/gxwebsoft/payment/strategy/WechatNativeStrategy.java +++ b/src/main/java/com/gxwebsoft/payment/strategy/WechatNativeStrategy.java @@ -517,7 +517,7 @@ public class WechatNativeStrategy implements PaymentStrategy { // 设置退款原因(可选,但建议填写) if (StringUtils.hasText(reason)) { // 退款原因最多80个字符 - String effectiveReason = CommonUtil.truncateString(reason, 80); + String effectiveReason = reason.length() > 80 ? reason.substring(0, 80) : reason; refundRequest.setReason(effectiveReason); } else { refundRequest.setReason("用户申请退款"); @@ -570,7 +570,8 @@ public class WechatNativeStrategy implements PaymentStrategy { response.setTenantId(tenantId); // 转换退款状态 - PaymentStatus paymentStatus = convertWechatRefundStatus(refund.getStatus()); + String statusStr = refund.getStatus() != null ? refund.getStatus().name() : null; + PaymentStatus paymentStatus = convertWechatRefundStatus(statusStr); response.setPaymentStatus(paymentStatus); // 设置退款金额(微信返回的金额是分,需要转换为元) @@ -630,7 +631,8 @@ public class WechatNativeStrategy implements PaymentStrategy { response.setTenantId(tenantId); // 转换退款状态 - PaymentStatus paymentStatus = convertWechatRefundStatus(refund.getStatus()); + String statusStr = refund.getStatus() != null ? refund.getStatus().name() : null; + PaymentStatus paymentStatus = convertWechatRefundStatus(statusStr); response.setPaymentStatus(paymentStatus); // 设置退款金额 @@ -645,19 +647,19 @@ public class WechatNativeStrategy implements PaymentStrategy { /** * 转换微信退款状态 */ - private PaymentStatus convertWechatRefundStatus(Refund.Status refundStatus) { + private PaymentStatus convertWechatRefundStatus(String refundStatus) { if (refundStatus == null) { return PaymentStatus.REFUNDING; } switch (refundStatus) { - case SUCCESS: + case "SUCCESS": return PaymentStatus.REFUNDED; - case CLOSED: + case "CLOSED": return PaymentStatus.REFUND_FAILED; - case PROCESSING: + case "PROCESSING": return PaymentStatus.REFUNDING; - case ABNORMAL: + case "ABNORMAL": return PaymentStatus.REFUND_FAILED; default: return PaymentStatus.REFUNDING; diff --git a/src/main/java/com/gxwebsoft/shop/controller/ShopOrderController.java b/src/main/java/com/gxwebsoft/shop/controller/ShopOrderController.java index 72032fc..879733e 100644 --- a/src/main/java/com/gxwebsoft/shop/controller/ShopOrderController.java +++ b/src/main/java/com/gxwebsoft/shop/controller/ShopOrderController.java @@ -179,6 +179,10 @@ public class ShopOrderController extends BaseController { @Operation(summary = "修改订单") @PutMapping() public ApiResult update(@RequestBody ShopOrder shopOrder) throws Exception { + // 1. 验证订单是否可以退款 + if (shopOrder == null) { + return fail("订单不存在"); + } ShopOrder shopOrderNow = shopOrderService.getById(shopOrder.getOrderId()); // 申请退款 if (shopOrder.getOrderStatus().equals(4)) { @@ -201,13 +205,9 @@ public class ShopOrderController extends BaseController { if(shopOrder.getOrderStatus().equals(6)){ // 当订单状态更改为6(已退款)时,执行退款操作 try { - // 1. 验证订单是否可以退款 - if (shopOrderNow == null) { - return fail("订单不存在"); - } // 检查订单是否已支付 - if (shopOrderNow.getPayStatus() == null || !shopOrderNow.getPayStatus().equals(1)) { + if (!shopOrder.getPayStatus()) { return fail("订单未支付,无法退款"); } @@ -236,7 +236,14 @@ public class ShopOrderController extends BaseController { PaymentType paymentType = PaymentType.WECHAT_NATIVE; if (shopOrderNow.getPayType() != null) { // 根据订单的支付类型确定 - paymentType = PaymentType.fromCode(shopOrderNow.getPayType()); + // 支付方式:0余额支付,1微信支付,2支付宝支付,3银联支付,4现金支付,5POS机支付,6免费,7积分支付 + paymentType = PaymentType.getByCode(shopOrderNow.getPayType()); + + // 如果是微信支付,需要根据微信支付子类型确定具体的支付方式 + if (paymentType == PaymentType.WECHAT) { + // 目前统一使用WECHAT_NATIVE进行退款 + paymentType = PaymentType.WECHAT_NATIVE; + } } // 5. 调用统一支付服务的退款接口 @@ -246,10 +253,10 @@ public class ShopOrderController extends BaseController { PaymentResponse refundResponse = paymentService.refund( shopOrderNow.getOrderNo(), // 原订单号 refundNo, // 退款单号 + paymentType, // 支付方式 shopOrderNow.getTotalPrice(), // 订单总金额 refundAmount, // 退款金额 shopOrder.getRefundReason() != null ? shopOrder.getRefundReason() : "用户申请退款", // 退款原因 - paymentType, // 支付方式 shopOrderNow.getTenantId() // 租户ID ); diff --git a/src/main/java/com/gxwebsoft/shop/entity/ShopOrder.java b/src/main/java/com/gxwebsoft/shop/entity/ShopOrder.java index d9a34ba..1fb387c 100644 --- a/src/main/java/com/gxwebsoft/shop/entity/ShopOrder.java +++ b/src/main/java/com/gxwebsoft/shop/entity/ShopOrder.java @@ -204,6 +204,10 @@ public class ShopOrder implements Serializable { @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime payTime; + @Schema(description = "退款原因") + @NotBlank(message = "退款原因不能为空") + private String refundReason; + @Schema(description = "退款时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime refundTime; diff --git a/src/main/java/com/gxwebsoft/shop/task/RefundStatusQueryTask.java b/src/main/java/com/gxwebsoft/shop/task/RefundStatusQueryTask.java index 9d5af16..ecce124 100644 --- a/src/main/java/com/gxwebsoft/shop/task/RefundStatusQueryTask.java +++ b/src/main/java/com/gxwebsoft/shop/task/RefundStatusQueryTask.java @@ -48,7 +48,10 @@ public class RefundStatusQueryTask { int totalProcessedCount = 0; // 查询所有退款处理中的订单(状态为5) - List refundProcessingOrders = shopOrderService.getRefundProcessingOrders(); + List refundProcessingOrders = shopOrderService.lambdaQuery() + .eq(ShopOrder::getOrderStatus, 5) + .isNotNull(ShopOrder::getRefundOrder) + .list(); if (refundProcessingOrders.isEmpty()) { log.info("没有找到退款处理中的订单");