mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-27 01:32:03 +08:00
1. 优化支付订单回调任务,避免重复打 SQL 查询日志
2. 修复定时任务的回调,回调成功未更新状态的问题。
This commit is contained in:
parent
44b0346e5e
commit
96ecd5028d
@ -48,7 +48,7 @@ public class PayDemoOrderController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/update-paid")
|
@PostMapping("/update-paid")
|
||||||
@Operation(description = "更新示例订单为已支付") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob
|
@Operation(summary = "更新示例订单为已支付") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob
|
||||||
@PermitAll // 无需登录,安全由 PayDemoOrderService 内部校验实现
|
@PermitAll // 无需登录,安全由 PayDemoOrderService 内部校验实现
|
||||||
@OperateLog(enable = false) // 禁用操作日志,因为没有操作人
|
@OperateLog(enable = false) // 禁用操作日志,因为没有操作人
|
||||||
public CommonResult<Boolean> updateDemoOrderPaid(@RequestBody PayOrderNotifyReqDTO notifyReqDTO) {
|
public CommonResult<Boolean> updateDemoOrderPaid(@RequestBody PayOrderNotifyReqDTO notifyReqDTO) {
|
||||||
@ -58,7 +58,7 @@ public class PayDemoOrderController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/refund")
|
@PutMapping("/refund")
|
||||||
@Operation(description = "发起示例订单的退款")
|
@Operation(summary = "发起示例订单的退款")
|
||||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||||
public CommonResult<Boolean> refundDemoOrder(@RequestParam("id") Long id) {
|
public CommonResult<Boolean> refundDemoOrder(@RequestParam("id") Long id) {
|
||||||
payDemoOrderService.refundDemoOrder(id, getClientIP());
|
payDemoOrderService.refundDemoOrder(id, getClientIP());
|
||||||
@ -66,7 +66,7 @@ public class PayDemoOrderController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/update-refunded")
|
@PostMapping("/update-refunded")
|
||||||
@Operation(description = "更新示例订单为已退款") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob
|
@Operation(summary = "更新示例订单为已退款") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob
|
||||||
@PermitAll // 无需登录,安全由 PayDemoOrderService 内部校验实现
|
@PermitAll // 无需登录,安全由 PayDemoOrderService 内部校验实现
|
||||||
@OperateLog(enable = false) // 禁用操作日志,因为没有操作人
|
@OperateLog(enable = false) // 禁用操作日志,因为没有操作人
|
||||||
public CommonResult<Boolean> updateDemoOrderRefunded(@RequestBody PayRefundNotifyReqDTO notifyReqDTO) {
|
public CommonResult<Boolean> updateDemoOrderRefunded(@RequestBody PayRefundNotifyReqDTO notifyReqDTO) {
|
||||||
|
@ -5,5 +5,5 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
|||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface PayNotifyLogCoreMapper extends BaseMapperX<PayNotifyLogDO> {
|
public interface PayNotifyLogMapper extends BaseMapperX<PayNotifyLogDO> {
|
||||||
}
|
}
|
@ -10,7 +10,7 @@ import java.time.LocalDateTime;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface PayNotifyTaskCoreMapper extends BaseMapperX<PayNotifyTaskDO> {
|
public interface PayNotifyTaskMapper extends BaseMapperX<PayNotifyTaskDO> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得需要通知的 PayNotifyTaskDO 记录。需要满足如下条件:
|
* 获得需要通知的 PayNotifyTaskDO 记录。需要满足如下条件:
|
@ -13,8 +13,8 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO;
|
|||||||
import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO;
|
import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO;
|
||||||
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
|
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
|
||||||
import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
|
import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
|
||||||
import cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyLogCoreMapper;
|
import cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyLogMapper;
|
||||||
import cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskCoreMapper;
|
import cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskMapper;
|
||||||
import cn.iocoder.yudao.module.pay.dal.redis.notify.PayNotifyLockRedisDAO;
|
import cn.iocoder.yudao.module.pay.dal.redis.notify.PayNotifyLockRedisDAO;
|
||||||
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum;
|
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum;
|
||||||
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum;
|
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum;
|
||||||
@ -32,6 +32,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
import java.time.Duration;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -40,6 +41,7 @@ import java.util.Objects;
|
|||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
|
||||||
import static cn.iocoder.yudao.module.pay.framework.job.config.PayJobConfiguration.NOTIFY_THREAD_POOL_TASK_EXECUTOR;
|
import static cn.iocoder.yudao.module.pay.framework.job.config.PayJobConfiguration.NOTIFY_THREAD_POOL_TASK_EXECUTOR;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -69,9 +71,9 @@ public class PayNotifyServiceImpl implements PayNotifyService {
|
|||||||
private PayRefundService refundService;
|
private PayRefundService refundService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private PayNotifyTaskCoreMapper payNotifyTaskCoreMapper;
|
private PayNotifyTaskMapper payNotifyTaskMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private PayNotifyLogCoreMapper payNotifyLogCoreMapper;
|
private PayNotifyLogMapper payNotifyLogMapper;
|
||||||
|
|
||||||
@Resource(name = NOTIFY_THREAD_POOL_TASK_EXECUTOR)
|
@Resource(name = NOTIFY_THREAD_POOL_TASK_EXECUTOR)
|
||||||
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
|
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
|
||||||
@ -101,7 +103,7 @@ public class PayNotifyServiceImpl implements PayNotifyService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 执行插入
|
// 执行插入
|
||||||
payNotifyTaskCoreMapper.insert(task);
|
payNotifyTaskMapper.insert(task);
|
||||||
|
|
||||||
// 异步直接发起任务。虽然会有定时任务扫描,但是会导致延迟
|
// 异步直接发起任务。虽然会有定时任务扫描,但是会导致延迟
|
||||||
self.executeNotifyAsync(task);
|
self.executeNotifyAsync(task);
|
||||||
@ -110,7 +112,7 @@ public class PayNotifyServiceImpl implements PayNotifyService {
|
|||||||
@Override
|
@Override
|
||||||
public int executeNotify() throws InterruptedException {
|
public int executeNotify() throws InterruptedException {
|
||||||
// 获得需要通知的任务
|
// 获得需要通知的任务
|
||||||
List<PayNotifyTaskDO> tasks = payNotifyTaskCoreMapper.selectListByNotify();
|
List<PayNotifyTaskDO> tasks = payNotifyTaskMapper.selectListByNotify();
|
||||||
if (CollUtil.isEmpty(tasks)) {
|
if (CollUtil.isEmpty(tasks)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -168,8 +170,8 @@ public class PayNotifyServiceImpl implements PayNotifyService {
|
|||||||
payNotifyLockCoreRedisDAO.lock(task.getId(), NOTIFY_TIMEOUT_MILLIS, () -> {
|
payNotifyLockCoreRedisDAO.lock(task.getId(), NOTIFY_TIMEOUT_MILLIS, () -> {
|
||||||
// 校验,当前任务是否已经被通知过
|
// 校验,当前任务是否已经被通知过
|
||||||
// 虽然已经通过分布式加锁,但是可能同时满足通知的条件,然后都去获得锁。此时,第一个执行完后,第二个还是能拿到锁,然后会再执行一次。
|
// 虽然已经通过分布式加锁,但是可能同时满足通知的条件,然后都去获得锁。此时,第一个执行完后,第二个还是能拿到锁,然后会再执行一次。
|
||||||
PayNotifyTaskDO dbTask = payNotifyTaskCoreMapper.selectById(task.getId());
|
PayNotifyTaskDO dbTask = payNotifyTaskMapper.selectById(task.getId());
|
||||||
if (LocalDateTimeUtils.afterNow(dbTask.getNextNotifyTime())) {
|
if (afterNow(dbTask.getNextNotifyTime())) {
|
||||||
log.info("[executeNotifySync][dbTask({}) 任务被忽略,原因是未到达下次通知时间,可能是因为并发执行了]",
|
log.info("[executeNotifySync][dbTask({}) 任务被忽略,原因是未到达下次通知时间,可能是因为并发执行了]",
|
||||||
JsonUtils.toJsonString(dbTask));
|
JsonUtils.toJsonString(dbTask));
|
||||||
return;
|
return;
|
||||||
@ -197,7 +199,7 @@ public class PayNotifyServiceImpl implements PayNotifyService {
|
|||||||
// 记录 PayNotifyLog 日志
|
// 记录 PayNotifyLog 日志
|
||||||
String response = invokeException != null ? ExceptionUtil.getRootCauseMessage(invokeException) :
|
String response = invokeException != null ? ExceptionUtil.getRootCauseMessage(invokeException) :
|
||||||
JsonUtils.toJsonString(invokeResult);
|
JsonUtils.toJsonString(invokeResult);
|
||||||
payNotifyLogCoreMapper.insert(PayNotifyLogDO.builder().taskId(task.getId())
|
payNotifyLogMapper.insert(PayNotifyLogDO.builder().taskId(task.getId())
|
||||||
.notifyTimes(task.getNotifyTimes() + 1).status(newStatus).response(response).build());
|
.notifyTimes(task.getNotifyTimes() + 1).status(newStatus).response(response).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,23 +252,22 @@ public class PayNotifyServiceImpl implements PayNotifyService {
|
|||||||
// 情况一:调用成功
|
// 情况一:调用成功
|
||||||
if (invokeResult != null && invokeResult.isSuccess()) {
|
if (invokeResult != null && invokeResult.isSuccess()) {
|
||||||
updateTask.setStatus(PayNotifyStatusEnum.SUCCESS.getStatus());
|
updateTask.setStatus(PayNotifyStatusEnum.SUCCESS.getStatus());
|
||||||
|
payNotifyTaskMapper.updateById(updateTask);
|
||||||
return updateTask.getStatus();
|
return updateTask.getStatus();
|
||||||
}
|
}
|
||||||
// 情况二:调用失败、调用异常
|
// 情况二:调用失败、调用异常
|
||||||
// 2.1 超过最大回调次数
|
// 2.1 超过最大回调次数
|
||||||
if (updateTask.getNotifyTimes() >= PayNotifyTaskDO.NOTIFY_FREQUENCY.length) {
|
if (updateTask.getNotifyTimes() >= PayNotifyTaskDO.NOTIFY_FREQUENCY.length) {
|
||||||
updateTask.setStatus(PayNotifyStatusEnum.FAILURE.getStatus());
|
updateTask.setStatus(PayNotifyStatusEnum.FAILURE.getStatus());
|
||||||
|
payNotifyTaskMapper.updateById(updateTask);
|
||||||
return updateTask.getStatus();
|
return updateTask.getStatus();
|
||||||
}
|
}
|
||||||
// 2.2 未超过最大回调次数
|
// 2.2 未超过最大回调次数
|
||||||
updateTask.setNextNotifyTime(LocalDateTime.now().plusSeconds(PayNotifyTaskDO.NOTIFY_FREQUENCY[updateTask.getNotifyTimes()]));
|
updateTask.setNextNotifyTime(addTime(Duration.ofSeconds(PayNotifyTaskDO.NOTIFY_FREQUENCY[updateTask.getNotifyTimes()])));
|
||||||
updateTask.setStatus(invokeException != null ? PayNotifyStatusEnum.REQUEST_FAILURE.getStatus()
|
updateTask.setStatus(invokeException != null ? PayNotifyStatusEnum.REQUEST_FAILURE.getStatus()
|
||||||
: PayNotifyStatusEnum.REQUEST_SUCCESS.getStatus());
|
: PayNotifyStatusEnum.REQUEST_SUCCESS.getStatus());
|
||||||
|
payNotifyTaskMapper.updateById(updateTask);
|
||||||
return updateTask.getStatus();
|
return updateTask.getStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processNotifySuccess(PayNotifyTaskDO task, PayNotifyTaskDO updateTask) {
|
|
||||||
payNotifyTaskCoreMapper.updateById(updateTask);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -153,6 +153,7 @@ logging:
|
|||||||
cn.iocoder.yudao.module.infra.dal.mysql: debug
|
cn.iocoder.yudao.module.infra.dal.mysql: debug
|
||||||
cn.iocoder.yudao.module.infra.dal.mysql.job.JobLogMapper: INFO # 配置 JobLogMapper 的日志级别为 info
|
cn.iocoder.yudao.module.infra.dal.mysql.job.JobLogMapper: INFO # 配置 JobLogMapper 的日志级别为 info
|
||||||
cn.iocoder.yudao.module.pay.dal.mysql: debug
|
cn.iocoder.yudao.module.pay.dal.mysql: debug
|
||||||
|
cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskMapper: INFO # 配置 JobLogMapper 的日志级别为 info
|
||||||
cn.iocoder.yudao.module.system.dal.mysql: debug
|
cn.iocoder.yudao.module.system.dal.mysql: debug
|
||||||
cn.iocoder.yudao.module.tool.dal.mysql: debug
|
cn.iocoder.yudao.module.tool.dal.mysql: debug
|
||||||
cn.iocoder.yudao.module.member.dal.mysql: debug
|
cn.iocoder.yudao.module.member.dal.mysql: debug
|
||||||
|
Loading…
Reference in New Issue
Block a user