Xxl-Job实现订单30分钟未支付自动取消

数据库

配置文件

yaml 复制代码
xxl:
  job:
    admin:
      addresses: http://localhost:8080/xxl-job-admin/
      accessToken: default_token
      timeout: 30
    cookie: XXL_JOB_LOGIN_IDENTITY=
    executor:
      appname: springboot3
      address:
      ip:
      port: 9989
      logPath:
      logretentiondays: 10

配置xxlJob任务参数

java 复制代码
import lombok.Data;
import lombok.ToString;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

@Component
@PropertySource("classpath:xxl-job-info.properties")
@ConfigurationProperties(prefix = "xxl-job-info")
@Data
@ToString
public class XxlJobInfoVO {
    private String jobGroup;
    private String jobDesc;
    private String author;
    private String scheduleType;
    private String glueType;
    private String executorHandler;
    private String executorRouteStrategy;
    private String misfireStrategy;
    private String executorBlockStrategy;
    private String executorTimeout;
    private String executorFailRetryCount;
    private String glueRemark;
    private String triggerStatus;

}

xxl-job-info.properties

yaml 复制代码
# \u5B9A\u65F6\u5668\u7EC4
#这里需要根据自己的执行器改
xxl-job-info.jobGroup=5
# \u63CF\u8FF0
xxl-job-info.jobDesc=\u667A\u6167\u533B\u517B\u5EB7\u8BA2\u5355\u5B9A\u65F6\u53D6\u6D88\u652F\u4ED8
# \u521B\u5EFA\u8005
xxl-job-info.author=stx
# \u5B9A\u65F6\u5668\u7C7B\u578B
xxl-job-info.scheduleType=CRON
# glue\u7C7B\u578B
xxl-job-info.glueType=BEAN
# \u6267\u884C\u5668\u4EFB\u52A1handler
xxl-job-info.executorHandler=cancelPay
# \u6267\u884C\u5668\u8DEF\u7531\u7B56\u7565
xxl-job-info.executorRouteStrategy=FIRST
# \u8C03\u5EA6\u8FC7\u671F\u7B56\u7565
xxl-job-info.misfireStrategy=DO_NOTHING
# \u963B\u585E\u5904\u7406\u7B56\u7565
xxl-job-info.executorBlockStrategy=SERIAL_EXECUTION
# \u4EFB\u52A1\u6267\u884C\u8D85\u65F6\u65F6\u95F4\uFF0C\u5355\u4F4D\u79D2
xxl-job-info.executorTimeout=0
# \u5931\u8D25\u91CD\u8BD5\u6B21\u6570
xxl-job-info.executorFailRetryCount=0
# GLUE\u5907\u6CE8
xxl-job-info.glueRemark=GLUE\u4EE3\u7801\u521D\u59CB\u5316
# \u8C03\u5EA6\u72B6\u6001\uFF1A0-\u505C\u6B62\uFF0C1-\u8FD0\u884C
xxl-job-info.triggerStatus=1

CancelPayUtil

java 复制代码
@Component
//@RestController
public class CancelPayUtil {

    @Value("${xxl.job.cookie}")
    private String cookie;

    @Value("${xxl.job.admin.addresses}")
    private String xxlJobAdminAddr;

    @Autowired
    private XxlJobInfoVO xxlJobInfoVO;

    //@GetMapping("/removeCancelJob")
    public Boolean removeCancelJob(String jobId) {

        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        //设置为form方式
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.add("Cookie", cookie);
        MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
        map.add("id",jobId);
        HttpEntity<MultiValueMap<String, String>> requestb = new HttpEntity<MultiValueMap<String, String>>(map, headers);
        ResponseEntity<String> response = restTemplate.postForEntity(xxlJobAdminAddr + "/jobinfo/remove", requestb, String.class);
        String regionString = response.getBody();//获取请求体
        JSONObject jsonObject = JSONObject.parseObject(regionString,JSONObject.class);//将请求体转化为json格式
        String code = jsonObject.getString("code");
        if (!("200".equals(code))) {
            throw new IllegalArgumentException("xxl-job定时任务删除失败");
        }

        return true;

    }

    //@GetMapping("/uploadCancelJob")
    public String uploadCancelJob(String cron, String orderId) {
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        //设置为form方式
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.add("Cookie", cookie);
        MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
        map.add("jobGroup", xxlJobInfoVO.getJobGroup());
        map.add("jobDesc", xxlJobInfoVO.getJobDesc());
        map.add("author", xxlJobInfoVO.getAuthor());
        map.add("alarmEmail", "");
        map.add("scheduleType", xxlJobInfoVO.getScheduleType());
        map.add("scheduleConf", cron);
        map.add("cronGen_display", cron);
        map.add("schedule_conf_CRON", cron);
        map.add("schedule_conf_FIX_RATE", "");
        map.add("schedule_conf_FIX_DELAY", "");
        map.add("glueType", xxlJobInfoVO.getGlueType());
        map.add("executorHandler", xxlJobInfoVO.getExecutorHandler());
        map.add("executorParam", orderId);
        map.add("executorRouteStrategy", xxlJobInfoVO.getExecutorRouteStrategy());
        map.add("childJobId", "");
        map.add("misfireStrategy", xxlJobInfoVO.getMisfireStrategy());
        map.add("executorBlockStrategy", xxlJobInfoVO.getExecutorBlockStrategy());
        map.add("executorTimeout", xxlJobInfoVO.getExecutorTimeout());
        map.add("executorFailRetryCount", xxlJobInfoVO.getExecutorFailRetryCount());
        map.add("glueRemark", xxlJobInfoVO.getGlueRemark());
        map.add("glueSource", "");
        map.add("triggerStatus", xxlJobInfoVO.getTriggerStatus());
        HttpEntity<MultiValueMap<String, String>> requestb = new HttpEntity<MultiValueMap<String, String>>(map, headers);
        ResponseEntity<String> response = restTemplate.postForEntity(xxlJobAdminAddr + "/jobinfo/add", requestb, String.class);
        String regionString = response.getBody();//获取请求体
        JSONObject jsonObject = JSONObject.parseObject(regionString,JSONObject.class);//将请求体转化为json格式
        String code = jsonObject.getString("code");
        String jobId = jsonObject.getString("content");
        if (!("200".equals(code))) {
            throw new IllegalArgumentException("xxl-job定时任务创建失败");
        }
        return jobId;
    }
}

DateUtils

java 复制代码
public class DateUtils {


    public static String getLocalDateTimeToCron(long minutes){

        LocalDateTime localDateTime = LocalDateTime.now();

        LocalDateTime  plusMinLocalDateTime = localDateTime.plusMinutes(minutes);

        String cornExpress = plusMinLocalDateTime.format(DateTimeFormatter.ofPattern("ss mm HH dd MM ? yyyy"));

        return cornExpress;
    }

    public static String getDateToCron(Long time){

        // 示例
        /*
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.MINUTE, 30);
        SimpleDateFormat sdf = new SimpleDateFormat("ss mm HH dd MM ? yyyy");
        String cronExpression = sdf.format(calendar.getTime());
        System.out.println("Corn表达式:" + cronExpression);
        */

        SimpleDateFormat sdf = new SimpleDateFormat("ss mm HH dd MM ? yyyy");
        String cronExpression = sdf.format(time);
        return cronExpression;
    }


}

订单取消逻辑

java 复制代码
@Slf4j
@Component
public class OrderTimeOutJob {


    @Resource
    private IOrderInfoService orderInfoService;


    @XxlJob("cancelPay")
    public void job() {
        log.info(">>>>>>>>进入xxl-job定时任务执行方法");

        String orderNumber = XxlJobHelper.getJobParam();

        orderInfoService.update(
                Wrappers.<OrderInfo>lambdaUpdate()
                        .eq(OrderInfo::getOrderNumber, orderNumber)
                        .set(OrderInfo::getPayStatus,5)

        );

    }

}

定时任务创建逻辑

java 复制代码
@RestController
@RequestMapping("/orderInfo")
@Slf4j
public class OrderInfoController {

    @Resource
    private IOrderInfoService orderInfoService;
    @Resource
    private CancelPayUtil cancelPayUtil;

    @Resource
    private IOrderJobService orderJobService;

    @PostMapping("/saveOrderInfo")
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveOrderInfo(String orderNumber) {

        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setOrderNumber(orderNumber);

        boolean saveResultBoolean = orderInfoService.save(orderInfo);

        String localDateTimeToCron = DateUtils.getLocalDateTimeToCron(2);

        String jobId = cancelPayUtil.uploadCancelJob(localDateTimeToCron, orderNumber);

        Boolean jobIsExist = jobId.isEmpty() || jobId.equals("") ? false : true;

        if (jobIsExist){

            OrderJob orderJob = new OrderJob();
            orderJob.setOrderNumber(orderNumber);
            orderJob.setJobId(jobId);
            orderJobService.save(orderJob);
        }

        log.info(String.format("订单号: %s,订单取消时间: %s",orderNumber,localDateTimeToCron));

        return saveResultBoolean && jobIsExist;
    }



}

定时任务取消逻辑

java 复制代码
@RestController
@RequestMapping("/payInfo")
@Slf4j
public class PayController {


    @Resource
    private CancelPayUtil cancelPayUtil;
    @Resource
    private IOrderJobService orderJobService;

    @RequestMapping("/payInfo")
    public Boolean payInfo(String orderNumber) {


        //业务逻辑...

        //支付成功,取消定时任务
        LambdaQueryWrapper<OrderJob> jobLambdaQueryWrapper = new LambdaQueryWrapper<OrderJob>().eq(OrderJob::getOrderNumber, orderNumber);
        OrderJob orderJob = orderJobService.getOne(jobLambdaQueryWrapper);
        return cancelPayUtil.removeCancelJob(orderJob.getJobId());

    }


}
相关推荐
明洞日记2 小时前
【设计模式手册022】抽象工厂模式 - 创建产品家族
java·设计模式·抽象工厂模式
用户8307196840822 小时前
Spring Boot 多数据源与事务管理深度解析:从原理到实践
java·spring boot
Yiii_x2 小时前
基于多线程机制的技术应用与性能优化
java·经验分享·笔记
uup2 小时前
包装类的 “缓存陷阱”:Integer.valueOf (128) == 128 为何为 false?
java
小徐Chao努力2 小时前
Go语言核心知识点底层原理教程【Map的底层原理】
java·golang·哈希算法
后端小张2 小时前
【AI 学习】LangChain框架深度解析:从核心组件到企业级应用实战
java·人工智能·学习·langchain·tensorflow·gpt-3·ai编程
天天摸鱼的java工程师2 小时前
后端密码存储优化:BCrypt 与 Argon2 加密方案对比
java·后端
雨中飘荡的记忆2 小时前
Vavr:让Java拥抱函数式编程的利器
java
沈千秋.2 小时前
xss.pwnfunction.com闯关(1~6)
java·前端·xss