Commit bcc2ff0f5bee343442898dcc17306b197552c08a

Authored by YunaiV
1 parent d49ce4c8

code review 退款逻辑

Showing 17 changed files with 77 additions and 156 deletions
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/PayCommonCoreService.java deleted
1   -package cn.iocoder.yudao.coreservice.modules.pay.service.order;
2   -
3   -import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO;
4   -
5   -/**
6   - * 支付通用 Core Service
7   - *
8   - * @author jason
9   - */
10   -public interface PayCommonCoreService {
11   -
12   - /**
13   - * 验证是否是渠道通知
14   - * @param notifyData 通知数据
15   - */
16   - void verifyNotifyData(Long channelId, PayNotifyDataDTO notifyData);
17   -
18   - /**
19   - * 支付宝的支付回调通知,和退款回调通知 地址是同一个
20   - * 是否是退款回调通知
21   - * @param notifyData 通知数据
22   - * @return
23   - */
24   - boolean isRefundNotify(Long channelId, PayNotifyDataDTO notifyData);
25   -}
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/PayOrderCoreService.java
... ... @@ -47,6 +47,4 @@ public interface PayOrderCoreService {
47 47 */
48 48 void notifyPayOrder(Long channelId, PayNotifyDataDTO notifyData) throws Exception;
49 49  
50   -
51   -
52 50 }
... ...
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/PayRefundChannelPostHandler.java
... ... @@ -5,19 +5,21 @@ import cn.iocoder.yudao.framework.pay.core.enums.PayChannelRespEnum;
5 5  
6 6 /**
7 7 * 支付退款订单 ,渠道返回后 后置处理
  8 + *
8 9 * @author jason
9 10 */
10 11 public interface PayRefundChannelPostHandler {
11 12  
12 13 /**
13 14 * 支持的渠道返回值
  15 + *
14 16 * @return 支持的渠道返回值数组
15 17 */
16 18 PayChannelRespEnum[] supportHandleResp();
17 19  
18   -
19 20 /**
20   - * 根据渠道返回, 处理支付退款单
  21 + * 根据渠道返回,处理支付退款单
  22 + *
21 23 * @param respBO
22 24 */
23 25 void handleRefundChannelResp(PayRefundPostReqBO respBO);
... ...
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/PayRefundCoreService.java
... ... @@ -11,23 +11,22 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO;
11 11 */
12 12 public interface PayRefundCoreService {
13 13  
14   -
  14 + // TODO @jason:方法名改成,submitRefundOrder,发起退款订单。这样和发起支付单,保持一致
15 15 /**
16 16 * 提交退款申请
  17 + *
17 18 * @param reqDTO 退款申请信息
18 19 * @return 退款申请返回信息
19 20 */
20 21 PayRefundRespBO refund(PayRefundReqBO reqDTO);
21 22  
22   -
23 23 /**
24 24 * 渠道的退款通知
  25 + *
25 26 * @param channelId 渠道编号
26 27 * @param notifyData 通知数据
27 28 * @throws Exception 退款通知异常
28 29 */
29 30 void notifyPayRefund(Long channelId, PayNotifyDataDTO notifyData) throws Exception;
30 31  
31   -
32   -
33 32 }
... ...
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/bo/PayRefundPostReqBO.java
... ... @@ -8,6 +8,7 @@ import lombok.Data;
8 8 import lombok.NoArgsConstructor;
9 9 import lombok.experimental.Accessors;
10 10  
  11 +// TODO @jason:改到 dto 哈。我们项目,统一使用 DTO
11 12 @Data
12 13 @Accessors(chain = true)
13 14 @Builder
... ...
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/bo/PayRefundReqBO.java
... ... @@ -5,6 +5,8 @@ import lombok.Builder;
5 5 import lombok.Data;
6 6 import lombok.NoArgsConstructor;
7 7 import lombok.experimental.Accessors;
  8 +
  9 +// TODO @jason:改到 dto 哈。我们项目,统一使用 DTO
8 10 /**
9 11 * 退款申请单 Request DTO
10 12 */
... ...
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/bo/PayRefundRespBO.java
... ... @@ -6,6 +6,7 @@ import lombok.Data;
6 6 import lombok.NoArgsConstructor;
7 7 import lombok.experimental.Accessors;
8 8  
  9 +// TODO @jason:改到 dto 哈。我们项目,统一使用 DTO
9 10 /**
10 11 * 退款申请单 Response DTO
11 12 */
... ...
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/impl/PayCommonCoreServiceImpl.java deleted
1   -package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl;
2   -
3   -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
4   -import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayChannelCoreService;
5   -import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayCommonCoreService;
6   -import cn.iocoder.yudao.framework.pay.core.client.PayClient;
7   -import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
8   -import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO;
9   -import lombok.extern.slf4j.Slf4j;
10   -import org.springframework.stereotype.Service;
11   -
12   -import javax.annotation.Resource;
13   -
14   -import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_CHANNEL_CLIENT_NOT_FOUND;
15   -import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_CHANNEL_NOTIFY_VERIFY_FAILED;
16   -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
17   -
18   -/**
19   - * 支付通用 Core Service 实现类
20   - *
21   - * @author jason
22   - */
23   -@Service
24   -@Slf4j
25   -public class PayCommonCoreServiceImpl implements PayCommonCoreService {
26   -
27   - @Resource
28   - private PayChannelCoreService payChannelCoreService;
29   -
30   - @Resource
31   - private PayClientFactory payClientFactory;
32   -
33   - @Override
34   - public void verifyNotifyData(Long channelId, PayNotifyDataDTO notifyData) {
35   - // 校验支付渠道是否有效
36   - PayChannelDO channel = payChannelCoreService.validPayChannel(channelId);
37   - // 校验支付客户端是否正确初始化
38   - PayClient client = payClientFactory.getPayClient(channel.getId());
39   - if (client == null) {
40   - log.error("[notifyPayOrder][渠道编号({}) 找不到对应的支付客户端]", channel.getId());
41   - throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND);
42   - }
43   - boolean verifyResult = client.verifyNotifyData(notifyData);
44   - if(!verifyResult){
45   - //渠道通知验证失败
46   - throw exception(PAY_CHANNEL_NOTIFY_VERIFY_FAILED);
47   - }
48   - }
49   -
50   - @Override
51   - public boolean isRefundNotify(Long channelId, PayNotifyDataDTO notifyData) {
52   - // 校验支付渠道是否有效
53   - PayChannelDO channel = payChannelCoreService.validPayChannel(channelId);
54   - // 校验支付客户端是否正确初始化
55   - PayClient client = payClientFactory.getPayClient(channel.getId());
56   - if (client == null) {
57   - log.error("[notifyPayOrder][渠道编号({}) 找不到对应的支付客户端]", channel.getId());
58   - throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND);
59   - }
60   - return client.isRefundNotify(notifyData);
61   - }
62   -}
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/impl/PayRefundCoreServiceImpl.java
... ... @@ -50,18 +50,17 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
50 50  
51 51 @Resource
52 52 private PayOrderCoreMapper payOrderCoreMapper;
53   -
54 53 @Resource
55 54 private PayRefundCoreMapper payRefundCoreMapper;
56   -
57 55 @Resource
58 56 private PayOrderExtensionCoreMapper payOrderExtensionCoreMapper;
59 57  
60 58 @Resource
61 59 private PayAppCoreService payAppCoreService;
62   -
63 60 @Resource
64 61 private PayChannelCoreService payChannelCoreService;
  62 + @Resource
  63 + private PayNotifyCoreService payNotifyCoreService;
65 64  
66 65 @Resource
67 66 private PayClientFactory payClientFactory;
... ... @@ -72,25 +71,18 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
72 71 @Resource
73 72 private List<PayRefundChannelPostHandler> handlerList;
74 73  
75   - @Resource
76   - private PayNotifyCoreService payNotifyCoreService;
77   -
78   -
  74 + // TODO @json:mapHandlers
79 75 private final EnumMap<PayChannelRespEnum, PayRefundChannelPostHandler> mapHandler = new EnumMap<>(PayChannelRespEnum.class);
80 76  
81   -
82   -
83 77 @PostConstruct
84 78 public void init(){
85   -
86 79 if (Objects.nonNull(handlerList)) {
87   - handlerList.forEach(t->{
88   - for (PayChannelRespEnum item : t.supportHandleResp()) {
89   - mapHandler.put(item, t);
  80 + handlerList.forEach(handler -> {
  81 + for (PayChannelRespEnum item : handler.supportHandleResp()) {
  82 + mapHandler.put(item, handler);
90 83 }
91 84 });
92 85 }
93   -
94 86 }
95 87  
96 88 @Override
... ... @@ -113,16 +105,16 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
113 105 throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND);
114 106 }
115 107  
116   - //校验退款的条件
  108 + // 校验退款的条件
117 109 validatePayRefund(reqBO, order);
118 110  
119   - //退款类型
  111 + // 退款类型
120 112 PayRefundTypeEnum refundType = PayRefundTypeEnum.SOME;
121 113 if (Objects.equals(reqBO.getAmount(), order.getAmount())) {
122 114 refundType = PayRefundTypeEnum.ALL;
123 115 }
124 116  
125   - //退款单入库 退款单状态:生成, 没有和渠道产生交互
  117 + // 退款单入库 退款单状态:生成, 没有和渠道产生交互
126 118 PayOrderExtensionDO orderExtensionDO = payOrderExtensionCoreMapper.selectById(order.getSuccessExtensionId());
127 119 PayRefundDO refundDO = PayRefundDO.builder().channelOrderNo(order.getChannelOrderNo())
128 120 .appId(order.getAppId())
... ... @@ -144,9 +136,9 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
144 136 .reqNo(PaySeqUtils.genRefundReqNo())
145 137 .type(refundType.getStatus())
146 138 .build();
147   -
148 139 payRefundCoreMapper.insert(refundDO);
149 140  
  141 + // TODO @jason:可以把“调用渠道进行退款"写到这里,这样分块更明确
150 142 PayRefundUnifiedReqDTO unifiedReqDTO = PayRefundUnifiedReqDTO.builder()
151 143 .userIp(reqBO.getUserIp())
152 144 .channelOrderNo(refundDO.getChannelOrderNo())
... ... @@ -156,13 +148,14 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
156 148 .reason(refundDO.getReason())
157 149 .build();
158 150  
159   - //调用渠道进行退款
  151 + // 调用渠道进行退款
160 152 PayRefundUnifiedRespDTO refundUnifiedRespDTO = client.unifiedRefund(unifiedReqDTO);
161 153  
162   - //根据渠道返回,获取退款后置处理,由postHandler 进行处理
  154 + // TODO @jason:下面这块,是一整块逻辑,不要空开。不然阅读的时候,会以为不是一块逻辑
  155 + // 根据渠道返回,获取退款后置处理,由postHandler 进行处理
163 156 PayRefundChannelPostHandler payRefundChannelPostHandler = mapHandler.get(refundUnifiedRespDTO.getRespEnum());
164 157  
165   - if(Objects.isNull(payRefundChannelPostHandler)){
  158 + if (Objects.isNull(payRefundChannelPostHandler)) {
166 159 throw exception(PAY_REFUND_POST_HANDLER_NOT_FOUND);
167 160 }
168 161  
... ... @@ -192,11 +185,12 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
192 185 log.error("[notifyPayOrder][渠道编号({}) 找不到对应的支付客户端]", channel.getId());
193 186 throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND);
194 187 }
195   - //解析渠道退款通知数据, 统一处理
  188 + // 解析渠道退款通知数据, 统一处理
196 189 PayRefundNotifyDTO refundNotify = client.parseRefundNotify(notifyData);
197 190  
198   - if(Objects.equals(PayNotifyRefundStatusEnum.SUCCESS,refundNotify.getStatus())){
199   - //退款成功。 支付宝只有退款成功才会发通知
  191 + // TODO @jason:抽一个 notifyPayRefundSuccess 方法
  192 + if (Objects.equals(PayNotifyRefundStatusEnum.SUCCESS,refundNotify.getStatus())){
  193 + // 退款成功。 支付宝只有退款成功才会发通知
200 194 PayRefundDO refundDO = payRefundCoreMapper.selectByReqNo(refundNotify.getReqNo());
201 195 if (refundDO == null) {
202 196 log.error("不存在 seqNo 为{} 的支付退款单",refundNotify.getReqNo());
... ... @@ -208,9 +202,9 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
208 202 if(PayRefundTypeEnum.ALL.getStatus().equals(type)){
209 203 orderStatus = PayOrderStatusEnum.CLOSED;
210 204 }
211   - //更新支付订单
  205 + // 更新支付订单
212 206 PayOrderDO payOrderDO = payOrderCoreMapper.selectById(refundDO.getOrderId());
213   - //需更新已退金额
  207 + // 需更新已退金额
214 208 Long refundedAmount = payOrderDO.getRefundAmount();
215 209 PayOrderDO updateOrderDO = new PayOrderDO();
216 210 updateOrderDO.setId(refundDO.getOrderId())
... ... @@ -219,7 +213,7 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
219 213 .setRefundStatus(type);
220 214 payOrderCoreMapper.updateById(updateOrderDO);
221 215  
222   - //跟新退款订单
  216 + // 跟新退款订单
223 217 PayRefundDO updateRefundDO = new PayRefundDO();
224 218 updateRefundDO.setId(refundDO.getId())
225 219 .setSuccessTime(refundNotify.getRefundSuccessTime())
... ... @@ -233,10 +227,9 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
233 227 // TODO 通知商户成功或者失败. 现在通知似乎没有实现, 只是回调
234 228 payNotifyCoreService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder()
235 229 .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refundDO.getId()).build());
236   - }else{
  230 + } else {
237 231 //TODO 退款失败
238 232 }
239   -
240 233 }
241 234  
242 235 /**
... ... @@ -245,7 +238,6 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
245 238 * @param order 原始支付订单信息
246 239 */
247 240 private void validatePayRefund(PayRefundReqBO reqBO, PayOrderDO order) {
248   -
249 241 // 校验状态,必须是支付状态
250 242 if (!PayOrderStatusEnum.SUCCESS.getStatus().equals(order.getStatus())) {
251 243 throw exception(PAY_ORDER_STATUS_IS_NOT_SUCCESS);
... ... @@ -258,10 +250,11 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
258 250 if(reqBO.getAmount() + order.getRefundAmount() > order.getAmount()){
259 251 throw exception(PAY_REFUND_AMOUNT_EXCEED);
260 252 }
261   - //校验渠道订单号
  253 + // 校验渠道订单号
262 254 if (StrUtil.isEmpty(order.getChannelOrderNo())) {
263 255 throw exception(PAY_REFUND_CHN_ORDER_NO_IS_NULL);
264 256 }
265 257 //TODO 退款的期限 退款次数的控制
266 258 }
  259 +
267 260 }
... ...
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/impl/PayRefundChannelFailedHandler.java renamed to yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/impl/handler/PayRefundChannelFailedHandler.java
1   -package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl;
  1 +package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl.handler;
2 2  
3 3 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
4 4 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO;
... ...
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/impl/PayRefundChannelNotifyHandler.java renamed to yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/impl/handler/PayRefundChannelNotifyHandler.java
1   -package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl;
  1 +package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl.handler;
2 2  
3 3 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
4 4 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO;
... ...
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/impl/PayRefundChannelQueryHandler.java renamed to yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/impl/handler/PayRefundChannelQueryHandler.java
1   -package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl;
  1 +package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl.handler;
2 2  
3 3 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
4 4 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO;
... ...
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/impl/PayRefundChannelRetryHandler.java renamed to yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/impl/handler/PayRefundChannelRetryHandler.java
1   -package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl;
  1 +package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl.handler;
2 2  
3 3 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
4 4 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO;
... ...
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/impl/PayRefundChannelSuccessHandler.java renamed to yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/impl/handler/PayRefundChannelSuccessHandler.java
1   -package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl;
  1 +package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl.handler;
2 2  
3 3 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
4 4 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO;
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClient.java
... ... @@ -34,7 +34,6 @@ public interface PayClient {
34 34 */
35 35 PayOrderNotifyRespDTO parseOrderNotify(PayNotifyDataDTO data) throws Exception;
36 36  
37   -
38 37 /**
39 38 * 调用支付渠道,进行退款
40 39 * @param reqDTO 统一退款请求信息
... ... @@ -49,22 +48,26 @@ public interface PayClient {
49 48 */
50 49 PayRefundNotifyDTO parseRefundNotify(PayNotifyDataDTO notifyData);
51 50  
52   -
  51 + // TODO @芋艿:后续改成非 default,避免不知道去实现
53 52 /**
54 53 * 验证是否渠道通知
  54 + *
55 55 * @param notifyData 通知数据
56 56 * @return 默认是 true
57 57 */
58   - default boolean verifyNotifyData(PayNotifyDataDTO notifyData){
  58 + default boolean verifyNotifyData(PayNotifyDataDTO notifyData) {
59 59 return true;
60 60 }
61 61  
  62 + // TODO @芋艿:后续改成非 default,避免不知道去实现
62 63 /**
63   - * 是否退款通知
  64 + * 判断是否为退款通知
  65 + *
64 66 * @param notifyData 通知数据
65 67 * @return 默认是 false
66 68 */
67 69 default boolean isRefundNotify(PayNotifyDataDTO notifyData){
68 70 return false;
69 71 }
  72 +
70 73 }
... ...
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/PayOrderController.java
... ... @@ -2,27 +2,27 @@ package cn.iocoder.yudao.userserver.modules.pay.controller.order;
2 2  
3 3 import cn.hutool.core.bean.BeanUtil;
4 4 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
5   -import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayCommonCoreService;
6 5 import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayOrderCoreService;
7 6 import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayRefundCoreService;
8 7 import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitReqDTO;
9 8 import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitRespDTO;
10 9 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  10 +import cn.iocoder.yudao.framework.pay.core.client.PayClient;
  11 +import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
11 12 import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO;
12   -import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
13 13 import cn.iocoder.yudao.userserver.modules.pay.controller.order.vo.PayOrderSubmitReqVO;
14 14 import cn.iocoder.yudao.userserver.modules.pay.controller.order.vo.PayOrderSubmitRespVO;
15 15 import io.swagger.annotations.Api;
16 16 import io.swagger.annotations.ApiOperation;
17 17 import lombok.extern.slf4j.Slf4j;
18   -import org.springframework.http.MediaType;
19 18 import org.springframework.validation.annotation.Validated;
20 19 import org.springframework.web.bind.annotation.*;
21 20  
22 21 import javax.annotation.Resource;
23   -
24 22 import java.util.Map;
25 23  
  24 +import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_CHANNEL_CLIENT_NOT_FOUND;
  25 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
26 26 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
27 27 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
28 28  
... ... @@ -35,11 +35,11 @@ public class PayOrderController {
35 35  
36 36 @Resource
37 37 private PayOrderCoreService payOrderCoreService;
38   -
39 38 @Resource
40 39 private PayRefundCoreService payRefundCoreService;
41 40  
42   - @Resource PayCommonCoreService commonCoreService;
  41 + @Resource
  42 + private PayClientFactory payClientFactory;
43 43  
44 44  
45 45 @PostMapping("/submit")
... ... @@ -81,11 +81,12 @@ public class PayOrderController {
81 81 public String returnAliPayOrder(@PathVariable("channelId") Long channelId, @RequestParam Map<String, String> params){
82 82 //TODO 可以根据渠道和 app_id 返回不同的页面
83 83 log.info("app_id is {}", params.get("app_id"));
84   - return String.format("渠道[%s]支付成功", String.valueOf(channelId));
  84 + return String.format("渠道[%s]支付成功", channelId);
85 85 }
86 86  
87 87 /**
88 88 * 统一的渠道支付回调,支付宝的退款回调
  89 + *
89 90 * @param channelId 渠道编号
90 91 * @param params form 参数
91 92 * @param originData http request body
... ... @@ -94,20 +95,27 @@ public class PayOrderController {
94 95 @PostMapping(value = "/notify/{channelId}")
95 96 @ApiOperation("渠道统一的支付成功,或退款成功 通知url")
96 97 public String notifyChannelPay(@PathVariable("channelId") Long channelId,
97   - @RequestParam Map<String, String> params,
98   - @RequestBody String originData) throws Exception {
99   - //校验是否是渠道回调
100   - commonCoreService.verifyNotifyData(channelId, PayNotifyDataDTO.builder().params(params).body(originData).build());
101   - //支付宝退款交易也会触发支付回调接口
102   - //参考 https://opensupport.alipay.com/support/helpcenter/193/201602484851
103   - //判断是否为退款通知
104   - if(commonCoreService.isRefundNotify(channelId, PayNotifyDataDTO.builder().params(params).body(originData).build())) {
105   - //退款通知
106   - payRefundCoreService.notifyPayRefund(channelId,PayNotifyDataDTO.builder().params(params).body(originData).build());
107   - }else{
108   - //支付通知
109   - payOrderCoreService.notifyPayOrder(channelId,PayNotifyDataDTO.builder().params(params).body(originData).build());
  98 + @RequestParam Map<String, String> params,
  99 + @RequestBody String originData) throws Exception {
  100 + // 校验支付渠道是否存在
  101 + PayClient payClient = payClientFactory.getPayClient(channelId);
  102 + if (payClient == null) {
  103 + log.error("[notifyPayOrder][渠道编号({}) 找不到对应的支付客户端]", channelId);
  104 + throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND);
110 105 }
  106 +
  107 + // 校验通知数据是否合法
  108 + PayNotifyDataDTO notifyData = PayNotifyDataDTO.builder().params(params).body(originData).build();
  109 + payClient.verifyNotifyData(notifyData);
  110 +
  111 + // 如果是退款,则发起退款通知
  112 + if (payClient.isRefundNotify(notifyData)) {
  113 + payRefundCoreService.notifyPayRefund(channelId, PayNotifyDataDTO.builder().params(params).body(originData).build());
  114 + return "success";
  115 + }
  116 +
  117 + // 如果非退款,则发起支付通知
  118 + payOrderCoreService.notifyPayOrder(channelId, PayNotifyDataDTO.builder().params(params).body(originData).build());
111 119 return "success";
112 120 }
113 121  
... ...
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/PayRefundController.java
... ... @@ -32,7 +32,7 @@ public class PayRefundController {
32 32  
33 33 @PostMapping("/refund")
34 34 @ApiOperation("提交退款订单")
35   - public CommonResult<PayRefundRespVO> refund(@RequestBody PayRefundReqVO reqVO){
  35 + public CommonResult<PayRefundRespVO> refund(@RequestBody PayRefundReqVO reqVO){
36 36 PayRefundReqBO reqBO = PayRefundConvert.INSTANCE.convert(reqVO);
37 37 reqBO.setUserIp(getClientIP());
38 38 //TODO 测试暂时模拟生成商户退款订单
... ... @@ -40,4 +40,5 @@ public class PayRefundController {
40 40 //reqBO.setMerchantRefundNo("MO202111210814084370000");
41 41 return CommonResult.success( PayRefundConvert.INSTANCE.convert(payRefundCoreService.refund(reqBO)));
42 42 }
  43 +
43 44 }
... ...