mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-29 18:51:53 +08:00
code review 退款逻辑
This commit is contained in:
parent
d49ce4c81f
commit
bcc2ff0f5b
@ -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
|
||||
@ -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())
|
||||
@ -159,6 +151,7 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
|
||||
// 调用渠道进行退款
|
||||
PayRefundUnifiedRespDTO refundUnifiedRespDTO = client.unifiedRefund(unifiedReqDTO);
|
||||
|
||||
// TODO @jason:下面这块,是一整块逻辑,不要空开。不然阅读的时候,会以为不是一块逻辑
|
||||
// 根据渠道返回,获取退款后置处理,由postHandler 进行处理
|
||||
PayRefundChannelPostHandler payRefundChannelPostHandler = mapHandler.get(refundUnifiedRespDTO.getRespEnum());
|
||||
|
||||
@ -195,6 +188,7 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
|
||||
// 解析渠道退款通知数据, 统一处理
|
||||
PayRefundNotifyDTO refundNotify = client.parseRefundNotify(notifyData);
|
||||
|
||||
// TODO @jason:抽一个 notifyPayRefundSuccess 方法
|
||||
if (Objects.equals(PayNotifyRefundStatusEnum.SUCCESS,refundNotify.getStatus())){
|
||||
// 退款成功。 支付宝只有退款成功才会发通知
|
||||
PayRefundDO refundDO = payRefundCoreMapper.selectByReqNo(refundNotify.getReqNo());
|
||||
@ -236,7 +230,6 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
|
||||
} 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);
|
||||
@ -264,4 +256,5 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
|
||||
}
|
||||
//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;
|
@ -34,7 +34,6 @@ public interface PayClient {
|
||||
*/
|
||||
PayOrderNotifyRespDTO parseOrderNotify(PayNotifyDataDTO data) throws Exception;
|
||||
|
||||
|
||||
/**
|
||||
* 调用支付渠道,进行退款
|
||||
* @param reqDTO 统一退款请求信息
|
||||
@ -49,9 +48,10 @@ public interface PayClient {
|
||||
*/
|
||||
PayRefundNotifyDTO parseRefundNotify(PayNotifyDataDTO notifyData);
|
||||
|
||||
|
||||
// TODO @芋艿:后续改成非 default,避免不知道去实现
|
||||
/**
|
||||
* 验证是否渠道通知
|
||||
*
|
||||
* @param notifyData 通知数据
|
||||
* @return 默认是 true
|
||||
*/
|
||||
@ -59,12 +59,15 @@ public interface PayClient {
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO @芋艿:后续改成非 default,避免不知道去实现
|
||||
/**
|
||||
* 是否退款通知
|
||||
* 判断是否为退款通知
|
||||
*
|
||||
* @param notifyData 通知数据
|
||||
* @return 默认是 false
|
||||
*/
|
||||
default boolean isRefundNotify(PayNotifyDataDTO notifyData){
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,27 +2,27 @@ package cn.iocoder.yudao.userserver.modules.pay.controller.order;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayCommonCoreService;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayOrderCoreService;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayRefundCoreService;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitReqDTO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitRespDTO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
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 cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
|
||||
import cn.iocoder.yudao.userserver.modules.pay.controller.order.vo.PayOrderSubmitReqVO;
|
||||
import cn.iocoder.yudao.userserver.modules.pay.controller.order.vo.PayOrderSubmitRespVO;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_CHANNEL_CLIENT_NOT_FOUND;
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
|
||||
|
||||
@ -35,11 +35,11 @@ public class PayOrderController {
|
||||
|
||||
@Resource
|
||||
private PayOrderCoreService payOrderCoreService;
|
||||
|
||||
@Resource
|
||||
private PayRefundCoreService payRefundCoreService;
|
||||
|
||||
@Resource PayCommonCoreService commonCoreService;
|
||||
@Resource
|
||||
private PayClientFactory payClientFactory;
|
||||
|
||||
|
||||
@PostMapping("/submit")
|
||||
@ -81,11 +81,12 @@ public class PayOrderController {
|
||||
public String returnAliPayOrder(@PathVariable("channelId") Long channelId, @RequestParam Map<String, String> params){
|
||||
//TODO 可以根据渠道和 app_id 返回不同的页面
|
||||
log.info("app_id is {}", params.get("app_id"));
|
||||
return String.format("渠道[%s]支付成功", String.valueOf(channelId));
|
||||
return String.format("渠道[%s]支付成功", channelId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一的渠道支付回调,支付宝的退款回调
|
||||
*
|
||||
* @param channelId 渠道编号
|
||||
* @param params form 参数
|
||||
* @param originData http request body
|
||||
@ -96,18 +97,25 @@ public class PayOrderController {
|
||||
public String notifyChannelPay(@PathVariable("channelId") Long channelId,
|
||||
@RequestParam Map<String, String> params,
|
||||
@RequestBody String originData) throws Exception {
|
||||
//校验是否是渠道回调
|
||||
commonCoreService.verifyNotifyData(channelId, PayNotifyDataDTO.builder().params(params).body(originData).build());
|
||||
//支付宝退款交易也会触发支付回调接口
|
||||
//参考 https://opensupport.alipay.com/support/helpcenter/193/201602484851
|
||||
//判断是否为退款通知
|
||||
if(commonCoreService.isRefundNotify(channelId, PayNotifyDataDTO.builder().params(params).body(originData).build())) {
|
||||
//退款通知
|
||||
payRefundCoreService.notifyPayRefund(channelId,PayNotifyDataDTO.builder().params(params).body(originData).build());
|
||||
}else{
|
||||
//支付通知
|
||||
payOrderCoreService.notifyPayOrder(channelId,PayNotifyDataDTO.builder().params(params).body(originData).build());
|
||||
// 校验支付渠道是否存在
|
||||
PayClient payClient = payClientFactory.getPayClient(channelId);
|
||||
if (payClient == null) {
|
||||
log.error("[notifyPayOrder][渠道编号({}) 找不到对应的支付客户端]", channelId);
|
||||
throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
// 校验通知数据是否合法
|
||||
PayNotifyDataDTO notifyData = PayNotifyDataDTO.builder().params(params).body(originData).build();
|
||||
payClient.verifyNotifyData(notifyData);
|
||||
|
||||
// 如果是退款,则发起退款通知
|
||||
if (payClient.isRefundNotify(notifyData)) {
|
||||
payRefundCoreService.notifyPayRefund(channelId, PayNotifyDataDTO.builder().params(params).body(originData).build());
|
||||
return "success";
|
||||
}
|
||||
|
||||
// 如果非退款,则发起支付通知
|
||||
payOrderCoreService.notifyPayOrder(channelId, PayNotifyDataDTO.builder().params(params).body(originData).build());
|
||||
return "success";
|
||||
}
|
||||
|
||||
|
@ -40,4 +40,5 @@ public class PayRefundController {
|
||||
//reqBO.setMerchantRefundNo("MO202111210814084370000");
|
||||
return CommonResult.success( PayRefundConvert.INSTANCE.convert(payRefundCoreService.refund(reqBO)));
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user