【电商项目实战】实现订单超时支付取消

news2024/11/15 12:25:24

🎉🎉欢迎来到我的CSDN主页!🎉🎉

🏅我是Java方文山,一个在CSDN分享笔记的博主。📚📚

🌟推荐给大家我的专栏《电商项目实战》。🎯🎯

👉点击这里,就可以查看我的主页啦!👇👇

Java方文山的个人主页

🎁如果感觉还不错的话请给我点赞吧!🎁🎁

💖期待你的加入,一起学习,一起进步!💖💖

请添加图片描述

前言

大家对电商购物应该都比较熟悉了,我们应该注意到,在下单之后,通常会有一个倒计时,如果超过支付时间,订单就会被自动取消。这个功能说难也不难,说简单但也足以难倒一大片人,今天我就为大家提供一种思路。

一、订单显示

我们在购物车页面点击结算的时候肯定还是没有直接让我们交钱的,是跳转一个订单确认页面,确认订单信息无误,选择收货地址支付方式等才会生成订单。

订单详情页面

<!DOCTYPE html>
<html>
	<head lang="en">
		<#include "common/head.html">
		<link rel="stylesheet" type="text/css" href="css/public.css"/>
		<link rel="stylesheet" type="text/css" href="css/proList.css" />
		<link rel="stylesheet" type="text/css" href="css/mygxin.css" />
	</head>
	<body>
		<!----------------------------------------order------------------>
		<div class="head ding">
			<div class="wrapper clearfix">
				<div class="clearfix" id="top">
					<h1 class="fl"><a href="${ctx}/"><img src="img/logo.png"/></a></h1>
					<div class="fr clearfix" id="top1">
						<form action="#" method="get" class="fl">
							<input type="text" placeholder="搜索" />
							<input type="button" />
						</form>
					</div>
				</div>
			</div>
		</div>
		<!-----------------site------------------->
		<div class="order cart mt">
		<div class="site">
				<p class="wrapper clearfix">
					<span class="fl">订单确认</span>
					<img class="top" src="img/temp/cartTop02.png">
				</p>
			</div>
			<!-----------------orderCon------------------->
			<div class="orderCon wrapper clearfix">
				<div class="orderL fl">
					<!--------h3---------------->
					<h3>收件信息<a href="#" class="fr">新增地址</a></h3>
					<!--------addres---------------->
					<div class="addres clearfix">
						<div class="addre fl on">
							<div class="tit clearfix">
								<p class="fl">张三1
									<span class="default">[默认地址]</span>
								</p>
								<p class="fr">
									<a href="#">删除</a>
									<span>|</span>
									<a href="#" class="edit">编辑</a>
								</p>
							</div>
							<div class="addCon">
								<p>河北省&nbsp;唐山市&nbsp;路北区&nbsp;大学生公寓村</p>
								<p>15732570937</p>
							</div>
						</div>
						<div class="addre fl">
							<div class="tit clearfix">
								<p class="fl">张三2
								</p>
								<p class="fr">
									<a href="#" class="setDefault">设为默认</a>
									<span>|</span>
									<a href="#">删除</a>
									<span>|</span>
									<a href="#" class="edit">编辑</a>
								</p>
							</div>
							<div class="addCon">
								<p>河北省&nbsp;唐山市&nbsp;路北区&nbsp;大学生公寓村</p>
								<p>15732570937</p>
							</div>
						</div>
						<div class="addre fl">
							<div class="tit clearfix">
								<p class="fl">张三3
								</p>
								<p class="fr">
									<a href="#" class="setDefault">设为默认</a>
									<span>|</span>
									<a href="#">删除</a>
									<span>|</span>
									<a href="#" class="edit">编辑</a>
								</p>
							</div>
							<div class="addCon">
								<p>河北省&nbsp;唐山市&nbsp;路北区&nbsp;大学生公寓村</p>
								<p>15732570937</p>
							</div>
						</div>
					</div>
					<h3>支付方式</h3>
					<!--------way---------------->
					<div class="way clearfix">
						<img class="on" value="0" src="img/temp/way01.jpg">
						<img value="1" src="img/temp/way02.jpg">
						<img value="2" src="img/temp/way03.jpg">
						<img value="3" src="img/temp/way04.jpg">
					</div>
					<h3>选择快递</h3>
					<!--------dis---------------->
					<div class="dis clearfix">
						<span class="on">顺风快递</span>
						<span>百世汇通</span>
						<span>圆通快递</span>
						<span>中通快递</span>
					</div>
				</div>
				<div class="orderR fr">
					<div class="msg">
						<h3>订单内容<a href="${ctx}/cart/getCart" class="fr">返回购物车</a></h3>

						<#--定义商品总价-->
						<#assign sumnum=0>
						<#--遍历商品信息-->
						<#if item??>
						<#list item as g>
						<ul class="clearfix">
							<li class="fl">
								<img src="${g.goodsImg}" style="width: 100px;height: 100px">
							</li>
							<li class="fl">
								<p>${g.goodsTitle}</p>
								<p>${g.goodsName}</p>
								<p>数量:${g.num}</p>
								<#assign xiaoji=g.num*g.goodsPrice>
							</li>
							<li class="fr">¥${g.goodsPrice}</li>
						</ul>
							<#assign sumnum=sumnum+xiaoji>
						</#list>
						</#if>
					</div>
					<!--------tips---------------->
					<div class="tips">
						<p><span class="fl">商品金额:</span><span class="fr">¥${sumnum}</span></p>
						<p><span class="fl">优惠金额:</span><span class="fr">¥0.00</span></p>
						<p><span class="fl">运费:</span><span class="fr">免运费</span></p>
					</div>
					<!--------tips count---------------->
					<div class="count tips">
						<p><span class="fl">合计:</span><span class="fr">¥${sumnum}</span></p>
					</div>
					<!--<input type="button" name="" value="去支付"> -->
					<a href="javascript:void(0);" class="pay">去支付</a>
				</div>
			</div>
		</div>
		<!--编辑弹框-->
		<!--遮罩-->
		<div class="mask"></div>
		<div class="adddz editAddre">
			<form action="#" method="get">
				<input type="text" placeholder="姓名" class="on" />
				<input type="text" placeholder="手机号" />
				<div class="city">
					<select name="">
						<option value="省份/自治区">省份/自治区</option>
					</select>
					<select>
						<option value="城市/地区">城市/地区</option>
					</select>
					<select>
						<option value="区/县">区/县</option>
					</select>
					<select>
						<option value="配送区域">配送区域</option>
					</select>
				</div>
				<textarea name="" rows="" cols="" placeholder="详细地址"></textarea>
				<input type="text" placeholder="邮政编码" />
				<div class="bc">
					<input type="button" value="保存" />
					<input type="button" value="取消" />
				</div>
			</form>
		</div>
		<!--返回顶部-->
		<input type="hidden" id="gids" value="${RequestParameters['gids']!}"/>
		<#include "common/footer.html">
		<script src="js/others/order.js" type="text/javascript" charset="utf-8"></script>
		<script src="js/public.js" type="text/javascript" charset="utf-8"></script>
		<script src="js/pro.js" type="text/javascript" charset="utf-8"></script>
		<script src="js/user.js" type="text/javascript" charset="utf-8"></script>
	</body>
</html>

 

1.前端代码 

首先我们为结算按钮设置点击事件

$(".count").click(function (){
		//拿到所有选中的商品id
		let ids=[];
		$(".th input[type='checkbox']:checked").each(function(j){
			//获取单条数据上面的gid属性
			let gid=$(this).attr('data-gid');
			ids.push(gid)
		})
		ids=ids.join(",")
		//将商品数据发送到后端
		location.href="/cart/getOrder?ids="+ids;
	})

 

2.后端代码 

 拿到选中需要结算的商品后需要先去Redis中将对应的商品拿出来

// 查询用户结算的购物车商品
    List<GoodsVo> loadCart(User user,List<String> ids);
 @Override
    public List<GoodsVo> loadCart(User user, List<String> ids) {
        HashOperations<String,String,GoodsVo> operations=redisTemplate.opsForHash();
        String bigKey=Constants.REDIS_CART_PREFIX + user.getId();
        //根据用户Id查询结算的购物车商品
        List<GoodsVo> goodsVos = operations.multiGet(bigKey, ids);
        return goodsVos;
    }

这里拿出来的商品只有商品id和数量所以还需要拿到数据库做比较

    @RequestMapping("/getOrder")
    public String getOrder(User user, String ids, Model model) {
        //根据用户查询结算购物车商品
        List<String> ds = (List<String>) Arrays.asList(ids.split(","));
        List<GoodsVo> item = redisService.loadCart(user,ds);

        //根据商品Id查询对应商品
        List<Integer> gds = item.stream().map(GoodsVo::getGid).collect(Collectors.toList());
        if (gds.size() > 0) {
            List<Goods> goods = goodsService.listByIds(gds);
//        进行遍历筛选合适的数据
            for (Goods g : goods) {
                //找到对应属性的商品
                for (GoodsVo gv : item) {
                    if (g.getGid() == gv.getGid()) {
                        BeanUtils.copyProperties(g, gv);
                    }
                }
            }
        }

        model.addAttribute("item", item);
        return "order";
    }

3.数据显示 

最后在前端显示相应的数据即可

//订单详情页面部分代码


            <#--定义商品总价-->
						<#assign sumnum=0>
						<#--遍历商品信息-->
						<#if item??>
						<#list item as g>
						<ul class="clearfix">
							<li class="fl">
								<img src="${g.goodsImg}" style="width: 100px;height: 100px">
							</li>
							<li class="fl">
								<p>${g.goodsTitle}</p>
								<p>${g.goodsName}</p>
								<p>数量:${g.num}</p>
								<#assign xiaoji=g.num*g.goodsPrice>
							</li>
							<li class="fr">¥${g.goodsPrice}</li>
						</ul>
							<#assign sumnum=sumnum+xiaoji>
						</#list>
						</#if>
					</div>
					<!--------tips---------------->
					<div class="tips">
						<p><span class="fl">商品金额:</span><span class="fr">¥${sumnum}</span></p>
						<p><span class="fl">优惠金额:</span><span class="fr">¥0.00</span></p>
						<p><span class="fl">运费:</span><span class="fr">免运费</span></p>
					</div>
					<!--------tips count---------------->
					<div class="count tips">
						<p><span class="fl">合计:</span><span class="fr">¥${sumnum}</span></p>

					</div>

效果展示: 

这里其他的东西除了商品以外都是定死的,包括收件信息(感兴趣的可以自行优化) 

 

 二、生成订单

1.表设计

生成订单前,我们先看一下订单表和订单详情表有什么表字段好去拿什么值。

t_orde(订单表

t_order_item(订单详情表

 

 2.前端取值

我们可以先对页面元素进行判断,拿取我们需要的元素

 这里我为选中的收件信息、支付方式、快递都添加了一个"on"样式,我们只需要根据标签层层抓取即可。

//生成订单
$(".pay").click(function (){
    let el=$(".addres").find(".on")
    let person= el.find(".tit .fl").text()
    let address= el.find(".addCon p:first-child").text()
    let telephone= el.find(".addCon p:last-child").text()
    let pay=$(".way .on").attr('value')
    let mail=$(".dis .on").text()
    let ids=$(this).attr('data-ids')
    let order={
        person,address,telephone,pay,mail,ids
    }
        console.log(order)
})

 打印结果没有问题,那么我们就可以向后端发起请求了

 我们把后面的请求写完

//生成订单
$(".pay").click(function (){
    let el=$(".addres").find(".on")
    let person= el.find(".tit .fl").text()
    let address= el.find(".addCon p:first-child").text()
    let telephone= el.find(".addCon p:last-child").text()
    let pay=$(".way .on").attr('value')
    let mail=$(".dis .on").text()
    let ids=$(this).attr('data-ids')
    let order={
        person,address,telephone,pay,mail,ids
    }
        // console.log(order)
    $.post('order/addOrder',order,resp=>{
        if(resp.code===200){alert("新增订单成功")}
    },'json')
})

 

2.后端处理

首先需要一个接收前端参数的Vo类

@Data
public class OrderVo  extends Order implements Serializable {
    private String ids;
}

 随后就可以开始编写我们的controller层代码

@RestController
@RequestMapping("/order")
public class OrderController {
    @Autowired
    private IRedisService redisService;
    @Autowired
    private IGoodsService goodsService;
    @Autowired
    private IOrderItemService orderItemService;
    @Autowired
    private IOrderService orderService;

    @RequestMapping("/addOrder")
    public JsonResponseBody<?> addOrder(User user, OrderVo vo) {
        //从Redis将数据查询出来
        String ids = vo.getIds();
        List<String> ds = Arrays.asList(ids.split(","));
        List<GoodsVo> item = redisService.loadCart(user, ds);
        //根据商品id到数据库查询商品详情
        //根据商品Id查询对应商品
        List<Integer> gds = item.stream().map(GoodsVo::getGid).collect(Collectors.toList());
        if (gds.size() > 0) {
            List<Goods> goods = goodsService.listByIds(gds);
//        进行遍历筛选合适的数据
            for (Goods g : goods) {
                //找到对应属性的商品
                for (GoodsVo gv : item) {
                    if (g.getGid() == gv.getGid()) {
                        BeanUtils.copyProperties(g, gv);
                    }
                }
            }
        }

        BigDecimal sumPrice= BigDecimal.valueOf(0);//保存商品总价
        long oid = YitIdHelper.nextId();//订单id
        //新增订单详情
        //订单项集合
        List<OrderItem> orderItems=new ArrayList<>();
        for (GoodsVo it : item) {
            //生成订单项
            OrderItem orderItem=new OrderItem();
            BeanUtils.copyProperties(it,orderItem);
            orderItem.setQuantity(it.getNum());
            orderItem.setOoid(YitIdHelper.nextId());
            orderItem.setGid(Long.valueOf(it.getGid()+""));
            orderItem.setOid(oid);
            //将订单项加入集合中
            orderItems.add(orderItem);
            BigDecimal sum= BigDecimal.valueOf(it.getNum()*Double.parseDouble((it.getGoodsPrice()+"")));//保存商品小计
            sumPrice.add(sum);
        }
        //为了反正sql过长可选择批量
        orderItemService.saveBatch(orderItems,5);

        //新增订单
        Order order=new Order();
        BeanUtils.copyProperties(vo,order);
        order.setTotal(sumPrice);
        order.setUserId(user.getId());
        order.setStatus(0);
        order.setOid(oid);
        order.setCreateDate(new Date());
        orderService.save(order);

        //删除购物车信息
        redisService.deleteCart(user,ds);

        return JsonResponseBody.success();
    }


}

 将我们需要的参数一个一个注入进去即可下面实践一下

 

请添加图片描述

到这里我的分享就结束了,欢迎到评论区探讨交流!!

💖如果觉得有用的话还请点个赞吧 💖

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1354089.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OpenHarmony源码转换器—多线程特性转换

本文讨论了如何将多线程的 Java 代码转换为 OpenHarmony ArkTS 代码​ 一、简介 Java 内存共享模型 以下示例伪代码和示意图展示了如何使用内存共享模型解决生产者消费者问题。 生产者消费者与共享内存间交互示意图 为了避免不同生产者或消费者同时访问一块共享内存的容器时…

阶段十-分布式-Redis02

第一章 Redis 事务 1.1 节 数据库事务复习 数据库事务的四大特性 A&#xff1a;Atomic &#xff0c;原子性&#xff0c;将所以SQL作为原子工作单元执行&#xff0c;要么全部执行&#xff0c;要么全部不执行&#xff1b;C&#xff1a;Consistent&#xff0c;一致性&#xff0…

Vue前端文字效果:如何让一段文本像是手动一个一个字打出来的

效果展示 自己做的AI聊天机器人界面&#xff0c;我觉得比微信还好看 由于这个前端略微复杂&#xff0c;下文用最简单的例子来展示&#xff1a; 分析需求 对于AI聊天工具的前端&#xff0c;如果AI生成的文本像是一个一个字打出来的&#xff0c;就会让AI看起来更像真的人&…

详解卡尔曼滤波(Kalman Filter)

1. 从维纳滤波到卡尔曼滤波 黑盒&#xff08;Black Box&#xff09;思想最早由维纳&#xff08;Wiener&#xff09;在1939年提出&#xff0c;即假定我们对从数据到估计中间的映射过程一无所知&#xff0c;仅仅用线性估计&#xff08;我们知道在高斯背景下&#xff0c;线性估计…

STM32 HAL库定时器触发DMA并口数据传输

代码目的&#xff1a; STM32与FPGA通讯&#xff0c;通过8位并口线进行通讯&#xff0c;16byte的数据在10us之内通过8位并口数据线传给FPGA&#xff0c;FPGA读取该数据。 HAL库设置说明&#xff1a; 时钟采用80MHz&#xff0c;由于16byte的数据要在10us之内传完&#xff0c;那…

[笔记] 使用 qemu 创建虚拟磁盘并安装 grub

之前使用 wsl 进行了直接创建虚拟磁盘并安装 grub,现在希望能够直接借助 qemu 的工具创建虚拟磁盘文件并安装 grub,由于需要用到 nbd(net block device网络块设备) 模块,在 wsl 中并不支持,因此这里使用到了 Hypver-V 虚拟机创建了一个 Ubuntu 系统,在系统中安装了 qemu 和 gru…

物联网安全:保护关键网络免受数字攻击

物联网 (IoT) 彻底改变了当今互联世界中的各个行业&#xff0c;实现了智能家居、自动驾驶汽车和先进的工业系统。然而&#xff0c;随着物联网设备数量的急剧增加&#xff0c;这些设备和相应网络的安全性已成为人们关注的焦点。本文旨在探讨物联网安全的重要性&#xff0c;同时简…

Pandas教程(五)—— 数据重塑透视及批量处理

1.数据重塑 重塑数据主要有两种方式&#xff0c;分别是 stack&#xff08;堆叠&#xff09;和 unstack&#xff08;拆堆&#xff09;&#xff0c;他们两个是互逆的操作 函数作用 data.stack&#xff08; &#xff09; 堆叠 会“旋转”或将列中的数据透视到行 列 一一> 行…

AWS(三):如何在AwsManagedAd目录和windowsAD实例之间建立双向信任。

前提&#xff1a; 1.创建好了一个AWS managed AD目录&#xff0c;我的目录域名为:aws.managed.com 2.创建好了一个windows AD实例并提升了为域控服务器,实例域名为:aws2.com 看过我AWS 一和二的应该都会创建windows实例了&#xff0c;切记不能将其无缝加入到aws managed AD的…

(JAVA)-反射

什么是反射&#xff1f; 反射允许对成员变量&#xff0c;成员方法和构造方法的信息进行编程访问。 说简单点就是反射能将类里面的构造方法&#xff0c;成员变量,修饰符,返回值&#xff0c;注解&#xff0c;类型&#xff0c;甚至异常等类里面的所有东西都能够获取出来。 关于C…

打造炫酷粒子效果的前端利器tsParticles

前端潮流速递 &#xff1a;打造炫酷粒子效果的前端利器tsParticles 在现代前端开发中&#xff0c;动画和视觉效果是吸引用户的关键元素之一。而实现炫酷而引人入胜的粒子效果&#xff0c;常常需要耗费大量的时间和精力。然而&#xff0c;有了 tsParticles&#xff0c;这一切变…

GitHub上的15000个Go模块存储库易受劫持攻击

内容概要&#xff1a; 目前研究发现&#xff0c;GitHub上超过15000个Go模块存储库容易受到一种名为“重新劫持”的攻击。 由于GitHub用户名的更改会造成9000多个存储库容易被重新劫持&#xff0c;同时因为帐户删除&#xff0c;会对6000多个存储库造成重新劫持的危机。目前统计…

【MySQL·8.0·源码】MySQL 表的扫描方式

前言 在进一步介绍 MySQL 优化器时&#xff0c;先来了解一下 MySQL 单表都有哪些扫描方式。 单表扫描方法是基表的读取基础&#xff0c;也是完成表连接的基础&#xff0c;熟悉了基表的基本扫描方式&#xff0c; 即可以倒推理解 MySQL 优化器层的诸多考量。 基表&#xff0c;即…

半导体行业-SECS/GEM协议 JAVA与SECS/GEM通信 什么是配方?springboot集成SECS通信协议 配方管理S7FX

Java与SECS基础通信 Java实现SECS指令S2F17获取时间 Java实现SECS指令 S10F3 终端单个显示例子 Java实现SECS指令 S7FX配方管理 Java实现SECS指令 S5F1报警/取消报警上传 实例源码及DEMO请查阅 JAVA开发SECS快速入门资料&#xff0c;SECS S7F19 什么是半导体配方&…

Unity3D UGUI图集打包与动态使用(TexturePacker)

制作图集的好处&#xff1a; 众所周知CPU是用来处理游戏的逻辑运算的&#xff0c;而GPU是用来处理游戏中图像的。在GPU中&#xff0c;我们要绘制一个图像需要提交图片&#xff08;纹理&#xff09;到显存&#xff0c;然后再进行绘制&#xff08;在这个过程中会产生一次DrawCall…

书生-浦路大模型全链路开源体系

2023年&#xff0c;大模型成为热门关键词 论文链接 大模型已经成为发展通用人工智能的重要途经 模型评测过程&#xff1a;从模型到应用 全链条开源开发体系 | 数据&#xff1a; 多模态融合 万卷包含文本、图像和视频等多模态数据&#xff0c;涵盖科技、文学、媒体、教育和法…

力扣hot100 二叉树的层序遍历 BFS 队列

&#x1f468;‍&#x1f3eb; 题目地址 时间复杂度&#xff1a; O ( n ) O(n) O(n)空间复杂度&#xff1a; O ( n ) O(n) O(n) &#x1f60b; 队列写法 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode…

Pycharm恢复默认设置

window 系统 找到下方目录-->删除. 再重新打开Pycharm C:\Users\Administrator\.PyCharm2023.3 你的不一定和我名称一样 只要是.PyCharm*因为版本不同后缀可能不一样 mac 系统 请根据需要删除下方目录 # Configuration rm -rf ~/Library/Preferences/PyCharm* # Caches …

vue的小入门

vue的快速上手 Vue概念 是一个用于构建用户界面的渐进式框架优点&#xff1a;大大提高开发效率缺点&#xff1a;需要理解记忆规则 创建Vue实例 步骤&#xff1a; 准备容器引包创建Vue实例new Vue()指定配置项el data>渲染数据 el指定挂载点&#xff0c;选择器指定控制…

OpenCV-14图片的四则运算和图片的融合

一、图片的四则运算 1. 加法运算 通过使用API add来执行图像的加法运算 cv2.add&#xff08;src1&#xff0c; src2&#xff09;需要再其中传入两张图片。 图片就是矩阵&#xff0c;图片的加法运算就是矩阵的加法运算。 因此加法运算中要求两张图的shape必须是相同的。 首…