Commit 888c48820662de70e8df18623f6660f179abd01c

Authored by YunaiV
1 parent 3f410c27

mall + pay:

1. 优化 PayClient 退款逻辑,返回业务失败 errorCode + errorMsg 错误码
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/refund/PayRefundStatusRespEnum.java
@@ -25,4 +25,8 @@ public enum PayRefundStatusRespEnum { @@ -25,4 +25,8 @@ public enum PayRefundStatusRespEnum {
25 return Objects.equals(status, SUCCESS.getStatus()); 25 return Objects.equals(status, SUCCESS.getStatus());
26 } 26 }
27 27
  28 + public static boolean isFailure(Integer status) {
  29 + return Objects.equals(status, FAILURE.getStatus());
  30 + }
  31 +
28 } 32 }
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/refund/PayRefundStatusEnum.java
@@ -25,4 +25,8 @@ public enum PayRefundStatusEnum { @@ -25,4 +25,8 @@ public enum PayRefundStatusEnum {
25 return Objects.equals(status, SUCCESS.getStatus()); 25 return Objects.equals(status, SUCCESS.getStatus());
26 } 26 }
27 27
  28 + public static boolean isFailure(Integer status) {
  29 + return Objects.equals(status, FAILURE.getStatus());
  30 + }
  31 +
28 } 32 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java
@@ -237,6 +237,7 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -237,6 +237,7 @@ public class PayOrderServiceImpl implements PayOrderService {
237 TenantUtils.execute(channel.getTenantId(), () -> notifyPayOrder(channel, notify)); 237 TenantUtils.execute(channel.getTenantId(), () -> notifyPayOrder(channel, notify));
238 } 238 }
239 239
  240 + // TODO 芋艿:事务问题
240 private void notifyPayOrder(PayChannelDO channel, PayOrderRespDTO notify) { 241 private void notifyPayOrder(PayChannelDO channel, PayOrderRespDTO notify) {
241 // 情况一:支付成功的回调 242 // 情况一:支付成功的回调
242 if (PayOrderStatusRespEnum.isSuccess(notify.getStatus())) { 243 if (PayOrderStatusRespEnum.isSuccess(notify.getStatus())) {
@@ -372,7 +373,7 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -372,7 +373,7 @@ public class PayOrderServiceImpl implements PayOrderService {
372 throw exception(ORDER_NOT_FOUND); 373 throw exception(ORDER_NOT_FOUND);
373 } 374 }
374 if (!PayOrderStatusEnum.isSuccess(order.getStatus())) { 375 if (!PayOrderStatusEnum.isSuccess(order.getStatus())) {
375 - throw exception(REFUND_PRICE_EXCEED); 376 + throw exception(ORDER_STATUS_IS_NOT_SUCCESS);
376 } 377 }
377 if (order.getRefundPrice() + incrRefundPrice > order.getPrice()) { 378 if (order.getRefundPrice() + incrRefundPrice > order.getPrice()) {
378 throw exception(REFUND_PRICE_EXCEED); 379 throw exception(REFUND_PRICE_EXCEED);
@@ -389,7 +390,10 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -389,7 +390,10 @@ public class PayOrderServiceImpl implements PayOrderService {
389 updateObj.setStatus(PayOrderStatusEnum.CLOSED.getStatus()) 390 updateObj.setStatus(PayOrderStatusEnum.CLOSED.getStatus())
390 .setRefundStatus(PayOrderRefundStatusEnum.PART.getStatus()); 391 .setRefundStatus(PayOrderRefundStatusEnum.PART.getStatus());
391 } 392 }
392 - orderMapper.updateByIdAndStatus(id, PayOrderStatusEnum.SUCCESS.getStatus(), updateObj); 393 + int updateCount = orderMapper.updateByIdAndStatus(id, PayOrderStatusEnum.SUCCESS.getStatus(), updateObj);
  394 + if (updateCount == 0) {
  395 + throw exception(ORDER_STATUS_IS_NOT_SUCCESS);
  396 + }
393 } 397 }
394 398
395 } 399 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java
@@ -206,7 +206,6 @@ public class PayRefundServiceImpl implements PayRefundService { @@ -206,7 +206,6 @@ public class PayRefundServiceImpl implements PayRefundService {
206 } 206 }
207 207
208 @Override 208 @Override
209 - @Transactional(rollbackFor = Exception.class)  
210 public void notifyRefund(Long channelId, PayRefundRespDTO notify) { 209 public void notifyRefund(Long channelId, PayRefundRespDTO notify) {
211 // 校验支付渠道是否有效 210 // 校验支付渠道是否有效
212 channelService.validPayChannel(channelId); 211 channelService.validPayChannel(channelId);
@@ -218,15 +217,20 @@ public class PayRefundServiceImpl implements PayRefundService { @@ -218,15 +217,20 @@ public class PayRefundServiceImpl implements PayRefundService {
218 TenantUtils.execute(channel.getTenantId(), () -> notifyRefund(channel, notify)); 217 TenantUtils.execute(channel.getTenantId(), () -> notifyRefund(channel, notify));
219 } 218 }
220 219
  220 + // TODO 芋艿:事务问题
221 private void notifyRefund(PayChannelDO channel, PayRefundRespDTO notify) { 221 private void notifyRefund(PayChannelDO channel, PayRefundRespDTO notify) {
  222 + // 情况一:退款成功
222 if (PayRefundStatusRespEnum.isSuccess(notify.getStatus())) { 223 if (PayRefundStatusRespEnum.isSuccess(notify.getStatus())) {
223 notifyRefundSuccess(channel, notify); 224 notifyRefundSuccess(channel, notify);
224 - } else { 225 + return;
  226 + }
  227 + // 情况二:退款失败
  228 + if (PayRefundStatusRespEnum.isFailure(notify.getStatus())) {
225 notifyRefundFailure(channel, notify); 229 notifyRefundFailure(channel, notify);
226 } 230 }
227 } 231 }
228 232
229 - private void notifyRefundSuccess(PayChannelDO channel, PayRefundRespDTO notify) { 233 + public void notifyRefundSuccess(PayChannelDO channel, PayRefundRespDTO notify) {
230 // 1.1 查询 PayRefundDO 234 // 1.1 查询 PayRefundDO
231 PayRefundDO refund = refundMapper.selectByAppIdAndNo( 235 PayRefundDO refund = refundMapper.selectByAppIdAndNo(
232 channel.getAppId(), notify.getOutRefundNo()); 236 channel.getAppId(), notify.getOutRefundNo());
@@ -234,12 +238,12 @@ public class PayRefundServiceImpl implements PayRefundService { @@ -234,12 +238,12 @@ public class PayRefundServiceImpl implements PayRefundService {
234 throw exception(ErrorCodeConstants.REFUND_NOT_FOUND); 238 throw exception(ErrorCodeConstants.REFUND_NOT_FOUND);
235 } 239 }
236 if (PayRefundStatusEnum.isSuccess(refund.getStatus())) { // 如果已经是成功,直接返回,不用重复更新 240 if (PayRefundStatusEnum.isSuccess(refund.getStatus())) { // 如果已经是成功,直接返回,不用重复更新
  241 + log.info("[notifyRefundSuccess][退款订单({}) 已经是退款成功,无需更新]", refund.getId());
237 return; 242 return;
238 } 243 }
239 if (!PayRefundStatusEnum.WAITING.getStatus().equals(refund.getStatus())) { 244 if (!PayRefundStatusEnum.WAITING.getStatus().equals(refund.getStatus())) {
240 throw exception(ErrorCodeConstants.REFUND_STATUS_IS_NOT_WAITING); 245 throw exception(ErrorCodeConstants.REFUND_STATUS_IS_NOT_WAITING);
241 } 246 }
242 -  
243 // 1.2 更新 PayRefundDO 247 // 1.2 更新 PayRefundDO
244 PayRefundDO updateRefundObj = new PayRefundDO() 248 PayRefundDO updateRefundObj = new PayRefundDO()
245 .setSuccessTime(notify.getSuccessTime()) 249 .setSuccessTime(notify.getSuccessTime())
@@ -250,17 +254,46 @@ public class PayRefundServiceImpl implements PayRefundService { @@ -250,17 +254,46 @@ public class PayRefundServiceImpl implements PayRefundService {
250 if (updateCounts == 0) { // 校验状态,必须是等待状态 254 if (updateCounts == 0) { // 校验状态,必须是等待状态
251 throw exception(ErrorCodeConstants.REFUND_STATUS_IS_NOT_WAITING); 255 throw exception(ErrorCodeConstants.REFUND_STATUS_IS_NOT_WAITING);
252 } 256 }
  257 + log.info("[notifyRefundSuccess][退款订单({}) 更新为退款成功]", refund.getId());
253 258
254 // 2. 更新订单 259 // 2. 更新订单
255 orderService.updateOrderRefundPrice(refund.getOrderId(), refund.getRefundPrice()); 260 orderService.updateOrderRefundPrice(refund.getOrderId(), refund.getRefundPrice());
256 261
257 - // 3. 插入退款通知记录 262 + // 3. 插入退款通知记录 TODO 芋艿:退款成功
258 notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder() 263 notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder()
259 .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build()); 264 .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build());
260 } 265 }
261 266
262 - private void notifyRefundFailure(PayChannelDO channel, PayRefundRespDTO notify) {  
263 - // TODO 芋艿:未实现 267 + @Transactional(rollbackFor = Exception.class)
  268 + public void notifyRefundFailure(PayChannelDO channel, PayRefundRespDTO notify) {
  269 + // 1.1 查询 PayRefundDO
  270 + PayRefundDO refund = refundMapper.selectByAppIdAndNo(
  271 + channel.getAppId(), notify.getOutRefundNo());
  272 + if (refund == null) {
  273 + throw exception(ErrorCodeConstants.REFUND_NOT_FOUND);
  274 + }
  275 + if (PayRefundStatusEnum.isFailure(refund.getStatus())) { // 如果已经是成功,直接返回,不用重复更新
  276 + log.info("[notifyRefundSuccess][退款订单({}) 已经是退款关闭,无需更新]", refund.getId());
  277 + return;
  278 + }
  279 + if (!PayRefundStatusEnum.WAITING.getStatus().equals(refund.getStatus())) {
  280 + throw exception(ErrorCodeConstants.REFUND_STATUS_IS_NOT_WAITING);
  281 + }
  282 + // 1.2 更新 PayRefundDO
  283 + PayRefundDO updateRefundObj = new PayRefundDO()
  284 + .setChannelRefundNo(notify.getChannelRefundNo())
  285 + .setStatus(PayRefundStatusEnum.FAILURE.getStatus())
  286 + .setChannelNotifyData(toJsonString(notify))
  287 + .setChannelErrorCode(notify.getChannelErrorCode()).setChannelErrorMsg(notify.getChannelErrorMsg());
  288 + int updateCounts = refundMapper.updateByIdAndStatus(refund.getId(), refund.getStatus(), updateRefundObj);
  289 + if (updateCounts == 0) { // 校验状态,必须是等待状态
  290 + throw exception(ErrorCodeConstants.REFUND_STATUS_IS_NOT_WAITING);
  291 + }
  292 + log.info("[notifyRefundFailure][退款订单({}) 更新为退款失败]", refund.getId());
  293 +
  294 + // 2. 插入退款通知记录 TODO 芋艿:退款失败
  295 + notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder()
  296 + .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build());
264 } 297 }
265 298
266 } 299 }