完成支付通知的逻辑

pull/2/head
YunaiV 2021-10-27 13:22:49 +08:00
parent 2df46a7c2d
commit c89accbf06
4 changed files with 102 additions and 23 deletions

View File

@ -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.coreservice.modules.pay.enums.notify.PayNotifyStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.*;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/** /**
* 退 Log * 退 Log
@ -16,7 +14,9 @@ import lombok.experimental.Accessors;
@TableName("pay_notify_log") @TableName("pay_notify_log")
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@Accessors(chain = true) @Builder
@NoArgsConstructor
@AllArgsConstructor
public class PayNotifyLogDO extends BaseDO { public class PayNotifyLogDO extends BaseDO {
/** /**
@ -24,13 +24,15 @@ public class PayNotifyLogDO extends BaseDO {
*/ */
private Long id; private Long id;
/** /**
* *
* *
* {@link PayNotifyTaskDO#getId()} * {@link PayNotifyTaskDO#getId()}
*/ */
private Long notifyId; private Long taskId;
/** /**
* *
*
* {@link PayNotifyTaskDO#getNotifyTimes()}
*/ */
private Integer notifyTimes; private Integer notifyTimes;
/** /**

View File

@ -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<PayNotifyLogDO> {
}

View File

@ -2,8 +2,10 @@ package cn.iocoder.yudao.coreservice.modules.pay.service.notify.impl;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.http.HttpUtil; 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.notify.PayNotifyTaskDO;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; 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.mysql.notify.PayNotifyTaskCoreMapper;
import cn.iocoder.yudao.coreservice.modules.pay.dal.redis.notify.PayNotifyLockCoreRedisDAO; import cn.iocoder.yudao.coreservice.modules.pay.dal.redis.notify.PayNotifyLockCoreRedisDAO;
import cn.iocoder.yudao.coreservice.modules.pay.enums.notify.PayNotifyStatusEnum; 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.annotation.Resource;
import javax.validation.Valid; import javax.validation.Valid;
import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Objects; 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.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.date.DateUtils.SECOND_MILLIS;
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
@ -59,6 +63,8 @@ public class PayNotifyCoreServiceImpl implements PayNotifyCoreService {
@Resource @Resource
private PayNotifyTaskCoreMapper payNotifyTaskCoreMapper; private PayNotifyTaskCoreMapper payNotifyTaskCoreMapper;
@Resource
private PayNotifyLogCoreMapper payNotifyLogCoreMapper;
@Resource @Resource
private ThreadPoolTaskExecutor threadPoolTaskExecutor; // TODO 芋艿:未来提供独立的线程池 private ThreadPoolTaskExecutor threadPoolTaskExecutor; // TODO 芋艿:未来提供独立的线程池
@ -105,7 +111,7 @@ public class PayNotifyCoreServiceImpl implements PayNotifyCoreService {
CountDownLatch latch = new CountDownLatch(tasks.size()); CountDownLatch latch = new CountDownLatch(tasks.size());
tasks.forEach(task -> threadPoolTaskExecutor.execute(() -> { tasks.forEach(task -> threadPoolTaskExecutor.execute(() -> {
try { try {
executeNotify(task); executeNotifySync(task);
} finally { } finally {
latch.countDown(); latch.countDown();
} }
@ -141,7 +147,7 @@ public class PayNotifyCoreServiceImpl implements PayNotifyCoreService {
*/ */
@Async @Async
public void executeNotifyAsync(PayNotifyTaskDO task) { public void executeNotifyAsync(PayNotifyTaskDO task) {
self.executeNotify(task); // 使用 self避免事务不发起 self.executeNotifySync(task); // 使用 self避免事务不发起
} }
/** /**
@ -149,7 +155,7 @@ public class PayNotifyCoreServiceImpl implements PayNotifyCoreService {
* *
* @param task * @param task
*/ */
public void executeNotify(PayNotifyTaskDO task) { public void executeNotifySync(PayNotifyTaskDO task) {
// 分布式锁,避免并发问题 // 分布式锁,避免并发问题
payNotifyLockCoreRedisDAO.lock(task.getId(), NOTIFY_TIMEOUT_MILLIS, () -> { payNotifyLockCoreRedisDAO.lock(task.getId(), NOTIFY_TIMEOUT_MILLIS, () -> {
// 校验,当前任务是否已经被通知过 // 校验,当前任务是否已经被通知过
@ -161,12 +167,12 @@ public class PayNotifyCoreServiceImpl implements PayNotifyCoreService {
} }
// 执行通知 // 执行通知
executeNotify0(dbTask); executeNotify(dbTask);
}); });
} }
@Transactional @Transactional
public void executeNotify0(PayNotifyTaskDO task) { public void executeNotify(PayNotifyTaskDO task) {
// 发起回调 // 发起回调
CommonResult<?> invokeResult = null; CommonResult<?> invokeResult = null;
Throwable invokeException = null; Throwable invokeException = null;
@ -176,19 +182,13 @@ public class PayNotifyCoreServiceImpl implements PayNotifyCoreService {
invokeException = e; invokeException = e;
} }
// 设置通用的更新 PayNotifyTaskDO 的字段 // 处理
PayNotifyTaskDO updateTask = new PayNotifyTaskDO() Integer newStatus = this.processNotifyResult(task, invokeResult, invokeException);
.setId(task.getId())
.setLastExecuteTime(new Date())
.setNotifyTimes(task.getNotifyTimes() + 1);
// 情况一:调用成功
// 情况二:调用失败
// 调用三:调用异常
// 记录 PayNotifyLog 日志 // 记录 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); 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);
}
} }

View File

@ -89,4 +89,35 @@ public class DateUtils {
return date.getTime() >= System.currentTimeMillis(); return date.getTime() >= System.currentTimeMillis();
} }
/**
*
*
* @param field .<br/>eg:Calendar.MONTH,Calendar.DAY_OF_MONTH,<br/>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();
}
} }