diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/notify/PayNotifyLogDO.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/notify/PayNotifyLogDO.java index 80ed5b017..85626006c 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/notify/PayNotifyLogDO.java +++ b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/notify/PayNotifyLogDO.java @@ -3,9 +3,7 @@ package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.notify; import cn.iocoder.yudao.coreservice.modules.pay.enums.notify.PayNotifyStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Accessors; +import lombok.*; /** * 商户支付、退款等的通知 Log @@ -16,7 +14,9 @@ import lombok.experimental.Accessors; @TableName("pay_notify_log") @Data @EqualsAndHashCode(callSuper = true) -@Accessors(chain = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor public class PayNotifyLogDO extends BaseDO { /** @@ -24,13 +24,15 @@ public class PayNotifyLogDO extends BaseDO { */ private Long id; /** - * 通知编号 + * 通知任务编号 * * 关联 {@link PayNotifyTaskDO#getId()} */ - private Long notifyId; + private Long taskId; /** - * 当前通知次数 + * 第几次被通知 + * + * 对应到 {@link PayNotifyTaskDO#getNotifyTimes()} */ private Integer notifyTimes; /** diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/notify/PayNotifyLogCoreMapper.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/notify/PayNotifyLogCoreMapper.java new file mode 100644 index 000000000..e3f90d614 --- /dev/null +++ b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/notify/PayNotifyLogCoreMapper.java @@ -0,0 +1,9 @@ +package cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.notify; + +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.notify.PayNotifyLogDO; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface PayNotifyLogCoreMapper extends BaseMapperX { +} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/notify/impl/PayNotifyCoreServiceImpl.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/notify/impl/PayNotifyCoreServiceImpl.java index 77a500a37..4e7b91547 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/notify/impl/PayNotifyCoreServiceImpl.java +++ b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/notify/impl/PayNotifyCoreServiceImpl.java @@ -2,8 +2,10 @@ package cn.iocoder.yudao.coreservice.modules.pay.service.notify.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.http.HttpUtil; +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.notify.PayNotifyLogDO; import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.notify.PayNotifyTaskDO; import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; +import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.notify.PayNotifyLogCoreMapper; import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.notify.PayNotifyTaskCoreMapper; import cn.iocoder.yudao.coreservice.modules.pay.dal.redis.notify.PayNotifyLockCoreRedisDAO; import cn.iocoder.yudao.coreservice.modules.pay.enums.notify.PayNotifyStatusEnum; @@ -25,12 +27,14 @@ import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import javax.validation.Valid; +import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Objects; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import static cn.hutool.core.exceptions.ExceptionUtil.getRootCauseMessage; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.SECOND_MILLIS; import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; @@ -59,6 +63,8 @@ public class PayNotifyCoreServiceImpl implements PayNotifyCoreService { @Resource private PayNotifyTaskCoreMapper payNotifyTaskCoreMapper; + @Resource + private PayNotifyLogCoreMapper payNotifyLogCoreMapper; @Resource private ThreadPoolTaskExecutor threadPoolTaskExecutor; // TODO 芋艿:未来提供独立的线程池 @@ -105,7 +111,7 @@ public class PayNotifyCoreServiceImpl implements PayNotifyCoreService { CountDownLatch latch = new CountDownLatch(tasks.size()); tasks.forEach(task -> threadPoolTaskExecutor.execute(() -> { try { - executeNotify(task); + executeNotifySync(task); } finally { latch.countDown(); } @@ -141,7 +147,7 @@ public class PayNotifyCoreServiceImpl implements PayNotifyCoreService { */ @Async public void executeNotifyAsync(PayNotifyTaskDO task) { - self.executeNotify(task); // 使用 self,避免事务不发起 + self.executeNotifySync(task); // 使用 self,避免事务不发起 } /** @@ -149,7 +155,7 @@ public class PayNotifyCoreServiceImpl implements PayNotifyCoreService { * * @param task 通知任务 */ - public void executeNotify(PayNotifyTaskDO task) { + public void executeNotifySync(PayNotifyTaskDO task) { // 分布式锁,避免并发问题 payNotifyLockCoreRedisDAO.lock(task.getId(), NOTIFY_TIMEOUT_MILLIS, () -> { // 校验,当前任务是否已经被通知过 @@ -161,12 +167,12 @@ public class PayNotifyCoreServiceImpl implements PayNotifyCoreService { } // 执行通知 - executeNotify0(dbTask); + executeNotify(dbTask); }); } @Transactional - public void executeNotify0(PayNotifyTaskDO task) { + public void executeNotify(PayNotifyTaskDO task) { // 发起回调 CommonResult invokeResult = null; Throwable invokeException = null; @@ -176,19 +182,13 @@ public class PayNotifyCoreServiceImpl implements PayNotifyCoreService { invokeException = e; } - // 设置通用的更新 PayNotifyTaskDO 的字段 - PayNotifyTaskDO updateTask = new PayNotifyTaskDO() - .setId(task.getId()) - .setLastExecuteTime(new Date()) - .setNotifyTimes(task.getNotifyTimes() + 1); - - // 情况一:调用成功 - - // 情况二:调用失败 - - // 调用三:调用异常 + // 处理 + Integer newStatus = this.processNotifyResult(task, invokeResult, invokeException); // 记录 PayNotifyLog 日志 + String response = invokeException != null ? getRootCauseMessage(invokeException) : toJsonString(invokeResult); + payNotifyLogCoreMapper.insert(PayNotifyLogDO.builder().taskId(task.getId()) + .notifyTimes(task.getNotifyTimes() + 1).status(newStatus).response(response).build()); } /** @@ -216,4 +216,41 @@ public class PayNotifyCoreServiceImpl implements PayNotifyCoreService { return JsonUtils.parseObject(response, CommonResult.class); } + /** + * 处理并更新通知结果 + * + * @param task 通知任务 + * @param invokeResult 通知结果 + * @param invokeException 通知异常 + * @return 最终任务的状态 + */ + private Integer processNotifyResult(PayNotifyTaskDO task, CommonResult invokeResult, Throwable invokeException) { + // 设置通用的更新 PayNotifyTaskDO 的字段 + PayNotifyTaskDO updateTask = new PayNotifyTaskDO() + .setId(task.getId()) + .setLastExecuteTime(new Date()) + .setNotifyTimes(task.getNotifyTimes() + 1); + + // 情况一:调用成功 + if (invokeResult != null && invokeResult.isSuccess()) { + updateTask.setStatus(PayNotifyStatusEnum.SUCCESS.getStatus()); + return updateTask.getStatus(); + } + // 情况二:调用失败、调用异常 + // 2.1 超过最大回调次数 + if (updateTask.getNotifyTimes() >= PayNotifyTaskDO.NOTIFY_FREQUENCY.length) { + updateTask.setStatus(PayNotifyStatusEnum.FAILURE.getStatus()); + return updateTask.getStatus(); + } + // 2.2 未超过最大回调次数 + updateTask.setNextNotifyTime(DateUtils.addDate(Calendar.SECOND, PayNotifyTaskDO.NOTIFY_FREQUENCY[updateTask.getNotifyTimes()])); + updateTask.setStatus(invokeException != null ? PayNotifyStatusEnum.REQUEST_FAILURE.getStatus() + : PayNotifyStatusEnum.REQUEST_SUCCESS.getStatus()); + return updateTask.getStatus(); + } + + private void processNotifySuccess(PayNotifyTaskDO task, PayNotifyTaskDO updateTask) { + payNotifyTaskCoreMapper.updateById(updateTask); + } + } diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java index b90673e90..d508c6ced 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java @@ -89,4 +89,35 @@ public class DateUtils { return date.getTime() >= System.currentTimeMillis(); } + /** + * 计算当期时间相差的日期 + * + * @param field 日历字段.
eg:Calendar.MONTH,Calendar.DAY_OF_MONTH,
Calendar.HOUR_OF_DAY等. + * @param amount 相差的数值 + * @return 计算后的日志 + */ + public static Date addDate(int field, int amount) { + return addDate(null, field, amount); + } + + /** + * 计算当期时间相差的日期 + * + * @param date 设置时间 + * @param field 日历字段 例如说,{@link Calendar#DAY_OF_MONTH} 等 + * @param amount 相差的数值 + * @return 计算后的日志 + */ + public static Date addDate(Date date, int field, int amount) { + if (amount == 0) { + return date; + } + Calendar c = Calendar.getInstance(); + if (date != null) { + c.setTime(date); + } + c.add(field, amount); + return c.getTime(); + } + }