mirror of
https://gitee.com/hhyykk/ipms-sjy.git
synced 2025-07-15 03:25:06 +08:00
重构退款逻辑,去掉退款后处理
This commit is contained in:
@ -48,6 +48,7 @@ public class PayRefundUnifiedReqDTO {
|
||||
* https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 out_refund_no
|
||||
* https://opendocs.alipay.com/apis alipay.trade.refund 中的 out_request_no
|
||||
* 退款请求单号 同一退款请求单号多次请求只退一笔。
|
||||
* 使用 商户的退款单号。{PayRefundDO 字段 merchantRefundNo}
|
||||
*/
|
||||
@NotEmpty(message = "退款请求单号")
|
||||
private String refundReqNo;
|
||||
|
@ -1,15 +1,13 @@
|
||||
package cn.iocoder.yudao.framework.pay.core.client.dto;
|
||||
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelRespEnum;
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelRefundRespEnum;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
/**
|
||||
* 统一 退款 Response DTO
|
||||
* 统一退款 Response DTO
|
||||
*
|
||||
* @author jason
|
||||
*/
|
||||
@ -19,55 +17,20 @@ import javax.validation.constraints.NotEmpty;
|
||||
@AllArgsConstructor
|
||||
@Data
|
||||
public class PayRefundUnifiedRespDTO {
|
||||
|
||||
|
||||
/**
|
||||
* 渠道的退款结果
|
||||
*/
|
||||
private PayChannelRefundRespEnum channelResp;
|
||||
|
||||
/**
|
||||
* 渠道的通用返回结果
|
||||
* 渠道返回码
|
||||
*/
|
||||
private PayChannelRespEnum respEnum;
|
||||
|
||||
|
||||
private String channelCode;
|
||||
|
||||
/**
|
||||
* 渠道退款单号
|
||||
* 渠道返回信息
|
||||
*/
|
||||
private String channelRefundNo;
|
||||
|
||||
|
||||
/**
|
||||
* https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 out_trade_no
|
||||
* https://opendocs.alipay.com/apis alipay.trade.refund 中的 out_trade_no
|
||||
* 支付交易号 {PayOrderExtensionDO no字段} 和 渠道订单号 不能同时为空
|
||||
*/
|
||||
private String payTradeNo;
|
||||
|
||||
|
||||
/**
|
||||
* https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 out_refund_no
|
||||
* https://opendocs.alipay.com/apis alipay.trade.refund 中的 out_request_no
|
||||
* 退款请求单号 同一退款请求单号多次请求只退一笔。
|
||||
*/
|
||||
private String refundReqNo;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 调用异常错误信息
|
||||
*/
|
||||
private String exceptionMsg;
|
||||
|
||||
|
||||
/**
|
||||
* 渠道的错误码
|
||||
*/
|
||||
private String channelErrCode;
|
||||
|
||||
|
||||
/**
|
||||
* 渠道的错误描述
|
||||
*/
|
||||
private String channelErrMsg;
|
||||
private String channelMsg;
|
||||
|
||||
//TODO 退款资金渠 ???
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package cn.iocoder.yudao.framework.pay.core.client.impl;
|
||||
|
||||
import cn.hutool.extra.validation.ValidationUtil;
|
||||
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.AbstractPayCodeMapping;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.PayClient;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
|
||||
@ -8,11 +9,9 @@ import cn.iocoder.yudao.framework.pay.core.client.PayCommonResult;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedReqDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelRespEnum;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.net.SocketTimeoutException;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
|
||||
|
||||
/**
|
||||
@ -108,20 +107,10 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
|
||||
PayRefundUnifiedRespDTO resp;
|
||||
try {
|
||||
resp = doUnifiedRefund(reqDTO);
|
||||
} catch (SocketTimeoutException ex){
|
||||
// 网络 read time out 异常
|
||||
log.error("[unifiedRefund][request({}) 发起退款失败,网络读超时,退款状态未知]", toJsonString(reqDTO), ex);
|
||||
return PayRefundUnifiedRespDTO.builder()
|
||||
.exceptionMsg(ex.getMessage())
|
||||
.respEnum(PayChannelRespEnum.READ_TIME_OUT_EXCEPTION)
|
||||
.build();
|
||||
} catch (Throwable ex) {
|
||||
// 打印异常日志
|
||||
} catch (Throwable ex) {
|
||||
// 记录异常日志
|
||||
log.error("[unifiedRefund][request({}) 发起退款失败]", toJsonString(reqDTO), ex);
|
||||
return PayRefundUnifiedRespDTO.builder()
|
||||
.exceptionMsg(ex.getMessage())
|
||||
.respEnum(PayChannelRespEnum.CALL_EXCEPTION)
|
||||
.build();
|
||||
throw exception(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import cn.hutool.core.date.DateUtil;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.AbstractPayCodeMapping;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.*;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelRespEnum;
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelRefundRespEnum;
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.PayNotifyRefundStatusEnum;
|
||||
import com.alipay.api.AlipayApiException;
|
||||
import com.alipay.api.AlipayConfig;
|
||||
@ -17,7 +17,6 @@ import com.alipay.api.response.AlipayTradeRefundResponse;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
|
||||
@ -118,43 +117,21 @@ public abstract class AbstractAlipayClient extends AbstractPayClient<AlipayPayCl
|
||||
//退款成功,更新为PROCESSING_NOTIFY, 而不是 SYNC_SUCCESS 通过支付宝回调接口处理。退款导致触发的异步通知,
|
||||
//退款导致触发的异步通知是发送到支付接口中设置的notify_url
|
||||
//TODO 沙箱环境 返回 的tradeNo(渠道退款单号) 和 订单的tradNo 是一个值,是不是理解不对?
|
||||
respDTO.setRespEnum(PayChannelRespEnum.PROCESSING_NOTIFY);
|
||||
respDTO.setChannelResp(PayChannelRefundRespEnum.SUCCESS)
|
||||
.setChannelCode(response.getCode())
|
||||
.setChannelMsg(response.getMsg());
|
||||
}else{
|
||||
//特殊处理 sub_code ACQ.SYSTEM_ERROR(系统错误), 需要调用重试任务
|
||||
//沙箱环境返回的貌似是”aop.ACQ.SYSTEM_ERROR“, 用contain
|
||||
if (response.getSubCode().contains("ACQ.SYSTEM_ERROR")) {
|
||||
respDTO.setRespEnum(PayChannelRespEnum.RETRY_FAILURE)
|
||||
.setChannelErrMsg(response.getSubMsg())
|
||||
.setChannelErrCode(response.getSubCode());
|
||||
}else{
|
||||
//交易已关闭,需要查询确认退款是否已经完成
|
||||
if("ACQ.TRADE_HAS_CLOSE".equals(response.getSubCode())){
|
||||
respDTO.setRespEnum(PayChannelRespEnum.PROCESSING_QUERY)
|
||||
.setChannelErrMsg(response.getSubMsg())
|
||||
.setChannelErrCode(response.getSubCode());
|
||||
}else {
|
||||
//其他当做不可以重试的错误
|
||||
respDTO.setRespEnum(PayChannelRespEnum.CAN_NOT_RETRY_FAILURE)
|
||||
.setChannelErrCode(response.getSubCode())
|
||||
.setChannelErrMsg(response.getSubMsg());
|
||||
}
|
||||
}
|
||||
respDTO.setChannelResp(PayChannelRefundRespEnum.FAILURE)
|
||||
.setChannelCode(response.getSubCode())
|
||||
.setChannelMsg(response.getSubMsg());
|
||||
}
|
||||
return respDTO;
|
||||
} catch (AlipayApiException e) {
|
||||
//TODO 记录异常日志
|
||||
log.error("[doUnifiedRefund][request({}) 发起退款失败,网络读超时,退款状态未知]", toJsonString(reqDTO), e);
|
||||
Throwable cause = e.getCause();
|
||||
//网络 read time out 异常, 退款状态未知
|
||||
if (cause instanceof SocketTimeoutException) {
|
||||
respDTO.setExceptionMsg(e.getMessage())
|
||||
.setRespEnum(PayChannelRespEnum.READ_TIME_OUT_EXCEPTION);
|
||||
}else{
|
||||
respDTO.setExceptionMsg(e.getMessage())
|
||||
.setChannelErrCode(e.getErrCode())
|
||||
.setChannelErrMsg(e.getErrMsg())
|
||||
.setRespEnum(PayChannelRespEnum.CALL_EXCEPTION);
|
||||
}
|
||||
respDTO.setChannelResp(PayChannelRefundRespEnum.FAILURE)
|
||||
.setChannelCode(e.getErrCode())
|
||||
.setChannelMsg(e.getErrMsg());
|
||||
return respDTO;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,21 @@
|
||||
package cn.iocoder.yudao.framework.pay.core.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 渠道统一的退款返回结果
|
||||
*
|
||||
* @author jason
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum PayChannelRefundRespEnum {
|
||||
SUCCESS(1, "退款成功"),
|
||||
FAILURE(2, "退款失败"),
|
||||
PROCESSING(3,"退款处理中"),
|
||||
CLOSED(4, "退款关闭");
|
||||
|
||||
private final Integer status;
|
||||
private final String name;
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
package cn.iocoder.yudao.framework.pay.core.enums;
|
||||
|
||||
// TODO @芋艿:感觉情况有点多,得讨论下
|
||||
/**
|
||||
* 统一的渠道返回结果
|
||||
* @author jason
|
||||
*/
|
||||
public enum PayChannelRespEnum {
|
||||
|
||||
/**
|
||||
* 接口通讯正常返回, 并明确处理成功 ,不需要通过查询或者回调接口 进行下一步处理
|
||||
*/
|
||||
SYNC_SUCCESS,
|
||||
|
||||
/**
|
||||
* 接口通讯正常返回, 但返回错误,并且不能通过重试解决的错误,
|
||||
* 如提交失败, 业务错误(余额不足), 或者参数错误, 签名错误, 需要干预后才能处理
|
||||
*/
|
||||
CAN_NOT_RETRY_FAILURE,
|
||||
|
||||
|
||||
/**
|
||||
* 接口通讯正常返回,
|
||||
* 可以通过重试解决的错误. 如系统超时, 系统繁忙。状态未知 不能改变请求参数,如退款单请求号,重发请求
|
||||
*/
|
||||
RETRY_FAILURE,
|
||||
|
||||
|
||||
/**
|
||||
* 接口通讯正常返回,但是处理结果 需要渠道回调进行下一步处理
|
||||
*/
|
||||
PROCESSING_NOTIFY,
|
||||
|
||||
|
||||
/**
|
||||
* 接口通讯正常返回, 但是处理结果,需要调用查询接口 进行查询
|
||||
*/
|
||||
PROCESSING_QUERY,
|
||||
|
||||
|
||||
/**
|
||||
* 本系统调用渠道接口异常, 渠道接口请求未正常发送, 本系统不可预知的异常,较少发生, 可认为失败。 不用重试.
|
||||
*/
|
||||
CALL_EXCEPTION,
|
||||
|
||||
|
||||
/**
|
||||
* 本系统调用渠道接口成功, 但是未接受到请求结果,较少发生(需合理设置read time out ) 结果未知。 需要调用查询接口进行查询
|
||||
*/
|
||||
READ_TIME_OUT_EXCEPTION;
|
||||
}
|
Reference in New Issue
Block a user