Эх сурвалжийг харах

mall + pay:调整异常的处理
1. 如果是业务异常,则统一转换成 ServiceException
2. 如果是系统异常,则使用 PayException 包装成无需 check 的异常

YunaiV 1 жил өмнө
parent
commit
efb221b1fe
13 өөрчлөгдсөн 133 нэмэгдсэн , 102 устгасан
  1. 5 0
      yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/util/ServiceExceptionUtil.java
  2. 4 13
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/exception/PayException.java
  3. 23 41
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java
  4. 39 4
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java
  5. 1 1
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayAppPayClient.java
  6. 2 2
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayBarPayClient.java
  7. 1 2
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClient.java
  8. 1 1
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayQrPayClient.java
  9. 1 1
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayWapPayClient.java
  10. 37 22
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java
  11. 4 1
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxBarPayClient.java
  12. 14 0
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxPubPayClient.java
  13. 1 14
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayFrameworkErrorCodeConstants.java

+ 5 - 0
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/util/ServiceExceptionUtil.java

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.common.exception.util;
 
 import cn.iocoder.yudao.framework.common.exception.ErrorCode;
 import cn.iocoder.yudao.framework.common.exception.ServiceException;
+import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
 import com.google.common.annotations.VisibleForTesting;
 import lombok.extern.slf4j.Slf4j;
 
@@ -80,6 +81,10 @@ public class ServiceExceptionUtil {
         return new ServiceException(code, message);
     }
 
+    public static ServiceException invalidParamException(String messagePattern, Object... params) {
+        return exception0(GlobalErrorCodeConstants.BAD_REQUEST.getCode(), messagePattern, params);
+    }
+
     // ========== 格式化方法 ==========
 
     /**

+ 4 - 13
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/exception/PayException.java

@@ -1,26 +1,17 @@
 package cn.iocoder.yudao.framework.pay.core.client.exception;
 
-import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
-import lombok.NoArgsConstructor;
 
 /**
- * 业务逻辑异常 Exception
+ * 支付系统异常 Exception
  */
 @Data
 @EqualsAndHashCode(callSuper = true)
-@NoArgsConstructor
-@AllArgsConstructor
 public class PayException extends RuntimeException {
 
-    /**
-     * 第三方平台的错误码
-     */
-    private String code;
-    /**
-     * 第三方平台的错误提示
-     */
-    private String message;
+    public PayException(Throwable cause) {
+        super(cause);
+    }
 
 }

+ 23 - 41
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java

@@ -1,24 +1,19 @@
 package cn.iocoder.yudao.framework.pay.core.client.impl;
 
-import cn.hutool.core.date.LocalDateTimeUtil;
+import cn.iocoder.yudao.framework.common.exception.ServiceException;
 import cn.iocoder.yudao.framework.pay.core.client.PayClient;
 import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO;
 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedRespDTO;
-import com.alipay.api.AlipayResponse;
+import cn.iocoder.yudao.framework.pay.core.client.exception.PayException;
 import lombok.extern.slf4j.Slf4j;
 
 import javax.validation.Validation;
-import java.time.LocalDateTime;
 
-import static cn.hutool.core.date.DatePattern.NORM_DATETIME_FORMATTER;
-import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0;
 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
-import static cn.iocoder.yudao.framework.pay.core.enums.PayFrameworkErrorCodeConstants.PAY_EXCEPTION;
 
-// TODO 芋艿:优化下,替换异常;
 /**
  * 支付客户端的抽象类,提供模板方法,减少子类的冗余代码
  *
@@ -78,16 +73,19 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
     @Override
     public final PayOrderUnifiedRespDTO unifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
         Validation.buildDefaultValidatorFactory().getValidator().validate(reqDTO);
-        // 执行短信发送
-        PayOrderUnifiedRespDTO result;
+        // 执行统一下单
+        PayOrderUnifiedRespDTO resp;
         try {
-            result = doUnifiedOrder(reqDTO);
+            resp = doUnifiedOrder(reqDTO);
+        } catch (ServiceException ex) {
+            // 业务异常,都是实现类已经翻译,所以直接抛出即可
+            throw ex;
         } catch (Throwable ex) {
-            // 打印异常日志
-            log.error("[unifiedOrder][request({}) 发起支付失败]", toJsonString(reqDTO), ex);
+            // 系统异常,则包装成 PayException 异常抛出
+            log.error("[unifiedRefund][request({}) 发起支付异常]", toJsonString(reqDTO), ex);
             throw buildException(ex);
         }
-        return result;
+        return resp;
     }
 
     protected abstract PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO)
@@ -95,12 +93,17 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
 
     @Override
     public PayRefundUnifiedRespDTO unifiedRefund(PayRefundUnifiedReqDTO reqDTO) {
+        Validation.buildDefaultValidatorFactory().getValidator().validate(reqDTO);
+        // 执行统一退款
         PayRefundUnifiedRespDTO resp;
         try {
             resp = doUnifiedRefund(reqDTO);
-        }  catch (Throwable ex) {
-            // 记录异常日志
-            log.error("[unifiedRefund][request({}) 发起退款失败]", toJsonString(reqDTO), ex);
+        } catch (ServiceException ex) {
+            // 业务异常,都是实现类已经翻译,所以直接抛出即可
+            throw ex;
+        } catch (Throwable ex) {
+            // 系统异常,则包装成 PayException 异常抛出
+            log.error("[unifiedRefund][request({}) 发起退款异常]", toJsonString(reqDTO), ex);
             throw buildException(ex);
         }
         return resp;
@@ -110,32 +113,11 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
 
     // ========== 各种工具方法 ==========
 
-    private RuntimeException buildException(Throwable ex) {
-        if (ex instanceof RuntimeException) {
-            return (RuntimeException) ex;
-        }
-        throw new RuntimeException(ex);
-    }
-
-    protected void validateSuccess(AlipayResponse response) {
-        if (response.isSuccess()) {
-            return;
+    private PayException buildException(Throwable ex) {
+        if (ex instanceof PayException) {
+            return (PayException) ex;
         }
-        throw exception0(PAY_EXCEPTION.getCode(), response.getSubMsg());
-    }
-
-    protected String formatAmount(Integer amount) {
-        return String.valueOf(amount / 100.0);
-    }
-
-    protected String formatTime(LocalDateTime time) {
-        // "yyyy-MM-dd HH:mm:ss"
-        return LocalDateTimeUtil.format(time, NORM_DATETIME_FORMATTER);
-    }
-
-    protected LocalDateTime parseTime(String str) {
-        // "yyyy-MM-dd HH:mm:ss"
-        return LocalDateTimeUtil.parse(str, NORM_DATETIME_FORMATTER);
+        throw new PayException(ex);
     }
 
 }

+ 39 - 4
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java

@@ -1,7 +1,9 @@
 package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
 
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.date.LocalDateTimeUtil;
 import cn.hutool.http.HttpUtil;
+import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
 import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayNotifyReqDTO;
 import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayOrderNotifyRespDTO;
 import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayRefundNotifyRespDTO;
@@ -9,9 +11,7 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReq
 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedRespDTO;
 import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
 import cn.iocoder.yudao.framework.pay.core.enums.PayNotifyRefundStatusEnum;
-import com.alipay.api.AlipayApiException;
-import com.alipay.api.AlipayConfig;
-import com.alipay.api.DefaultAlipayClient;
+import com.alipay.api.*;
 import com.alipay.api.domain.AlipayTradeRefundModel;
 import com.alipay.api.internal.util.AlipaySignature;
 import com.alipay.api.request.AlipayTradeRefundRequest;
@@ -20,9 +20,13 @@ import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 
 import java.nio.charset.StandardCharsets;
+import java.time.LocalDateTime;
 import java.util.Map;
 
+import static cn.hutool.core.date.DatePattern.NORM_DATETIME_FORMATTER;
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0;
 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
+import static cn.iocoder.yudao.framework.pay.core.enums.PayFrameworkErrorCodeConstants.ORDER_UNIFIED_ERROR;
 
 /**
  * 支付宝抽象类,实现支付宝统一的接口、以及部分实现(退款)
@@ -58,7 +62,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
         model.setOutTradeNo(reqDTO.getPayTradeNo());
 
         model.setOutRequestNo(reqDTO.getMerchantRefundId());
-        model.setRefundAmount(formatAmount(reqDTO.getAmount()).toString());
+        model.setRefundAmount(formatAmount(reqDTO.getAmount()));
         model.setRefundReason(reqDTO.getReason());
 
         AlipayTradeRefundRequest refundRequest = new AlipayTradeRefundRequest();
@@ -114,4 +118,35 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
                 .build();
     }
 
+    // ========== 各种工具方法 ==========
+
+    protected String formatAmount(Integer amount) {
+        return String.valueOf(amount / 100.0);
+    }
+
+    protected String formatTime(LocalDateTime time) {
+        return LocalDateTimeUtil.format(time, NORM_DATETIME_FORMATTER);
+    }
+
+    protected LocalDateTime parseTime(String str) {
+        return LocalDateTimeUtil.parse(str, NORM_DATETIME_FORMATTER);
+    }
+
+    /**
+     * 校验支付宝统一下单的响应
+     *
+     * 如果校验不通过,则抛出 {@link cn.iocoder.yudao.framework.common.exception.ServiceException} 异常
+     *
+     * @param request 请求
+     * @param response 响应
+     */
+    protected void validateUnifiedOrderResponse(Object request, AlipayResponse response) {
+        if (response.isSuccess()) {
+            return;
+        }
+        log.error("[validateUnifiedOrderResponse][发起支付失败,request({}),response({})]",
+                JsonUtils.toJsonString(request), JsonUtils.toJsonString(response));
+        throw exception0(ORDER_UNIFIED_ERROR.getCode(), response.getSubMsg());
+    }
+
 }

+ 1 - 1
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayAppPayClient.java

@@ -49,7 +49,7 @@ public class AlipayAppPayClient extends AbstractAlipayPayClient {
         // 2.1 执行请求
         AlipayTradeAppPayResponse response = client.execute(request);
         // 2.2 处理结果
-        validateSuccess(response);
+        validateUnifiedOrderResponse(request, response);
         return new PayOrderUnifiedRespDTO()
                 .setDisplayMode(displayMode).setDisplayContent("");
     }

+ 2 - 2
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayBarPayClient.java

@@ -13,7 +13,6 @@ import com.alipay.api.response.AlipayTradePayResponse;
 import lombok.extern.slf4j.Slf4j;
 
 import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
-import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0;
 
 /**
@@ -59,8 +58,9 @@ public class AlipayBarPayClient extends AbstractAlipayPayClient {
         // 2.1 执行请求
         AlipayTradePayResponse response = client.execute(request);
         // 2.2 处理结果
-        validateSuccess(response);
+        validateUnifiedOrderResponse(request, response);
         return new PayOrderUnifiedRespDTO()
                 .setDisplayMode(displayMode).setDisplayContent("");
     }
+
 }

+ 1 - 2
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClient.java

@@ -59,9 +59,8 @@ public class AlipayPcPayClient extends AbstractAlipayPayClient {
         } else {
             response = client.pageExecute(request, Method.GET.name());
         }
-
         // 2.2 处理结果
-        validateSuccess(response);
+        validateUnifiedOrderResponse(request, response);
         return new PayOrderUnifiedRespDTO().setDisplayMode(displayMode)
                 .setDisplayContent(response.getBody());
     }

+ 1 - 1
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayQrPayClient.java

@@ -47,7 +47,7 @@ public class AlipayQrPayClient extends AbstractAlipayPayClient {
         // 2.1 执行请求
         AlipayTradePrecreateResponse response = client.execute(request);
         // 2.2 处理结果
-        validateSuccess(response);
+        validateUnifiedOrderResponse(request, response);
         return new PayOrderUnifiedRespDTO()
                 .setDisplayMode(displayMode).setDisplayContent(response.getQrCode());
     }

+ 1 - 1
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayWapPayClient.java

@@ -50,7 +50,7 @@ public class AlipayWapPayClient extends AbstractAlipayPayClient {
         AlipayTradeWapPayResponse response = client.pageExecute(request, Method.GET.name());
 
         // 2.2 处理结果
-        validateSuccess(response);
+        validateUnifiedOrderResponse(request, response);
         return new PayOrderUnifiedRespDTO()
                 .setDisplayMode(displayMode).setDisplayContent(response.getBody());
     }

+ 37 - 22
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java

@@ -4,16 +4,14 @@ import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.date.LocalDateTimeUtil;
 import cn.hutool.core.date.TemporalAccessorUtil;
 import cn.hutool.core.lang.Assert;
-import cn.hutool.core.map.MapUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.util.io.FileUtils;
-import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
 import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayNotifyReqDTO;
 import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayOrderNotifyRespDTO;
 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO;
-import cn.iocoder.yudao.framework.pay.core.client.exception.PayException;
 import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
+import cn.iocoder.yudao.framework.pay.core.enums.PayFrameworkErrorCodeConstants;
 import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
 import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result;
 import com.github.binarywang.wxpay.config.WxPayConfig;
@@ -26,6 +24,9 @@ import java.time.LocalDateTime;
 import java.time.ZoneId;
 import java.util.Objects;
 
+import static cn.hutool.core.date.DatePattern.PURE_DATETIME_PATTERN;
+import static cn.hutool.core.date.DatePattern.UTC_WITH_XXX_OFFSET_PATTERN;
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.*;
 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
 
 /**
@@ -67,8 +68,7 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
     }
 
     @Override
-    protected PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO)
-            throws Throwable {
+    protected PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws Exception {
         try {
             switch (config.getApiVersion()) {
                 case WxPayClientConfig.API_VERSION_V2:
@@ -79,8 +79,7 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
                     throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
             }
         } catch (WxPayException e) {
-            log.error("[doUnifiedOrder][request({}) 发起支付失败]", toJsonString(reqDTO), e);
-            throw buildPayException(e);
+            throw buildUnifiedOrderException(reqDTO, e);
         }
     }
 
@@ -118,7 +117,9 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
             }
         } catch (WxPayException e) {
             log.error("[parseNotify][rawNotify({}) 解析失败]", toJsonString(rawNotify), e);
-            throw buildPayException(e);
+//            throw buildPayException(e);
+            throw new RuntimeException(e);
+            // TODO 芋艿:缺一个异常翻译
         }
     }
 
@@ -151,33 +152,47 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
 
     // ========== 各种工具方法 ==========
 
-    static String getOpenid(PayOrderUnifiedReqDTO reqDTO) {
-        String openid = MapUtil.getStr(reqDTO.getChannelExtras(), "openid");
-        if (StrUtil.isEmpty(openid)) {
-            throw new IllegalArgumentException("支付请求的 openid 不能为空!");
+    /**
+     * 构建统一下单的异常
+     *
+     * 目的:将参数不正确等异常,转换成 {@link cn.iocoder.yudao.framework.common.exception.ServiceException} 业务异常
+     *
+     * @param reqDTO 请求
+     * @param e 微信的支付异常
+     * @return 转换后的异常
+     *
+     */
+    static Exception buildUnifiedOrderException(PayOrderUnifiedReqDTO reqDTO, WxPayException e) {
+        // 情况一:业务结果为 FAIL
+        if (Objects.equals(e.getResultCode(), "FAIL")) {
+            log.error("[buildUnifiedOrderException][request({}) 发起支付失败]", toJsonString(reqDTO), e);
+            if (Objects.equals(e.getErrCode(), "PARAM_ERROR")) {
+                throw invalidParamException(e.getErrCodeDes());
+            }
+            throw exception(PayFrameworkErrorCodeConstants.ORDER_UNIFIED_ERROR, e.getReturnMsg());
         }
-        return openid;
-    }
-
-    static PayException buildPayException(WxPayException e) {
-        return new PayException(ObjectUtils.defaultIfNull(e.getErrCode(), e.getReturnCode()),
-                ObjectUtils.defaultIfNull(e.getErrCodeDes(), e.getCustomErrorMsg()));
+        // 情况二:状态码结果为 FAIL
+        if (Objects.equals(e.getReturnCode(), "FAIL")) {
+            throw exception(PayFrameworkErrorCodeConstants.ORDER_UNIFIED_ERROR, e.getReturnMsg());
+        }
+        // 情况三:系统异常,这里暂时不打,交给上层的 AbstractPayClient 统一打
+        return e;
     }
 
     static String formatDateV2(LocalDateTime time) {
-        return TemporalAccessorUtil.format(time.atZone(ZoneId.systemDefault()), "yyyyMMddHHmmss");
+        return TemporalAccessorUtil.format(time.atZone(ZoneId.systemDefault()), PURE_DATETIME_PATTERN);
     }
 
     static LocalDateTime parseDateV2(String time) {
-        return LocalDateTimeUtil.parse(time, "yyyyMMddHHmmss");
+        return LocalDateTimeUtil.parse(time, PURE_DATETIME_PATTERN);
     }
 
     static String formatDateV3(LocalDateTime time) {
-        return TemporalAccessorUtil.format(time.atZone(ZoneId.systemDefault()), "yyyy-MM-dd'T'HH:mm:ssXXX");
+        return TemporalAccessorUtil.format(time.atZone(ZoneId.systemDefault()), UTC_WITH_XXX_OFFSET_PATTERN);
     }
 
     static LocalDateTime parseDateV3(String time) {
-        return LocalDateTimeUtil.parse(time, "yyyy-MM-dd'T'HH:mm:ssXXX");
+        return LocalDateTimeUtil.parse(time, UTC_WITH_XXX_OFFSET_PATTERN);
     }
 
 }

+ 4 - 1
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxBarPayClient.java

@@ -14,6 +14,8 @@ import com.github.binarywang.wxpay.bean.result.WxPayMicropayResult;
 import com.github.binarywang.wxpay.constant.WxPayConstants;
 import com.github.binarywang.wxpay.exception.WxPayException;
 
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.invalidParamException;
+
 public class WxBarPayClient extends AbstractWxPayClient {
 
     public WxBarPayClient(Long channelId, WxPayClientConfig config) {
@@ -57,10 +59,11 @@ public class WxBarPayClient extends AbstractWxPayClient {
     }
 
     // ========== 各种工具方法 ==========
+
     static String getAuthCode(PayOrderUnifiedReqDTO reqDTO) {
         String authCode = MapUtil.getStr(reqDTO.getChannelExtras(), "authCode");
         if (StrUtil.isEmpty(authCode)) {
-            throw new IllegalArgumentException("支付请求的 authCode 不能为空!");
+            throw invalidParamException("支付请求的 authCode 不能为空!");
         }
         return authCode;
     }

+ 14 - 0
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxPubPayClient.java

@@ -1,5 +1,7 @@
 package cn.iocoder.yudao.framework.pay.core.client.impl.weixin;
 
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO;
@@ -16,6 +18,8 @@ import com.github.binarywang.wxpay.constant.WxPayConstants;
 import com.github.binarywang.wxpay.exception.WxPayException;
 import lombok.extern.slf4j.Slf4j;
 
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.invalidParamException;
+
 /**
  * 微信支付(公众号)的 PayClient 实现类
  *
@@ -83,4 +87,14 @@ public class WxPubPayClient extends AbstractWxPayClient {
         throw new UnsupportedOperationException();
     }
 
+    // ========== 各种工具方法 ==========
+
+    static String getOpenid(PayOrderUnifiedReqDTO reqDTO) {
+        String openid = MapUtil.getStr(reqDTO.getChannelExtras(), "openid");
+        if (StrUtil.isEmpty(openid)) {
+            throw invalidParamException("支付请求的 openid 不能为空!");
+        }
+        return openid;
+    }
+
 }

+ 1 - 14
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayFrameworkErrorCodeConstants.java

@@ -11,19 +11,6 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
  */
 public interface PayFrameworkErrorCodeConstants {
 
-    ErrorCode PAY_UNKNOWN = new ErrorCode(2002000000, "未知错误,需要解析");
-
-    // ========== 配置相关相关 2002000100 ==========
-    // todo 芋艿:如下的错误码,怎么处理掉
-    ErrorCode PAY_CONFIG_APP_ID_ERROR = new ErrorCode(2002000100, "支付渠道 AppId 不正确");
-    ErrorCode PAY_CONFIG_SIGN_ERROR = new ErrorCode(2002000100, "签名错误"); // 例如说,微信支付,配置错了 mchId 或者 mchKey
-
-
-    // ========== 其它相关 2002000900 开头 ==========
-    // todo 芋艿:如下的错误码,怎么处理掉
-    ErrorCode PAY_OPENID_ERROR = new ErrorCode(2002000900, "无效的 openid"); // 例如说,微信 openid 未授权过
-    ErrorCode PAY_PARAM_MISSING = new ErrorCode(2002000901, "请求参数缺失"); // 例如说,支付少传了金额
-
-    ErrorCode PAY_EXCEPTION = new ErrorCode(2002000999, "调用异常");
+    ErrorCode ORDER_UNIFIED_ERROR = new ErrorCode(2002000000, "发起支付失败,原因:{}");
 
 }