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

欢迎来到我的CSDN主页!

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

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

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

Java方文山的个人主页

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

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

请添加图片描述

前言

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

一、订单显示

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

订单详情页面



	
		<#include "common/head.html">
		
		
		
	
	
		
		

订单确认

收件信息新增地址

张三1 [默认地址]

删除 | 编辑

河北省 唐山市 路北区 大学生公寓村

15732570937

张三2

设为默认 | 删除 | 编辑

河北省 唐山市 路北区 大学生公寓村

15732570937

张三3

设为默认 | 删除 | 编辑

河北省 唐山市 路北区 大学生公寓村

15732570937

支付方式

选择快递

顺风快递 百世汇通 圆通快递 中通快递

订单内容返回购物车

<#--定义商品总价--> <#assign sumnum=0> <#--遍历商品信息--> <#if item??> <#list item as g>
  • ${g.goodsTitle}

    ${g.goodsName}

    数量:${g.num}

    <#assign xiaoji=g.num*g.goodsPrice>
  • ¥${g.goodsPrice}
<#assign sumnum=sumnum+xiaoji>

商品金额:¥${sumnum}

优惠金额:¥0.00

运费:免运费

合计:¥${sumnum}

去支付
<#include "common/footer.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 loadCart(User user,List ids);
 @Override
    public List loadCart(User user, List ids) {
        HashOperations operations=redisTemplate.opsForHash();
        String bigKey=Constants.REDIS_CART_PREFIX + user.getId();
        //根据用户Id查询结算的购物车商品
        List goodsVos = operations.multiGet(bigKey, ids);
        return goodsVos;
    }

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

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

        //根据商品Id查询对应商品
        List gds = item.stream().map(GoodsVo::getGid).collect(Collectors.toList());
        if (gds.size() > 0) {
            List 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>
						
  • ${g.goodsTitle}

    ${g.goodsName}

    数量:${g.num}

    <#assign xiaoji=g.num*g.goodsPrice>
  • ¥${g.goodsPrice}
<#assign sumnum=sumnum+xiaoji>

商品金额:¥${sumnum}

优惠金额:¥0.00

运费:免运费

合计:¥${sumnum}

效果展示: 

【电商项目实战】实现订单超时支付取消_第1张图片

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

 二、生成订单

1.表设计

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

t_orde(订单表

【电商项目实战】实现订单超时支付取消_第2张图片

t_order_item(订单详情表

 2.前端取值

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

【电商项目实战】实现订单超时支付取消_第3张图片

 这里我为选中的收件信息、支付方式、快递都添加了一个"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)
})

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

【电商项目实战】实现订单超时支付取消_第4张图片

 我们把后面的请求写完

//生成订单
$(".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 ds = Arrays.asList(ids.split(","));
        List item = redisService.loadCart(user, ds);
        //根据商品id到数据库查询商品详情
        //根据商品Id查询对应商品
        List gds = item.stream().map(GoodsVo::getGid).collect(Collectors.toList());
        if (gds.size() > 0) {
            List 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 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();
    }


}

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

【电商项目实战】实现订单超时支付取消_第5张图片

三、解决订单超时

我这里提供的解决办法是使用Redis,确认订单后将订单存入Redis设置有效期,有效期结束就将该订单的状态设置为已过期,如果用户在有效期内支付了订单,那么我们就删除Redis中的缓存数据

IRedisService

    //将订单信息放入Redis
    void saveOrder(String token, Order order);

    //根据用户查询未支付订单
    Order getOder(String token);

    //根据用户查询未支付订单
    void deleteOder(String token);

IRedisServiceImpl

    @Override
    public void saveOrder(String token, Order order) {
        //将订单信息保存到Redis
        redisTemplate.opsForValue().set(Constants.REDIS_ORDER_PREFIX +token,order);
        //设置过期时间(过期自动删除)
        redisTemplate.expire(Constants.REDIS_ORDER_PREFIX + token, 1800, TimeUnit.SECONDS);
    }

    @Override
    public Order getOder(String token) {
        return (Order) redisTemplate.opsForValue().get(Constants.REDIS_ORDER_PREFIX +token);
    }

    @Override
    public void deleteOder(String token) {
        redisTemplate.delete(Constants.REDIS_ORDER_PREFIX +token);
    }

我们查看订单的时候具体controller代码如下

 @RequestMapping("/unpaidOrder")
    public String unpaidOrder(User user, Model model) {
        //根据用户拿到未支付订单
        List item = orderService.list(new QueryWrapper()
                .eq("user_id", user.getId())
                .eq("status", 0));
        //在有效期未支付的查询出来,过期的做相应的处理
        List items = new ArrayList<>();
        for (Order order : item) {
            //将用户未支付的订单查询出来
            Order oders = redisService.getOder(order.getOid() + "");
            if (oders == null) {
                order.setStatus(6);
            } else {
                items.add(order);
            }
        }
        //清理过期订单
        orderService.updateBatchById(item);
        model.addAttribute("item", items);
        return "myorderq";
    }

 

请添加图片描述

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

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

你可能感兴趣的:(电商项目实战,Redis,Java,电商项目)