mirror of
https://gitee.com/hhyykk/ipms-sjy.git
synced 2025-07-25 00:15:06 +08:00
code review 退款逻辑
This commit is contained in:
@ -1,25 +0,0 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.service.order;
|
||||
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO;
|
||||
|
||||
/**
|
||||
* 支付通用 Core Service
|
||||
*
|
||||
* @author jason
|
||||
*/
|
||||
public interface PayCommonCoreService {
|
||||
|
||||
/**
|
||||
* 验证是否是渠道通知
|
||||
* @param notifyData 通知数据
|
||||
*/
|
||||
void verifyNotifyData(Long channelId, PayNotifyDataDTO notifyData);
|
||||
|
||||
/**
|
||||
* 支付宝的支付回调通知,和退款回调通知 地址是同一个
|
||||
* 是否是退款回调通知
|
||||
* @param notifyData 通知数据
|
||||
* @return
|
||||
*/
|
||||
boolean isRefundNotify(Long channelId, PayNotifyDataDTO notifyData);
|
||||
}
|
@ -47,6 +47,4 @@ public interface PayOrderCoreService {
|
||||
*/
|
||||
void notifyPayOrder(Long channelId, PayNotifyDataDTO notifyData) throws Exception;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -5,19 +5,21 @@ import cn.iocoder.yudao.framework.pay.core.enums.PayChannelRespEnum;
|
||||
|
||||
/**
|
||||
* 支付退款订单 ,渠道返回后 后置处理
|
||||
*
|
||||
* @author jason
|
||||
*/
|
||||
public interface PayRefundChannelPostHandler {
|
||||
|
||||
/**
|
||||
* 支持的渠道返回值
|
||||
*
|
||||
* @return 支持的渠道返回值数组
|
||||
*/
|
||||
PayChannelRespEnum[] supportHandleResp();
|
||||
|
||||
|
||||
/**
|
||||
* 根据渠道返回, 处理支付退款单
|
||||
* 根据渠道返回,处理支付退款单
|
||||
*
|
||||
* @param respBO
|
||||
*/
|
||||
void handleRefundChannelResp(PayRefundPostReqBO respBO);
|
||||
|
@ -11,23 +11,22 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO;
|
||||
*/
|
||||
public interface PayRefundCoreService {
|
||||
|
||||
|
||||
// TODO @jason:方法名改成,submitRefundOrder,发起退款订单。这样和发起支付单,保持一致
|
||||
/**
|
||||
* 提交退款申请
|
||||
*
|
||||
* @param reqDTO 退款申请信息
|
||||
* @return 退款申请返回信息
|
||||
*/
|
||||
PayRefundRespBO refund(PayRefundReqBO reqDTO);
|
||||
|
||||
|
||||
/**
|
||||
* 渠道的退款通知
|
||||
*
|
||||
* @param channelId 渠道编号
|
||||
* @param notifyData 通知数据
|
||||
* @throws Exception 退款通知异常
|
||||
*/
|
||||
void notifyPayRefund(Long channelId, PayNotifyDataDTO notifyData) throws Exception;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
// TODO @jason:改到 dto 哈。我们项目,统一使用 DTO
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Builder
|
||||
|
@ -5,6 +5,8 @@ import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
// TODO @jason:改到 dto 哈。我们项目,统一使用 DTO
|
||||
/**
|
||||
* 退款申请单 Request DTO
|
||||
*/
|
||||
|
@ -6,6 +6,7 @@ import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
// TODO @jason:改到 dto 哈。我们项目,统一使用 DTO
|
||||
/**
|
||||
* 退款申请单 Response DTO
|
||||
*/
|
||||
|
@ -1,62 +0,0 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl;
|
||||
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayChannelCoreService;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayCommonCoreService;
|
||||
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.dto.PayNotifyDataDTO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_CHANNEL_CLIENT_NOT_FOUND;
|
||||
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_CHANNEL_NOTIFY_VERIFY_FAILED;
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
|
||||
/**
|
||||
* 支付通用 Core Service 实现类
|
||||
*
|
||||
* @author jason
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class PayCommonCoreServiceImpl implements PayCommonCoreService {
|
||||
|
||||
@Resource
|
||||
private PayChannelCoreService payChannelCoreService;
|
||||
|
||||
@Resource
|
||||
private PayClientFactory payClientFactory;
|
||||
|
||||
@Override
|
||||
public void verifyNotifyData(Long channelId, PayNotifyDataDTO notifyData) {
|
||||
// 校验支付渠道是否有效
|
||||
PayChannelDO channel = payChannelCoreService.validPayChannel(channelId);
|
||||
// 校验支付客户端是否正确初始化
|
||||
PayClient client = payClientFactory.getPayClient(channel.getId());
|
||||
if (client == null) {
|
||||
log.error("[notifyPayOrder][渠道编号({}) 找不到对应的支付客户端]", channel.getId());
|
||||
throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND);
|
||||
}
|
||||
boolean verifyResult = client.verifyNotifyData(notifyData);
|
||||
if(!verifyResult){
|
||||
//渠道通知验证失败
|
||||
throw exception(PAY_CHANNEL_NOTIFY_VERIFY_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRefundNotify(Long channelId, PayNotifyDataDTO notifyData) {
|
||||
// 校验支付渠道是否有效
|
||||
PayChannelDO channel = payChannelCoreService.validPayChannel(channelId);
|
||||
// 校验支付客户端是否正确初始化
|
||||
PayClient client = payClientFactory.getPayClient(channel.getId());
|
||||
if (client == null) {
|
||||
log.error("[notifyPayOrder][渠道编号({}) 找不到对应的支付客户端]", channel.getId());
|
||||
throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND);
|
||||
}
|
||||
return client.isRefundNotify(notifyData);
|
||||
}
|
||||
}
|
@ -50,18 +50,17 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
|
||||
|
||||
@Resource
|
||||
private PayOrderCoreMapper payOrderCoreMapper;
|
||||
|
||||
@Resource
|
||||
private PayRefundCoreMapper payRefundCoreMapper;
|
||||
|
||||
@Resource
|
||||
private PayOrderExtensionCoreMapper payOrderExtensionCoreMapper;
|
||||
|
||||
@Resource
|
||||
private PayAppCoreService payAppCoreService;
|
||||
|
||||
@Resource
|
||||
private PayChannelCoreService payChannelCoreService;
|
||||
@Resource
|
||||
private PayNotifyCoreService payNotifyCoreService;
|
||||
|
||||
@Resource
|
||||
private PayClientFactory payClientFactory;
|
||||
@ -72,25 +71,18 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
|
||||
@Resource
|
||||
private List<PayRefundChannelPostHandler> handlerList;
|
||||
|
||||
@Resource
|
||||
private PayNotifyCoreService payNotifyCoreService;
|
||||
|
||||
|
||||
// TODO @json:mapHandlers
|
||||
private final EnumMap<PayChannelRespEnum, PayRefundChannelPostHandler> mapHandler = new EnumMap<>(PayChannelRespEnum.class);
|
||||
|
||||
|
||||
|
||||
@PostConstruct
|
||||
public void init(){
|
||||
|
||||
if (Objects.nonNull(handlerList)) {
|
||||
handlerList.forEach(t->{
|
||||
for (PayChannelRespEnum item : t.supportHandleResp()) {
|
||||
mapHandler.put(item, t);
|
||||
handlerList.forEach(handler -> {
|
||||
for (PayChannelRespEnum item : handler.supportHandleResp()) {
|
||||
mapHandler.put(item, handler);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -113,16 +105,16 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
|
||||
throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
//校验退款的条件
|
||||
// 校验退款的条件
|
||||
validatePayRefund(reqBO, order);
|
||||
|
||||
//退款类型
|
||||
// 退款类型
|
||||
PayRefundTypeEnum refundType = PayRefundTypeEnum.SOME;
|
||||
if (Objects.equals(reqBO.getAmount(), order.getAmount())) {
|
||||
refundType = PayRefundTypeEnum.ALL;
|
||||
}
|
||||
|
||||
//退款单入库 退款单状态:生成, 没有和渠道产生交互
|
||||
// 退款单入库 退款单状态:生成, 没有和渠道产生交互
|
||||
PayOrderExtensionDO orderExtensionDO = payOrderExtensionCoreMapper.selectById(order.getSuccessExtensionId());
|
||||
PayRefundDO refundDO = PayRefundDO.builder().channelOrderNo(order.getChannelOrderNo())
|
||||
.appId(order.getAppId())
|
||||
@ -144,9 +136,9 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
|
||||
.reqNo(PaySeqUtils.genRefundReqNo())
|
||||
.type(refundType.getStatus())
|
||||
.build();
|
||||
|
||||
payRefundCoreMapper.insert(refundDO);
|
||||
|
||||
// TODO @jason:可以把“调用渠道进行退款"写到这里,这样分块更明确
|
||||
PayRefundUnifiedReqDTO unifiedReqDTO = PayRefundUnifiedReqDTO.builder()
|
||||
.userIp(reqBO.getUserIp())
|
||||
.channelOrderNo(refundDO.getChannelOrderNo())
|
||||
@ -156,13 +148,14 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
|
||||
.reason(refundDO.getReason())
|
||||
.build();
|
||||
|
||||
//调用渠道进行退款
|
||||
// 调用渠道进行退款
|
||||
PayRefundUnifiedRespDTO refundUnifiedRespDTO = client.unifiedRefund(unifiedReqDTO);
|
||||
|
||||
//根据渠道返回,获取退款后置处理,由postHandler 进行处理
|
||||
// TODO @jason:下面这块,是一整块逻辑,不要空开。不然阅读的时候,会以为不是一块逻辑
|
||||
// 根据渠道返回,获取退款后置处理,由postHandler 进行处理
|
||||
PayRefundChannelPostHandler payRefundChannelPostHandler = mapHandler.get(refundUnifiedRespDTO.getRespEnum());
|
||||
|
||||
if(Objects.isNull(payRefundChannelPostHandler)){
|
||||
if (Objects.isNull(payRefundChannelPostHandler)) {
|
||||
throw exception(PAY_REFUND_POST_HANDLER_NOT_FOUND);
|
||||
}
|
||||
|
||||
@ -192,11 +185,12 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
|
||||
log.error("[notifyPayOrder][渠道编号({}) 找不到对应的支付客户端]", channel.getId());
|
||||
throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND);
|
||||
}
|
||||
//解析渠道退款通知数据, 统一处理
|
||||
// 解析渠道退款通知数据, 统一处理
|
||||
PayRefundNotifyDTO refundNotify = client.parseRefundNotify(notifyData);
|
||||
|
||||
if(Objects.equals(PayNotifyRefundStatusEnum.SUCCESS,refundNotify.getStatus())){
|
||||
//退款成功。 支付宝只有退款成功才会发通知
|
||||
// TODO @jason:抽一个 notifyPayRefundSuccess 方法
|
||||
if (Objects.equals(PayNotifyRefundStatusEnum.SUCCESS,refundNotify.getStatus())){
|
||||
// 退款成功。 支付宝只有退款成功才会发通知
|
||||
PayRefundDO refundDO = payRefundCoreMapper.selectByReqNo(refundNotify.getReqNo());
|
||||
if (refundDO == null) {
|
||||
log.error("不存在 seqNo 为{} 的支付退款单",refundNotify.getReqNo());
|
||||
@ -208,9 +202,9 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
|
||||
if(PayRefundTypeEnum.ALL.getStatus().equals(type)){
|
||||
orderStatus = PayOrderStatusEnum.CLOSED;
|
||||
}
|
||||
//更新支付订单
|
||||
// 更新支付订单
|
||||
PayOrderDO payOrderDO = payOrderCoreMapper.selectById(refundDO.getOrderId());
|
||||
//需更新已退金额
|
||||
// 需更新已退金额
|
||||
Long refundedAmount = payOrderDO.getRefundAmount();
|
||||
PayOrderDO updateOrderDO = new PayOrderDO();
|
||||
updateOrderDO.setId(refundDO.getOrderId())
|
||||
@ -219,7 +213,7 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
|
||||
.setRefundStatus(type);
|
||||
payOrderCoreMapper.updateById(updateOrderDO);
|
||||
|
||||
//跟新退款订单
|
||||
// 跟新退款订单
|
||||
PayRefundDO updateRefundDO = new PayRefundDO();
|
||||
updateRefundDO.setId(refundDO.getId())
|
||||
.setSuccessTime(refundNotify.getRefundSuccessTime())
|
||||
@ -233,10 +227,9 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
|
||||
// TODO 通知商户成功或者失败. 现在通知似乎没有实现, 只是回调
|
||||
payNotifyCoreService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder()
|
||||
.type(PayNotifyTypeEnum.REFUND.getType()).dataId(refundDO.getId()).build());
|
||||
}else{
|
||||
} else {
|
||||
//TODO 退款失败
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -245,7 +238,6 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
|
||||
* @param order 原始支付订单信息
|
||||
*/
|
||||
private void validatePayRefund(PayRefundReqBO reqBO, PayOrderDO order) {
|
||||
|
||||
// 校验状态,必须是支付状态
|
||||
if (!PayOrderStatusEnum.SUCCESS.getStatus().equals(order.getStatus())) {
|
||||
throw exception(PAY_ORDER_STATUS_IS_NOT_SUCCESS);
|
||||
@ -258,10 +250,11 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
|
||||
if(reqBO.getAmount() + order.getRefundAmount() > order.getAmount()){
|
||||
throw exception(PAY_REFUND_AMOUNT_EXCEED);
|
||||
}
|
||||
//校验渠道订单号
|
||||
// 校验渠道订单号
|
||||
if (StrUtil.isEmpty(order.getChannelOrderNo())) {
|
||||
throw exception(PAY_REFUND_CHN_ORDER_NO_IS_NULL);
|
||||
}
|
||||
//TODO 退款的期限 退款次数的控制
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl;
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl.handler;
|
||||
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO;
|
@ -1,4 +1,4 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl;
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl.handler;
|
||||
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO;
|
@ -1,4 +1,4 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl;
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl.handler;
|
||||
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO;
|
@ -1,4 +1,4 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl;
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl.handler;
|
||||
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO;
|
@ -1,4 +1,4 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl;
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl.handler;
|
||||
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO;
|
Reference in New Issue
Block a user