feat 通知消息功能收尾, 支付订单超时任务改为quartz定时任务方式

This commit is contained in:
bootx
2024-02-22 22:50:49 +08:00
parent 84d1c2f451
commit 133982ef03
14 changed files with 79 additions and 49 deletions

View File

@@ -37,15 +37,16 @@ public class PayOrderExtra extends MpBaseEntity implements EntityBaseFunction<Pa
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private String returnUrl;
/** 回调通知时是否需要进行签名, 以最后一次为准 */
@DbColumn(comment = "回调通知时是否需要进行签名")
private boolean noticeSign;
/** 异步通知地址 */
/** 异步通知地址 以最后一次为准 */
@DbColumn(comment = "异步通知地址,以最后一次为准")
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private String notifyUrl;
/** 商户扩展参数,回调时会原样返回 */
/** 商户扩展参数,回调时会原样返回 以最后一次为准 */
@DbColumn(comment = "商户扩展参数")
private String attach;
@@ -57,24 +58,18 @@ public class PayOrderExtra extends MpBaseEntity implements EntityBaseFunction<Pa
@DbColumn(comment = "签名")
private String reqSign;
/** 商户扩展参数,回调时会原样返回 */
@DbColumn(comment = "商户扩展参数")
private String attach;
/** 请求时间,时间戳转时间, 以最后一次为准 */
@DbColumn(comment = "请求时间,传输时间戳,以最后一次为准")
private LocalDateTime reqTime;
/** 支付终端ip */
/** 支付终端ip 以最后一次为准 */
@DbColumn(comment = "支付终端ip")
private String clientIp;
/** 请求链路ID */
/** 请求链路ID 以最后一次为准 */
@DbColumn(comment = "请求链路ID")
private String reqId;
/** 错误码 */
@DbColumn(comment = "错误码")
private String errorCode;

View File

@@ -3,7 +3,7 @@ package cn.bootx.platform.daxpay.service.core.order.pay.service;
import cn.bootx.platform.daxpay.code.PayStatusEnum;
import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayOrderManager;
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
import cn.bootx.platform.daxpay.service.core.timeout.service.PayExpiredTimeService;
import cn.bootx.platform.daxpay.service.core.payment.pay.service.PayExpiredTimeService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

View File

@@ -7,22 +7,24 @@ import lombok.Data;
import lombok.experimental.Accessors;
/**
* 支付通道参数
* 支付通道信息
* @author xxm
* @since 2024/1/7
*/
@Data
@Accessors(chain = true)
@Schema(title = "支付通道参数")
@Schema(title = "支付通道信息")
public class PayChannelResult {
/**
* 支付通道编码
* @see PayChannelEnum#getCode()
*/
@Schema(description = "支付通道编码")
private String channel;
/**
* @see PayWayEnum#getCode()
* 支付方式编码
* @see PayWayEnum
*/
@Schema(description = "支付方式编码")
private String way;

View File

@@ -334,7 +334,7 @@ public class ClientNoticeService {
task.setSendCount(task.getSendCount() + 1);
// 判断发送次数是否未超过15次, 注册任务到redis中
if (task.getSendCount() < 16){
// 根据当前次数和时间计算出毫秒值
// 根据当前次数和时间计算出毫秒值, 然后写入到Redis中
Integer delay = DELAY_TIME.get(task.getSendCount());
long taskTime = LocalDateTimeUtil.timestamp(now) + delay;
redisClient.zadd(KEY, String.valueOf(task.getId()), taskTime);

View File

@@ -1,4 +1,4 @@
package cn.bootx.platform.daxpay.service.core.timeout.dao;
package cn.bootx.platform.daxpay.service.core.payment.pay.dao;
import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
import cn.bootx.platform.common.redis.RedisClient;

View File

@@ -6,10 +6,7 @@ import cn.bootx.platform.daxpay.code.PayChannelEnum;
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
import cn.bootx.platform.daxpay.param.pay.PayChannelParam;
import cn.bootx.platform.daxpay.param.pay.PayParam;
import cn.bootx.platform.daxpay.service.common.context.ApiInfoLocal;
import cn.bootx.platform.daxpay.service.common.context.AsyncPayLocal;
import cn.bootx.platform.daxpay.service.common.context.NoticeLocal;
import cn.bootx.platform.daxpay.service.common.context.PlatformLocal;
import cn.bootx.platform.daxpay.service.common.context.*;
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
import cn.bootx.platform.daxpay.service.core.order.pay.builder.PayBuilder;
import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayChannelOrderManager;
@@ -163,6 +160,8 @@ public class PayAssistService {
*/
public PayOrderExtra updatePayOrderExtra(PayParam payParam,Long paymentId){
ApiInfoLocal apiInfo = PaymentContextLocal.get().getApiInfo();
RequestLocal requestInfo = PaymentContextLocal.get().getRequestInfo();
PlatformLocal platformInfo = PaymentContextLocal.get().getPlatformInfo();
PayOrderExtra payOrderExtra = payOrderExtraManager.findById(paymentId)
.orElseThrow(() -> new DataNotExistException("支付订单不存在"));
@@ -172,12 +171,14 @@ public class PayAssistService {
String returnUrl = noticeInfo.getReturnUrl();
payOrderExtra.setReqTime(payParam.getReqTime())
.setReqSignType(platformInfo.getSignType())
.setReqSign(payParam.getSign())
.setNotifyUrl(notifyUrl)
.setReturnUrl(returnUrl)
.setNoticeSign(apiInfo.isNoticeSign())
.setAttach(payParam.getAttach())
.setClientIp(payParam.getClientIp());
.setClientIp(payParam.getClientIp())
.setReqId(requestInfo.getReqId());
return payOrderExtraManager.updateById(payOrderExtra);
}

View File

@@ -1,10 +1,10 @@
package cn.bootx.platform.daxpay.service.core.timeout.service;
package cn.bootx.platform.daxpay.service.core.payment.pay.service;
import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
import cn.bootx.platform.common.spring.exception.RetryableException;
import cn.bootx.platform.daxpay.code.PayStatusEnum;
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
import cn.bootx.platform.daxpay.service.core.timeout.dao.PayExpiredTimeRepository;
import cn.bootx.platform.daxpay.service.core.payment.pay.dao.PayExpiredTimeRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.retry.annotation.Retryable;

View File

@@ -1,9 +1,9 @@
package cn.bootx.platform.daxpay.service.core.timeout.task;
package cn.bootx.platform.daxpay.service.core.payment.pay.task;
import cn.bootx.platform.common.core.exception.RepetitiveOperationException;
import cn.bootx.platform.daxpay.param.pay.PaySyncParam;
import cn.bootx.platform.daxpay.service.core.payment.pay.dao.PayExpiredTimeRepository;
import cn.bootx.platform.daxpay.service.core.payment.sync.service.PaySyncService;
import cn.bootx.platform.daxpay.service.core.timeout.dao.PayExpiredTimeRepository;
import com.baomidou.lock.LockInfo;
import com.baomidou.lock.LockTemplate;
import lombok.RequiredArgsConstructor;

View File

@@ -186,6 +186,7 @@ public class RefundAssistService {
RefundOrderExtra refundOrderExtra = this.createRefundOrderExtra(refundParam, refundOrder.getId());
refundChannelOrders.forEach(r->r.setRefundId(refundOrder.getId()));
refundOrderExtraManager.save(refundOrderExtra);
payRefundChannelOrderManager.saveAll(refundChannelOrders);
return refundOrderManager.save(refundOrder);
}

View File

@@ -7,7 +7,6 @@ import cn.bootx.platform.daxpay.service.code.PayRepairWayEnum;
import cn.bootx.platform.daxpay.service.code.PaymentTypeEnum;
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayChannelOrderManager;
import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayOrderExtraManager;
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder;
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
import cn.bootx.platform.daxpay.service.core.order.pay.service.PayOrderService;
@@ -49,8 +48,6 @@ public class PayRepairService {
private final PayRepairRecordService recordService;
private final PayOrderExtraManager payOrderExtraManager;
/**
* 修复支付单
*/
@@ -96,6 +93,12 @@ public class PayRepairService {
}
// 设置修复iD
repairResult.setRepairNo(IdUtil.getSnowflakeNextIdStr());
// 发送通知
List<PayChannelOrder> channelOrders = repairStrategies.stream()
.map(AbsPayRepairStrategy::getChannelOrder)
.collect(Collectors.toList());
clientNoticeService.registerPayNotice(order, null, channelOrders);
this.saveRecord(order, repairType, repairResult);
return repairResult;
}
@@ -128,11 +131,6 @@ public class PayRepairService {
// 读取支付网关中的时间
order.setPayTime(payTime);
payOrderService.updateById(order);
List<PayChannelOrder> channelOrders = strategies.stream()
.map(AbsPayRepairStrategy::getChannelOrder)
.collect(Collectors.toList());
// 发送通知
clientNoticeService.registerPayNotice(order, null, channelOrders);
}
/**

View File

@@ -99,6 +99,9 @@ public class RefundRepairService {
PayRepairRecord payRepairRecord = this.payRepairRecord(payOrder, repairType, repairResult);
// 退款修复记录
PayRepairRecord refundRepairRecord = this.refundRepairRecord(refundOrder, repairType, repairResult);
// 发送通知
clientNoticeService.registerRefundNotice(refundOrder, null, new ArrayList<>(refundChannelOrderMap.values()));
recordService.saveAllRecord(Arrays.asList(payRepairRecord, refundRepairRecord));
return repairResult;
}

View File

@@ -23,6 +23,7 @@ import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROT
public class CashPayRepairStrategy extends AbsPayRepairStrategy {
private final CashRecordService cashRecordService;
/**
* 策略标识
*/

View File

@@ -0,0 +1,36 @@
package cn.bootx.platform.daxpay.service.task;
import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
import cn.bootx.platform.daxpay.service.core.payment.notice.service.ClientNoticeService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* 消息通知任务
* @author xxm
* @since 2024/2/22
*/
@Slf4j
@Component
@DisallowConcurrentExecution
@PersistJobDataAfterExecution
@RequiredArgsConstructor
public class ClientNoticeTask implements Job {
private final ClientNoticeService clientNoticeService;
/**
* 通知任务执行
*/
@Override
public void execute(JobExecutionContext context){
// 获取当前时间, 然后查询当前时间及以前需要进行通知的消息
LocalDateTime now = LocalDateTime.now();
clientNoticeService.taskStart(0, LocalDateTimeUtil.timestamp(now));
}
}

View File

@@ -1,15 +1,16 @@
package cn.bootx.platform.daxpay.service.core.timeout.task;
package cn.bootx.platform.daxpay.service.task;
import cn.bootx.platform.daxpay.param.pay.PaySyncParam;
import cn.bootx.platform.daxpay.service.code.PayRepairSourceEnum;
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
import cn.bootx.platform.daxpay.service.core.payment.pay.dao.PayExpiredTimeRepository;
import cn.bootx.platform.daxpay.service.core.payment.sync.service.PaySyncService;
import cn.bootx.platform.daxpay.service.core.timeout.dao.PayExpiredTimeRepository;
import com.baomidou.lock.LockInfo;
import com.baomidou.lock.LockTemplate;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
@@ -17,27 +18,23 @@ import java.util.Objects;
import java.util.Set;
/**
*
* 支付超时处理
* @author xxm
* @since 2024/1/2
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class PayExpiredTimeTask {
public class PayExpiredTimeTask implements Job {
private final PayExpiredTimeRepository repository;
private final PaySyncService paySyncService;
private final LockTemplate lockTemplate;
/**
* 先使用定时任务实现, 五秒轮训一下
*
*/
@Scheduled(cron = "*/5 * * * * ?")
public void task(){
// log.debug("执行超时取消任务....");
@Override
public void execute(JobExecutionContext context) {
// 获取超时的任务Key
Set<String> expiredKeys = repository.getExpiredKeys(LocalDateTime.now());
for (String expiredKey : expiredKeys) {
LockInfo lock = lockTemplate.lock("payment:expired:" + expiredKey,10000,200);
@@ -62,10 +59,6 @@ public class PayExpiredTimeTask {
} finally {
lockTemplate.releaseLock(lock);
}
}
}
}