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

🎉🎉欢迎来到我的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();
    }


}

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

 

请添加图片描述

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Git(2):Git环境的安装

本教程里的git命令例子都是在Git Bash中演示的&#xff0c;会用到一些基本的linux命令&#xff0c;在此为大家提前列举&#xff1a; ls/ll 查看当前目录cat 查看文件内容touch 创建文件vi vi编辑器&#xff08;使用vi编辑器是为了方便展示效果&#xff0c;学员可以记事本、edi…

Spring之 国际化:i18n

1、i18n概述 国际化也称作i18n&#xff0c;其来源是英文单词 internationalization的首末字符i和n&#xff0c;18为中间的字符数。由于软件发行可能面向多个国家&#xff0c;对于不同国家的用户&#xff0c;软件显示不同语言的过程就是国际化。通常来讲&#xff0c;软件中的国…

微服务注册到Zookeeper注册中心

jar包&#xff1a; <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-zookeeper-discovery</artifactId></dependency>启动类上面加入&#xff1a;EnableDiscoveryClient注解 application.ym…

使用 Docker 部署 SSCMS 内容管理系统

1&#xff09;SSCMS 介绍 官网&#xff1a;https://sscms.com/ GitHub&#xff1a;https://github.com/siteserver/cms SSCMS 基于 .NET Core&#xff0c;能够以最低的成本、最少的人力投入在最短的时间内架设一个功能齐全、性能优异、规模庞大并易于维护的网站平台。 2&#…

2024 年度 AAAI Fellows 揭晓!清华大学朱军教授入选!

今日&#xff0c;国际人工智能领域最权威的学术组织 AAAI 揭晓 2024 年度 Fellows 评选结果&#xff0c;新增 12 位 Fellow。 其中&#xff0c;清华大学计算机系教授朱军因「在机器学习理论与实践方面做出的重大贡献」而成功入选&#xff0c;成为本年度入选的唯一华人学者&…

LabVIEW开发滚筒洗衣机动态监测系统

LabVIEW软件在滚筒洗衣机的动态监测和分析中扮演着关键角色。本案例展示了如何利用LabVIEW开发的系统来优化洗衣机的性能和可靠性。 首先&#xff0c;在建立洗衣机的动力学模型基础上&#xff0c;利用LabVIEW进行了关键零部件的动态优化设计。通过LabVIEW的高级计算和模拟功能…

【计算机毕业设计】SSM健身房俱乐部管理系统

项目介绍 本项目包含前后台&#xff0c;分为普通用户与管理员两种角色&#xff0c;前台为普通用户登录&#xff0c;后台为管理员登录&#xff1b; 管理员角色包含以下功能&#xff1a; 登录,会员管理-增删改查,员工管理-增删改查,课程管理,网站新闻管理,新闻添加编辑,留言管…

解决 Postman 报错问题:一份综合指南

Postman 是一个流行的 API 测试工具&#xff0c;它可以帮助开发者和测试人员快速地创建和发送各种 HTTP 请求&#xff0c;并查看响应结果。但是&#xff0c;在使用 Postman 的过程中&#xff0c;有时候会遇到一些报错或异常情况&#xff0c;影响了正常的测试流程。本文将介绍一…

Groovy操作JSON和XML及对文件的处理

文章目录 1Groovy对Json的操作1.1 Groovy自带工具处理Json1.2 使用java第三方类库gson处理json 2 Groovy对xml的操作2.1 对象转换成xml2.2 xml转换成对象 3 Groovy操作文件3.1 文本文件操作3.2 对象写入文件和从文件中读出 1Groovy对Json的操作 1.1 Groovy自带工具处理Json ​…

word中设置上标后括号和数字没有上下对齐,解决

问题 word中设置上标后括号和数字没有上下对齐&#xff0c;如下图 原因 因为数字的括号是中文状态下输入的&#xff0c;数字是英文状态。用户需要将其改变成用英文状态下输入 解决办法 统一成英文状态&#xff1a;选中&#xff0c;设置字体为“半角” 如果上标来自参考文献…

计算机网络期末复习——计算大题(一)

个人名片&#xff1a; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生 &#x1f42f;个人主页&#xff1a;妄北y &#x1f427;个人QQ&#xff1a;2061314755 &#x1f43b;个人邮箱&#xff1a;2061314755qq.com &#x1f989;个人WeChat&#xff1a;V…

vue2 jeecg-boot

业务介绍 &#xff1a; 在首页进行数据的添加&#xff0c;添加之后 将数据传递给后端&#xff0c;后端会计算&#xff0c;在返回给前端&#xff0c;前端拿到进行渲染&#xff0c;拿到数据跳转到结果页面&#xff0c;点击存档后&#xff0c;才可以触发下载和浏览&#xff0c;不…

如何自动生成 API 接口文档 - 一份详细指南

本篇文章详细教你如何使用 Apifox 的 IDEA 插件实现自动生成接口代码。好处简单总结有以下几点&#xff1a; 自动生成接口文档&#xff1a; 不用手写&#xff0c;一键点击就可以自动生成文档&#xff0c;当有更新时&#xff0c;点击一下就可以自动同步接口文档&#xff1b;代码…

Apipost多Host服务配置

最近Apipost新增同环境下多host服务的配置功能&#xff0c;本篇文章带来该功能的使用场景及使用方法。 配置方法&#xff1a; 点击右上角眼睛标识进入环境管理 点击添加服务&#xff0c;输入服务名和URL 配置完成后需要在接口目录中选择该目录下需要使用的host服务&#xff0…

Linux——进程初识(二)

1. 对当前目录创建文件的理解 我们知道在创建一个文件时&#xff0c;它会被默认创建到当前目录下&#xff0c;那么它是如何知道当前目录的呢&#xff1f; 对于下面这样一段代码 #include <stdio.h> #include <unistd.h>int main() {fopen("tmp.txt", …

C++大作业——学生选课系统优化版

C大作业——学生选课系统优化版 前言1.学生类和课程类的实现2.输入输出流重载的实现3.增删改查的实现4.多级菜单的实现5.选课和退选的实现5.完整代码 前言 本文是对本人之前写过的一个学生选课系统的优化&#xff0c;整体上的逻辑是和我上一篇博客一样的&#xff08;链接在此&a…

这次,数据泄露的目标受害者指向了---救护车服务公司

已停业的救护车服务遭到勒索软件攻击导致近百万人受到威胁&#xff01; 此次数据泄露的目标受害者是法伦救护车服务公司&#xff0c;该公司是Transformative Healthcare的子公司。ALPHV勒索软件团伙声称对2023年4月下旬对Transformative Healthcare的攻击负责&#xff0c;并导…

3dmax全景图用什么渲染 全景图云渲染使用教程

在给客户展示设计概念时&#xff0c;应用3ds Max创建的全景图是一个高效直观的方法。这种方式不仅可以全方位地呈现整个空间&#xff0c;让客户沉浸式地感受设计师的创意&#xff0c;而且在展现大型空间设计&#xff0c;如展览馆或者会议室等&#xff0c;效果尤其显著&#xff…

如何在anaconda里安装basemap和pyproj库

当直接使用conda命令进行安装basemap和pyproj库时&#xff0c;会出现版本不对应的报错问题(如下图)&#xff0c;所以此篇博客用以展示如何安装basemap和pyproj库 题主默认使用的anaconda源已经切换成了清华大学源&#xff0c;但是仍然会出现报错&#xff0c;所以不是源的问题&a…

什么是向量数据库

什么是向量数据库 向量数据库是一种应用在高效存储和查询高维向量的数据库。在传统的OLTP和OLAP数据库中&#xff08;如上图所示&#xff09;&#xff0c;数据按行和列组织&#xff08;这些称为表&#xff09;&#xff0c;并根据这些列中的值执行查询。然而&#xff0c;在某些应…