mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-26 17:21:53 +08:00
code review 退款逻辑
This commit is contained in:
parent
d556eae556
commit
67aaf28832
@ -12,8 +12,6 @@ public interface PayRefundCoreConvert {
|
|||||||
|
|
||||||
PayRefundCoreConvert INSTANCE = Mappers.getMapper(PayRefundCoreConvert.class);
|
PayRefundCoreConvert INSTANCE = Mappers.getMapper(PayRefundCoreConvert.class);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//TODO 太多需要处理了, 暂时不用
|
//TODO 太多需要处理了, 暂时不用
|
||||||
@Mappings(value = {
|
@Mappings(value = {
|
||||||
@Mapping(source = "amount", target = "payAmount"),
|
@Mapping(source = "amount", target = "payAmount"),
|
||||||
@ -21,4 +19,5 @@ public interface PayRefundCoreConvert {
|
|||||||
@Mapping(target = "status",ignore = true)
|
@Mapping(target = "status",ignore = true)
|
||||||
})
|
})
|
||||||
PayRefundDO convert(PayOrderDO orderDO);
|
PayRefundDO convert(PayOrderDO orderDO);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@ package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order;
|
|||||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
|
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
|
||||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
|
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
|
||||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO;
|
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO;
|
||||||
|
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundStatusEnum;
|
||||||
|
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundTypeEnum;
|
||||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
|
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
@ -79,7 +81,6 @@ public class PayRefundDO extends BaseDO {
|
|||||||
*/
|
*/
|
||||||
private Long orderId;
|
private Long orderId;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 交易订单号,根据规则生成
|
* 交易订单号,根据规则生成
|
||||||
* 调用支付渠道时,使用该字段作为对接的订单号。
|
* 调用支付渠道时,使用该字段作为对接的订单号。
|
||||||
@ -110,7 +111,6 @@ public class PayRefundDO extends BaseDO {
|
|||||||
* 防止该笔交易重复退款。支付宝会保证同样的退款请求号多次请求只会退一次。
|
* 防止该笔交易重复退款。支付宝会保证同样的退款请求号多次请求只会退一次。
|
||||||
* 退款单请求号,根据规则生成
|
* 退款单请求号,根据规则生成
|
||||||
* 例如说,R202109181134287570000
|
* 例如说,R202109181134287570000
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
private String merchantRefundNo;
|
private String merchantRefundNo;
|
||||||
|
|
||||||
@ -129,19 +129,22 @@ public class PayRefundDO extends BaseDO {
|
|||||||
/**
|
/**
|
||||||
* 退款状态
|
* 退款状态
|
||||||
*
|
*
|
||||||
|
* 枚举 {@link PayRefundStatusEnum}
|
||||||
*/
|
*/
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 退款类型(部分退款,全部退款)
|
* 退款类型(部分退款,全部退款)
|
||||||
|
*
|
||||||
|
* 枚举 {@link PayRefundTypeEnum}
|
||||||
*/
|
*/
|
||||||
private Integer type;
|
private Integer type;
|
||||||
/**
|
/**
|
||||||
* 支付金额,单位分
|
* 支付金额,单位:分
|
||||||
*/
|
*/
|
||||||
private Long payAmount;
|
private Long payAmount;
|
||||||
/**
|
/**
|
||||||
* 退款金额,单位分
|
* 退款金额,单位:分
|
||||||
*/
|
*/
|
||||||
private Long refundAmount;
|
private Long refundAmount;
|
||||||
|
|
||||||
@ -150,7 +153,6 @@ public class PayRefundDO extends BaseDO {
|
|||||||
*/
|
*/
|
||||||
private String reason;
|
private String reason;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户 IP
|
* 用户 IP
|
||||||
*/
|
*/
|
||||||
|
@ -19,4 +19,5 @@ public interface PayRefundCoreMapper extends BaseMapperX<PayRefundDO> {
|
|||||||
default PayRefundDO selectByTradeNoAndMerchantRefundNo(String tradeNo, String merchantRefundNo){
|
default PayRefundDO selectByTradeNoAndMerchantRefundNo(String tradeNo, String merchantRefundNo){
|
||||||
return selectOne("trade_no", tradeNo, "merchant_refund_no", merchantRefundNo);
|
return selectOne("trade_no", tradeNo, "merchant_refund_no", merchantRefundNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import lombok.Getter;
|
|||||||
@Getter
|
@Getter
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public enum PayRefundStatusEnum {
|
public enum PayRefundStatusEnum {
|
||||||
|
|
||||||
CREATE(0, "退款订单生成"),
|
CREATE(0, "退款订单生成"),
|
||||||
SUCCESS(1, "退款成功"),
|
SUCCESS(1, "退款成功"),
|
||||||
FAILURE(2, "退款失败"),
|
FAILURE(2, "退款失败"),
|
||||||
|
@ -16,8 +16,9 @@ import lombok.experimental.Accessors;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class PayRefundReqDTO {
|
public class PayRefundReqDTO {
|
||||||
|
|
||||||
|
// TODO @jason:增加下 validation 注解哈
|
||||||
/**
|
/**
|
||||||
* 支付订单编号自增
|
* 支付订单编号
|
||||||
*/
|
*/
|
||||||
private Long payOrderId;
|
private Long payOrderId;
|
||||||
|
|
||||||
@ -31,10 +32,10 @@ public class PayRefundReqDTO {
|
|||||||
*/
|
*/
|
||||||
private String reason;
|
private String reason;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 商户退款订单号
|
* 商户退款订单号
|
||||||
*/
|
*/
|
||||||
|
// TODO @jason:merchantRefundNo=》merchantRefundId,保持和 PayOrder 的 merchantOrderId 一致哈
|
||||||
private String merchantRefundNo;
|
private String merchantRefundNo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21,10 +21,11 @@ public class PayRefundRespDTO {
|
|||||||
* 退款处理中和退款成功 返回 1
|
* 退款处理中和退款成功 返回 1
|
||||||
* 失败和其他情况 返回 2
|
* 失败和其他情况 返回 2
|
||||||
*/
|
*/
|
||||||
|
// TODO @jason:这个 result,可以使用 CommonResult 里呢
|
||||||
private Integer channelReturnResult;
|
private Integer channelReturnResult;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 渠道返回code
|
* 渠道返回 code
|
||||||
*/
|
*/
|
||||||
private String channelReturnCode;
|
private String channelReturnCode;
|
||||||
|
|
||||||
@ -34,7 +35,8 @@ public class PayRefundRespDTO {
|
|||||||
private String channelReturnMsg;
|
private String channelReturnMsg;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付退款单编号, 自增
|
* 支付退款单编号,自增
|
||||||
*/
|
*/
|
||||||
private Long refundId;
|
private Long refundId;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -11,20 +11,20 @@ import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayOrderExtensio
|
|||||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayRefundCoreMapper;
|
import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayRefundCoreMapper;
|
||||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.notify.PayNotifyTypeEnum;
|
import cn.iocoder.yudao.coreservice.modules.pay.enums.notify.PayNotifyTypeEnum;
|
||||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderNotifyStatusEnum;
|
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderNotifyStatusEnum;
|
||||||
import cn.iocoder.yudao.coreservice.modules.pay.service.notify.PayNotifyCoreService;
|
|
||||||
import cn.iocoder.yudao.coreservice.modules.pay.service.notify.dto.PayNotifyTaskCreateReqDTO;
|
|
||||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundReqDTO;
|
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundNotifyDTO;
|
|
||||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundTypeEnum;
|
|
||||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderStatusEnum;
|
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderStatusEnum;
|
||||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundStatusEnum;
|
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundStatusEnum;
|
||||||
|
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundTypeEnum;
|
||||||
import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayAppCoreService;
|
import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayAppCoreService;
|
||||||
import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayChannelCoreService;
|
import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayChannelCoreService;
|
||||||
|
import cn.iocoder.yudao.coreservice.modules.pay.service.notify.PayNotifyCoreService;
|
||||||
|
import cn.iocoder.yudao.coreservice.modules.pay.service.notify.dto.PayNotifyTaskCreateReqDTO;
|
||||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayRefundCoreService;
|
import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayRefundCoreService;
|
||||||
|
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundReqDTO;
|
||||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundRespDTO;
|
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundRespDTO;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.PayClient;
|
import cn.iocoder.yudao.framework.pay.core.client.PayClient;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
|
import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO;
|
import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO;
|
||||||
|
import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundNotifyDTO;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedReqDTO;
|
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.client.dto.PayRefundUnifiedRespDTO;
|
||||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelRefundRespEnum;
|
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelRefundRespEnum;
|
||||||
@ -34,7 +34,8 @@ import org.springframework.stereotype.Service;
|
|||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.*;
|
import java.util.Date;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*;
|
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*;
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
@ -90,17 +91,19 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
|
|||||||
|
|
||||||
PayOrderExtensionDO orderExtensionDO = payOrderExtensionCoreMapper.selectById(order.getSuccessExtensionId());
|
PayOrderExtensionDO orderExtensionDO = payOrderExtensionCoreMapper.selectById(order.getSuccessExtensionId());
|
||||||
PayRefundDO payRefundDO = payRefundCoreMapper.selectByTradeNoAndMerchantRefundNo(orderExtensionDO.getNo(), req.getMerchantRefundNo());
|
PayRefundDO payRefundDO = payRefundCoreMapper.selectByTradeNoAndMerchantRefundNo(orderExtensionDO.getNo(), req.getMerchantRefundNo());
|
||||||
//构造渠道的统一的退款请求参数
|
// 构造渠道的统一的退款请求参数
|
||||||
PayRefundUnifiedReqDTO unifiedReqDTO = new PayRefundUnifiedReqDTO();
|
PayRefundUnifiedReqDTO unifiedReqDTO = new PayRefundUnifiedReqDTO();
|
||||||
if(Objects.nonNull(payRefundDO)){
|
if(Objects.nonNull(payRefundDO)){
|
||||||
//退款订单已经提交过。
|
// 退款订单已经提交过。
|
||||||
//TODO 校验相同退款单的金额
|
//TODO 校验相同退款单的金额
|
||||||
if(Objects.equals(PayRefundStatusEnum.SUCCESS.getStatus(), payRefundDO.getStatus())
|
// TODO @jason:咱要不封装一个 ObjectUtils.equalsAny
|
||||||
|| Objects.equals(PayRefundStatusEnum.CLOSE.getStatus(), payRefundDO.getStatus())){
|
if (Objects.equals(PayRefundStatusEnum.SUCCESS.getStatus(), payRefundDO.getStatus())
|
||||||
|
|| Objects.equals(PayRefundStatusEnum.CLOSE.getStatus(), payRefundDO.getStatus())) {
|
||||||
//已成功退款
|
//已成功退款
|
||||||
throw exception(PAY_REFUND_SUCCEED);
|
throw exception(PAY_REFUND_SUCCEED);
|
||||||
}else{
|
} else{
|
||||||
//保证商户退款单不变,重复向渠道发起退款。渠道保持幂等
|
// TODO @jason:这里不用 else,简洁一些
|
||||||
|
// 保证商户退款单不变,重复向渠道发起退款。渠道保持幂等
|
||||||
unifiedReqDTO.setUserIp(req.getUserIp())
|
unifiedReqDTO.setUserIp(req.getUserIp())
|
||||||
.setAmount(payRefundDO.getRefundAmount())
|
.setAmount(payRefundDO.getRefundAmount())
|
||||||
.setChannelOrderNo(payRefundDO.getChannelOrderNo())
|
.setChannelOrderNo(payRefundDO.getChannelOrderNo())
|
||||||
@ -109,7 +112,8 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
|
|||||||
.setReason(payRefundDO.getReason());
|
.setReason(payRefundDO.getReason());
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
//新生成退款单。 退款单入库 退款单状态:生成
|
// 新生成退款单。 退款单入库 退款单状态:生成
|
||||||
|
// TODO @jason:封装一个小方法。插入退款单
|
||||||
payRefundDO = PayRefundDO.builder().channelOrderNo(order.getChannelOrderNo())
|
payRefundDO = PayRefundDO.builder().channelOrderNo(order.getChannelOrderNo())
|
||||||
.appId(order.getAppId())
|
.appId(order.getAppId())
|
||||||
.channelOrderNo(order.getChannelOrderNo())
|
.channelOrderNo(order.getChannelOrderNo())
|
||||||
@ -130,6 +134,7 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
|
|||||||
.type(refundType.getStatus())
|
.type(refundType.getStatus())
|
||||||
.build();
|
.build();
|
||||||
payRefundCoreMapper.insert(payRefundDO);
|
payRefundCoreMapper.insert(payRefundDO);
|
||||||
|
// TODO @jason:这块的逻辑,和已存在的这块,貌似是统一的?
|
||||||
unifiedReqDTO.setUserIp(req.getUserIp())
|
unifiedReqDTO.setUserIp(req.getUserIp())
|
||||||
.setAmount(payRefundDO.getRefundAmount())
|
.setAmount(payRefundDO.getRefundAmount())
|
||||||
.setChannelOrderNo(payRefundDO.getChannelOrderNo())
|
.setChannelOrderNo(payRefundDO.getChannelOrderNo())
|
||||||
@ -137,19 +142,20 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
|
|||||||
.setRefundReqNo(payRefundDO.getMerchantRefundNo())
|
.setRefundReqNo(payRefundDO.getMerchantRefundNo())
|
||||||
.setReason(req.getReason());
|
.setReason(req.getReason());
|
||||||
}
|
}
|
||||||
//向渠道发起退款申请
|
// 向渠道发起退款申请
|
||||||
PayRefundUnifiedRespDTO refundUnifiedRespDTO = client.unifiedRefund(unifiedReqDTO);
|
PayRefundUnifiedRespDTO refundUnifiedRespDTO = client.unifiedRefund(unifiedReqDTO);
|
||||||
//构造退款申请返回对象
|
// 构造退款申请返回对象
|
||||||
PayRefundRespDTO respDTO = new PayRefundRespDTO();
|
PayRefundRespDTO respDTO = new PayRefundRespDTO();
|
||||||
if(refundUnifiedRespDTO.getChannelResp() == PayChannelRefundRespEnum.SUCCESS
|
if (refundUnifiedRespDTO.getChannelResp() == PayChannelRefundRespEnum.SUCCESS
|
||||||
||refundUnifiedRespDTO.getChannelResp() == PayChannelRefundRespEnum.PROCESSING ){
|
||refundUnifiedRespDTO.getChannelResp() == PayChannelRefundRespEnum.PROCESSING) {
|
||||||
//成功处理, 在退款通知中处理, 这里不处理
|
// 成功处理,在退款通知中处理, 这里不处理
|
||||||
respDTO.setChannelReturnResult(PayChannelRefundRespEnum.SUCCESS.getStatus());
|
respDTO.setChannelReturnResult(PayChannelRefundRespEnum.SUCCESS.getStatus());
|
||||||
respDTO.setRefundId(payRefundDO.getId());
|
respDTO.setRefundId(payRefundDO.getId());
|
||||||
}else {
|
}else {
|
||||||
//失败返回错误给前端,可以重新发起退款,保证退款请求号(这里是商户退款单号), 避免重复退款。
|
// 失败返回错误给前端,可以重新发起退款,保证退款请求号(这里是商户退款单号), 避免重复退款。
|
||||||
|
// TODO @jason:失败的话,是不是可以跑出 ServiceException 业务异常。这样就是成功返回 refundId,失败业务异常
|
||||||
respDTO.setChannelReturnResult(PayChannelRefundRespEnum.FAILURE.getStatus());
|
respDTO.setChannelReturnResult(PayChannelRefundRespEnum.FAILURE.getStatus());
|
||||||
//更新退款单状态
|
// 更新退款单状态
|
||||||
PayRefundDO updatePayRefund = new PayRefundDO();
|
PayRefundDO updatePayRefund = new PayRefundDO();
|
||||||
updatePayRefund.setId(payRefundDO.getId())
|
updatePayRefund.setId(payRefundDO.getId())
|
||||||
.setChannelErrorMsg(refundUnifiedRespDTO.getChannelMsg())
|
.setChannelErrorMsg(refundUnifiedRespDTO.getChannelMsg())
|
||||||
@ -181,35 +187,37 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
|
|||||||
payRefundSuccess(refundNotify);
|
payRefundSuccess(refundNotify);
|
||||||
} else {
|
} else {
|
||||||
//TODO 支付异常, 支付宝似乎没有支付异常的通知。
|
//TODO 支付异常, 支付宝似乎没有支付异常的通知。
|
||||||
|
// TODO @jason:那这里可以考虑打个 error logger
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void payRefundSuccess(PayRefundNotifyDTO refundNotify) {
|
private void payRefundSuccess(PayRefundNotifyDTO refundNotify) {
|
||||||
|
// 校验退款单存在
|
||||||
PayRefundDO refundDO = payRefundCoreMapper.selectByTradeNoAndMerchantRefundNo(refundNotify.getTradeNo(), refundNotify.getReqNo());
|
PayRefundDO refundDO = payRefundCoreMapper.selectByTradeNoAndMerchantRefundNo(refundNotify.getTradeNo(), refundNotify.getReqNo());
|
||||||
if (refundDO == null) {
|
if (refundDO == null) {
|
||||||
log.error("不存在 seqNo 为{} 的支付退款单",refundNotify.getReqNo());
|
log.error("[payRefundSuccess][不存在 seqNo 为{} 的支付退款单]", refundNotify.getReqNo());
|
||||||
throw exception(PAY_REFUND_NOT_FOUND);
|
throw exception(PAY_REFUND_NOT_FOUND);
|
||||||
}
|
}
|
||||||
Long refundAmount = refundDO.getRefundAmount();
|
|
||||||
|
// 计算订单的状态。如果全部退款,则订单处于关闭。TODO @jason:建议这里按照金额来判断,因为可能退款多次
|
||||||
Integer type = refundDO.getType();
|
Integer type = refundDO.getType();
|
||||||
PayOrderStatusEnum orderStatus = PayOrderStatusEnum.SUCCESS;
|
PayOrderStatusEnum orderStatus = PayOrderStatusEnum.SUCCESS;
|
||||||
if(PayRefundTypeEnum.ALL.getStatus().equals(type)){
|
if (PayRefundTypeEnum.ALL.getStatus().equals(type)){
|
||||||
orderStatus = PayOrderStatusEnum.CLOSED;
|
orderStatus = PayOrderStatusEnum.CLOSED;
|
||||||
}
|
}
|
||||||
// 更新支付订单
|
|
||||||
PayOrderDO payOrderDO = payOrderCoreMapper.selectById(refundDO.getOrderId());
|
|
||||||
// 需更新已退金额
|
// 需更新已退金额
|
||||||
|
PayOrderDO payOrderDO = payOrderCoreMapper.selectById(refundDO.getOrderId());
|
||||||
Long refundedAmount = payOrderDO.getRefundAmount();
|
Long refundedAmount = payOrderDO.getRefundAmount();
|
||||||
|
// 更新支付订单
|
||||||
PayOrderDO updateOrderDO = new PayOrderDO();
|
PayOrderDO updateOrderDO = new PayOrderDO();
|
||||||
updateOrderDO.setId(refundDO.getOrderId())
|
updateOrderDO.setId(refundDO.getOrderId())
|
||||||
.setRefundAmount(refundedAmount + refundAmount)
|
.setRefundAmount(refundedAmount + refundDO.getRefundAmount())
|
||||||
.setStatus(orderStatus.getStatus())
|
.setStatus(orderStatus.getStatus())
|
||||||
.setRefundTimes(payOrderDO.getRefundTimes()+1)
|
.setRefundTimes(payOrderDO.getRefundTimes() + 1)
|
||||||
.setRefundStatus(type);
|
.setRefundStatus(type);
|
||||||
|
|
||||||
payOrderCoreMapper.updateById(updateOrderDO);
|
payOrderCoreMapper.updateById(updateOrderDO);
|
||||||
|
|
||||||
// 跟新退款订单
|
// 更新退款订单
|
||||||
PayRefundDO updateRefundDO = new PayRefundDO();
|
PayRefundDO updateRefundDO = new PayRefundDO();
|
||||||
updateRefundDO.setId(refundDO.getId())
|
updateRefundDO.setId(refundDO.getId())
|
||||||
.setSuccessTime(refundNotify.getRefundSuccessTime())
|
.setSuccessTime(refundNotify.getRefundSuccessTime())
|
||||||
@ -219,7 +227,7 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
|
|||||||
.setStatus(PayRefundStatusEnum.SUCCESS.getStatus());
|
.setStatus(PayRefundStatusEnum.SUCCESS.getStatus());
|
||||||
payRefundCoreMapper.updateById(updateRefundDO);
|
payRefundCoreMapper.updateById(updateRefundDO);
|
||||||
|
|
||||||
//插入退款通知记录
|
// 插入退款通知记录
|
||||||
// TODO 通知商户成功或者失败. 现在通知似乎没有实现, 只是回调
|
// TODO 通知商户成功或者失败. 现在通知似乎没有实现, 只是回调
|
||||||
payNotifyCoreService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder()
|
payNotifyCoreService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder()
|
||||||
.type(PayNotifyTypeEnum.REFUND.getType()).dataId(refundDO.getId()).build());
|
.type(PayNotifyTypeEnum.REFUND.getType()).dataId(refundDO.getId()).build());
|
||||||
@ -235,12 +243,12 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
|
|||||||
if (!PayOrderStatusEnum.SUCCESS.getStatus().equals(order.getStatus())) {
|
if (!PayOrderStatusEnum.SUCCESS.getStatus().equals(order.getStatus())) {
|
||||||
throw exception(PAY_ORDER_STATUS_IS_NOT_SUCCESS);
|
throw exception(PAY_ORDER_STATUS_IS_NOT_SUCCESS);
|
||||||
}
|
}
|
||||||
//是否已经全额退款
|
// 是否已经全额退款
|
||||||
if (PayRefundTypeEnum.ALL.getStatus().equals(order.getRefundStatus())) {
|
if (PayRefundTypeEnum.ALL.getStatus().equals(order.getRefundStatus())) {
|
||||||
throw exception(PAY_REFUND_ALL_REFUNDED);
|
throw exception(PAY_REFUND_ALL_REFUNDED);
|
||||||
}
|
}
|
||||||
// 校验金额 退款金额不能大于 原定的金额
|
// 校验金额 退款金额不能大于 原定的金额
|
||||||
if(req.getAmount() + order.getRefundAmount() > order.getAmount()){
|
if (req.getAmount() + order.getRefundAmount() > order.getAmount()){
|
||||||
throw exception(PAY_REFUND_AMOUNT_EXCEED);
|
throw exception(PAY_REFUND_AMOUNT_EXCEED);
|
||||||
}
|
}
|
||||||
// 校验渠道订单号
|
// 校验渠道订单号
|
||||||
|
@ -28,6 +28,7 @@ public class PayRefundUnifiedReqDTO {
|
|||||||
*/
|
*/
|
||||||
private String userIp;
|
private String userIp;
|
||||||
|
|
||||||
|
// TODO @jason:这个是否为非必传字段呀,只需要传递 payTradeNo 字段即可。尽可能精简
|
||||||
/**
|
/**
|
||||||
* https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 transaction_id
|
* https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 transaction_id
|
||||||
* https://opendocs.alipay.com/apis alipay.trade.refund 中的 trade_no
|
* https://opendocs.alipay.com/apis alipay.trade.refund 中的 trade_no
|
||||||
@ -35,7 +36,6 @@ public class PayRefundUnifiedReqDTO {
|
|||||||
*/
|
*/
|
||||||
private String channelOrderNo;
|
private String channelOrderNo;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 out_trade_no
|
* https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 out_trade_no
|
||||||
* https://opendocs.alipay.com/apis alipay.trade.refund 中的 out_trade_no
|
* https://opendocs.alipay.com/apis alipay.trade.refund 中的 out_trade_no
|
||||||
@ -43,24 +43,22 @@ public class PayRefundUnifiedReqDTO {
|
|||||||
*/
|
*/
|
||||||
private String payTradeNo;
|
private String payTradeNo;
|
||||||
|
|
||||||
|
// TODO @jason:这个字段,要不就使用 merchantRefundId,更直接
|
||||||
/**
|
/**
|
||||||
* https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 out_refund_no
|
* https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 out_refund_no
|
||||||
* https://opendocs.alipay.com/apis alipay.trade.refund 中的 out_request_no
|
* https://opendocs.alipay.com/apis alipay.trade.refund 中的 out_trade_no
|
||||||
* 退款请求单号 同一退款请求单号多次请求只退一笔。
|
* 退款请求单号 同一退款请求单号多次请求只退一笔。
|
||||||
* 使用 商户的退款单号。{PayRefundDO 字段 merchantRefundNo}
|
* 使用 商户的退款单号。{PayRefundDO 字段 merchantRefundNo}
|
||||||
*/
|
*/
|
||||||
@NotEmpty(message = "退款请求单号")
|
@NotEmpty(message = "退款请求单号")
|
||||||
private String refundReqNo;
|
private String refundReqNo;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 退款原因
|
* 退款原因
|
||||||
*/
|
*/
|
||||||
@NotEmpty(message = "退款原因不能为空")
|
@NotEmpty(message = "退款原因不能为空")
|
||||||
private String reason;
|
private String reason;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 退款金额,单位:分
|
* 退款金额,单位:分
|
||||||
*/
|
*/
|
||||||
@ -68,12 +66,10 @@ public class PayRefundUnifiedReqDTO {
|
|||||||
@DecimalMin(value = "0", inclusive = false, message = "支付金额必须大于零")
|
@DecimalMin(value = "0", inclusive = false, message = "支付金额必须大于零")
|
||||||
private Long amount;
|
private Long amount;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 退款结果 notify 回调地址, 支付宝退款不需要回调地址, 微信需要
|
* 退款结果 notify 回调地址, 支付宝退款不需要回调地址, 微信需要
|
||||||
*/
|
*/
|
||||||
@URL(message = "支付结果的 notify 回调地址必须是 URL 格式")
|
@URL(message = "支付结果的 notify 回调地址必须是 URL 格式")
|
||||||
private String notifyUrl;
|
private String notifyUrl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,14 @@ import lombok.experimental.Accessors;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@Data
|
@Data
|
||||||
public class PayRefundUnifiedRespDTO {
|
public class PayRefundUnifiedRespDTO {
|
||||||
|
|
||||||
|
// TODO @jason:可以合并下。退款处理中、成功,都是成功;其它就业务失败。这样,可以复用 PayCommonResult;这个 RespDTO 可以返回渠道的退款编号
|
||||||
/**
|
/**
|
||||||
* 渠道的退款结果
|
* 渠道的退款结果
|
||||||
*/
|
*/
|
||||||
private PayChannelRefundRespEnum channelResp;
|
private PayChannelRefundRespEnum channelResp;
|
||||||
|
|
||||||
|
// TODO @json:channelReturnCode 和 channelReturnMsg 放到 PayCommonResult 里噶
|
||||||
/**
|
/**
|
||||||
* 渠道返回码
|
* 渠道返回码
|
||||||
*/
|
*/
|
||||||
|
@ -11,6 +11,7 @@ import lombok.Getter;
|
|||||||
@Getter
|
@Getter
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public enum PayChannelRefundRespEnum {
|
public enum PayChannelRefundRespEnum {
|
||||||
|
|
||||||
SUCCESS(1, "退款成功"),
|
SUCCESS(1, "退款成功"),
|
||||||
FAILURE(2, "退款失败"),
|
FAILURE(2, "退款失败"),
|
||||||
PROCESSING(3,"退款处理中"),
|
PROCESSING(3,"退款处理中"),
|
||||||
@ -18,4 +19,5 @@ public enum PayChannelRefundRespEnum {
|
|||||||
|
|
||||||
private final Integer status;
|
private final Integer status;
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user