当前位置: 首页 > news >正文

完整版订单超时自动取消功能

        前几天对实习还是继续学习技术产生了抉择,问了一个前辈,他抛给我一个问题,怎么做15分钟订单自动取消,我说然后到时间之后,自动执行这个订单关闭业务,比如把锁了的库存给解开等等操作,然后在数据库里肯定要有体现,比如抖音,查我的订单内一块,在前段应该显示已过期,把支付的按钮变灰或者取消,支付的时候不能直接对库存进行操作,应该是支付模块调用订单模块调用库存模块。

        然后把理论予以实现,发现需要考虑的点还是有一些的。

功能架构

        该功能使用了三大模块解除耦合,保证高可用性,从高层到底层分别是支付模块->订单模块->商品模块,各司其职,支付模块主要负责支付,退款等相应功能;订单模块主要负责订单查询,订单创建,删除订单相关功能;商品模块主要负责商品上下架,补货,查货相关功能;是环环相扣的,支付模块通过操控订单实现支付,订单模块通过操控商品来实现订单创建等操作。

功能实现流程

        由于是全栈开发,本功能实现流程会涵盖前后端都有。由于管理模块,就是添加商品等等操作,在前端并没有实现,就先在数据库里加一些商品。sql如下:

 然后写一个接口获取商品列表,然后前端进行渲染,效果如下:

测试阶段,未接入微信支付等,但有字段标识,后期方便扩展,渲染的时候只需要有一点,判断支付类型,如果是钱支付就渲染成¥的形式,如果是积分就渲染成积分的形式。然后点击兑换会弹出一个弹出框如下:

 扩展一些信息也会变得非常简单,由于数据库里设置了两个字段一个是销售价(也就是优惠后的价格),一个是原价,直接在前端算出优惠金额即可。然后点击提交订单,就会向后端去发送一个创建的请求,java代码如下所示:

        // 这里先把订单持续事件设置成15秒// 1.1 先校验参数,看看该商品是否有库存CommonGoodPo good = goodMapper.queryGoodById(dto.getGoodId());if (good == null) return Result.error("已查询不到该商品");Boolean isPut = good.getIsPut();if (!isPut) return Result.error("无法对已下架的商品下订单");// 1.2 看看库存还够不够Boolean haveStore = good.getHaveStore();Integer store = good.getStore();if (haveStore && store <= 0) return Result.error("库存不足,无法下单");// 库存足就锁定一个库存if (haveStore) goodMapper.lockStore(good.getId());// 1.3 todo 如果有一个人只能买一单等等限制,可继续扩展// 2.1 然后就要生成订单的信息了,比如订单的id,这里起始应该使用杂乱的数字字母等作为id,图方便就直接使用自增id// 2.2 然后生成开始时间和结束时间LocalDateTime now = LocalDateTime.now();LocalDateTime end = LocalDateTime.now().plusMinutes(15); // 15分钟写死PopOrderVo popOrderVo = new PopOrderVo(null, good.getId(), now, end, 15 * 60, dto.getAccount());orderMapper.creatOrder(popOrderVo);// 3 准备对象,发送消息String mes = JSON.toJSONString(popOrderVo);sendDelayMessage(mes, 60 * 15, RabbitConstants.DELAY_ORDER_DEL_DIRECT_EXCHANGE, RabbitConstants.DELAY_ORDER_KEY);// 然后封装一下给前端,然后前端得到信息后,弹出弹出层,在我的订单里也可以找到该信息return Result.ok(popOrderVo);

 代码逻辑主要分为三部分,校验参数;然后去执行sql,就是向数据库的order表里去添加一条订单消息,并且要锁库存;最后向rabbitMQ里发一条延迟消息,这个是封装好的方法。到期执行的方法如下所示:

        log.error("我要开始喽!");// 把msg转成对象PopOrderVo popOrderVo = null;try {popOrderVo = JSON.parseObject(msg, PopOrderVo.class);} catch (Exception e) {throw new RuntimeException("请调用符合规定的api,类型转换错误,无法转换为PopOrderVo");}// 自动取消订单逻辑LocalDateTime now = LocalDateTime.now();Integer orderId = popOrderVo.getOrderId();Integer goodId = popOrderVo.getGoodId();// 修改订单状态orderMapper.finishOrder(orderId, now, ORDER_STATUS_OVERTIME);// 把锁了的库存释放goodMapper.unLockStore(goodId);log.error("我结束喽!");

就是去校验一下参数,然后去解锁库存,然后修改订单状态。

订单表如下所示:

然后在点击提交订单后,弹出支付页面,并有前端实现的倒计时。 

 然后会显示一些订单信息,倒计时到了之后,按钮会变成灰色,并无法点击,点击支付按钮后,进入到后端逻辑。代码如下:

    @Override@Transactionalpublic Result payOrder(PayOrderDto dto) {Integer orderId = dto.getOrderId();OrderPo orderInfo = orderMapper.getOrderInfo(orderId);Integer goodId = orderInfo.getGoodId();LocalDateTime now = LocalDateTime.now();CommonGoodPo good = goodMapper.queryGoodById(goodId);// 1 先需要校验参数// 1.1 看过没过期,如果现在的时间在截止时间之后,则证明过期了if (now.isAfter(orderInfo.getEndTime())) {return Result.error("该订单已经过期,请重新下单!");}// 1.2 看一下状态是不是待支付状态if (orderInfo.getStatus() != 0) return Result.error("该订单已被处理,请刷新重试");// 1.3 看余额够不够Boolean isEnough = payMapper.checkBalance(orderInfo.getAccount(), good.getSalePrice());// 2.1 如果不够,直接报错余额不足if (!isEnough) return Result.error("你的余额不足,无法完成支付");// 2.2 如果够,扣减余额payMapper.decreaseBalance(orderInfo.getAccount(), good.getSalePrice());// 2 需要进行三个方面的处理// 2.1 商品给增加销量等等goodMapper.increaseSales(goodId);// 2.2 设置订单状态,截至时间等orderMapper.finishOrder(orderId, now, ORDER_STATUS_SUCCESS);// 2.3 记录支付日志payMapper.logPay(good.getSalePrice(), good.getPayType(), orderInfo.getAccount(), now, goodId);
//        return null;return Result.ok("支付成功");}

支付逻辑比较简单,就是校验参数,但需要注意需要检验一下订单状态,因为可能因为网络问题等等,导致请求到后端的时候,出现时间延迟问题,出现状态已经不是待支付状态已经被修改的问题(处理幂等问题),余额不足问题,这时就不能再进行支付,要对订单进行一下处理。如果满足条件就进行sql操作。

然后在前端为了订单的丢失,又写了一个我的订单页面,如下所示:

可以根据不同的状态去筛选不同的订单列表,然后并可以在此页面完成支付。

至此本功能结束,使用的是rabbitMQ的延迟队列实现定时操作,也可以使用xxl-job,直接使用策略模式扩展一下即可,在复习专栏里有关于设计模式的文章和例子,后续有时间会讲一下定时操作策略的扩展。

 

相关文章:

完整版订单超时自动取消功能

前几天对实习还是继续学习技术产生了抉择&#xff0c;问了一个前辈&#xff0c;他抛给我一个问题&#xff0c;怎么做15分钟订单自动取消&#xff0c;我说然后到时间之后&#xff0c;自动执行这个订单关闭业务&#xff0c;比如把锁了的库存给解开等等操作&#xff0c;然后在数据…...

算法刷题:300. 最长递增子序列、674. 最长连续递增序列、718. 最长重复子数组、1143. 最长公共子序列

300. 最长递增子序列 1.dp定义&#xff1a;dp[i]表示i之前包括i的以nums[i]结尾的最长递增子序列的长度 2.递推公式&#xff1a;if (nums[i] > nums[j]) dp[i] max(dp[i], dp[j] 1); 注意这里不是要dp[i] 与 dp[j] 1进行比较&#xff0c;而是我们要取dp[j] 1的最大值…...

go 笔记

数据结构与 方法&#xff08;增删改查&#xff09; 安装goland,注意版本是2024.1.1&#xff0c;不是2024.2.1&#xff0c;软件下载地址也在链接中提供了 ‘go’ 不是内部或外部命令&#xff0c;也不是可运行的程序 或批处理文件。 在 Windows 搜索栏中输入“环境变量”&#…...

路由等保测评

1.身份鉴别 应对登录的用户进行身份标识和鉴别&#xff0c; 身份标识具有唯一性&#xff0c;身份鉴别信息具有复杂度要求并定期更换。 可以使用“ service password-encryption"命令对存储在配置文件中的所有口令和类似数据进行加密&#xff0c; 以避免攻击者通过读取配…...

C# 反射之动态生成dll/exe

这个可能应该属于反射的高级使用范围了&#xff0c;平常在项目中使用的人估计也不是很多。由于使用反射的话会降低性能&#xff0c;比如之前用到的GetValue、SetValue等之类&#xff0c;但是使用这种方式会大大提高效率&#xff0c;在这里我只想说&#xff0c;都直接写IL指令了…...

Rust 所有权 Slices

文章目录 发现宝藏1. Slice 的基础知识1.1 什么是 Slice&#xff1f;1.2 如何创建 Slice&#xff1f; 2. 处理字符串 Slice2.1 字符串的 Slice2.2 字符串的 Unicode 和切片 3. 在函数中使用 Slice3.1 传递 Slice 给函数3.2 可变 Slice 的函数 4. 复杂示例4.1 处理多维数组的 Sl…...

windows 安全与网络管理问题

问题&#xff1a;当编写的脚本或程序运行的时候&#xff0c;可能被windows阻止访问网络甚至被删除 避免被删除 wini 进入设置界面 -> 选择更新与安全 -> 选择windwos defender -> 点击添加排除项&#xff0c;将指定的文件或目录排除&#xff0c;避免被软件删除 允许…...

基于Python实现一个庆祝国庆节的小程序

功能&#xff1a; 添加互动功能&#xff1a;允许用户选择不同的祝福语或者查询不同的国庆节信息。动态背景音乐&#xff1a;播放国庆节相关的背景音乐。增加节日小测验&#xff1a;提供一些关于国庆节的趣味小测验&#xff0c;让用户参与。增强图形用户界面 (GUI)&#xff1a;…...

Anaconda 安装与使用教程

Anaconda 安装与使用教程 介绍 Anaconda 是一个用于科学计算的 Python 和 R 的发行版&#xff0c;它包含了众多流行的科学计算、数据分析、机器学习等领域的库。本教程旨在帮助初学者快速上手 Anaconda&#xff0c;并学会如何使用其管理环境以及安装包。 第一步&#xff1a;…...

时序预测SARIMAX模型

1. 项目背景 本文基于kaggle平台相关竞赛项目&#xff0c;具体连接如下&#xff1a; Time Series Forecasting With SARIMAX 基本信息如内容说明、数据集、已提交代码、当前得分排名以及比赛规则等&#xff0c;如图【1】所示&#xff0c;可以认真阅读。 图 1 2. 数据读取 …...

gin集成jaeger中间件实现链路追踪

1. 背景 新业务线带来新项目启动&#xff0c;需要改进原有项目的基础框架和组件能力&#xff0c;以提升后续开发和维护效率。项目搭建主要包括技术选型、框架搭建、基础服务搭建等。这其中就涉及到链路追踪的内容&#xff0c;结合其中的踩坑情况&#xff0c;用一篇文章来说明完…...

前端层面----监控与埋点

前言&#xff1a; 站在产品的视角&#xff0c;经常会问如下几个问题&#xff1a; 产品有没有用户使用 用户用得怎么样 系统会不会经常出现异常 如何更好地满足用户需求服务用户 当站在技术视角时&#xff0c;经常会问如下几个问题&#xff1a; 系统出现异常的频率如何 异常…...

linux Command

linux Command 1. 系统监控命令 1.1 top top [param] top -H -p pid&#xff0c;查看进程pid下面的子线程。-b以处理模式操作-c显示完整的命令行而不只是显示命令名。-d 屏幕刷新间隔时间。-l 忽略失效过程。-s 保密模式。-S 累积模式。-u 【用户名】 指定用户名。-p 【进程…...

uniapp登录页面( 适配:pc、小程序、h5)

<!-- 简洁登录页面 --> <template><view class"login-bg"><image class"img-a" src"https://zhoukaiwen.com/img/loginImg/2.png"></image><image class"img-b" src"https://zhoukaiwen.com/im…...

关于OceanBase 多模一体化的浅析

在当今多元化的业务生态中&#xff0c;各行各业对数据库系统的需求各有侧重。举例来说&#xff0c;金融风控领域对数据库的高效事务处理&#xff08;TP&#xff09;和分析处理&#xff08;AP&#xff09;能力有着严格要求&#xff1b;游戏行业则更加注重文档数据库的灵活性和性…...

快速git

下载 sudo apt install git配置 $ git config --global user.name "John Doe" $ git config --global user.email johndoeexample.com没有空格可以不加双引号如果~/.ssh没有先创建&#xff08;下一步用&#xff09; ssh方式制作密钥 github解释 #以邮箱作为标签…...

欺诈文本分类检测(十四):GPTQ量化模型

1. 引言 量化的本质&#xff1a;通过将模型参数从高精度&#xff08;例如32位&#xff09;降低到低精度&#xff08;例如8位&#xff09;&#xff0c;来缩小模型体积。 本文将采用一种训练后量化方法GPTQ&#xff0c;对前文已经训练并合并过的模型文件进行量化&#xff0c;通…...

2024.9.14(RC和RS)

一、replicationcontroller &#xff08;RC&#xff09; 1、更改镜像站 [rootk8s-master ~]# vim /etc/docker/daemon.json {"registry-mirrors": ["https://do.nark.eu.org","https://dc.j8.work","https://docker.m.daocloud.io",&…...

【算法随想录04】KMP 字符串匹配算法

这是字符串模式匹配经典算法。 给定一个文本 t 和一个字符串 s&#xff0c;我们尝试找到并展示 s 在 t 中的所有出现&#xff08;occurrence&#xff09;。 #include<bits/stdc.h>using namespace std;vector<int> KMP(string s) {int n s.size();vector<int&g…...

TCP和MQTT通信协议

协议分层 网络分层 协议应用层 Co AP MQTT HTTP传输层 UDP TCP网络层 IP链路层 Enternet 网络分层中最…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开&#xff0c;首…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发&#xff0c;后来由Pivotal Software Inc.&#xff08;现为VMware子公司&#xff09;接管。RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。广泛应用于各种分布…...

Python竞赛环境搭建全攻略

Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型&#xff08;算法、数据分析、机器学习等&#xff09;不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...

五子棋测试用例

一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏&#xff0c;有着深厚的文化底蕴。通过将五子棋制作成网页游戏&#xff0c;可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家&#xff0c;都可以通过网页五子棋感受到东方棋类…...

解析两阶段提交与三阶段提交的核心差异及MySQL实现方案

引言 在分布式系统的事务处理中&#xff0c;如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议&#xff08;2PC&#xff09;通过准备阶段与提交阶段的协调机制&#xff0c;以同步决策模式确保事务原子性。其改进版本三阶段提交协议&#xff08;3PC&#xf…...

《Offer来了:Java面试核心知识点精讲》大纲

文章目录 一、《Offer来了:Java面试核心知识点精讲》的典型大纲框架Java基础并发编程JVM原理数据库与缓存分布式架构系统设计二、《Offer来了:Java面试核心知识点精讲(原理篇)》技术文章大纲核心主题:Java基础原理与面试高频考点Java虚拟机(JVM)原理Java并发编程原理Jav…...

表单设计器拖拽对象时添加属性

背景&#xff1a;因为项目需要。自写设计器。遇到的坑在此记录 使用的拖拽组件时vuedraggable。下面放上局部示例截图。 坑1。draggable标签在拖拽时可以获取到被拖拽的对象属性定义 要使用 :clone, 而不是clone。我想应该是因为draggable标签比较特。另外在使用**:clone时要将…...