苍穹外卖day8(2)用户下单、微信支付

文章目录

  • 前言
  • 一、用户下单
    • 1. 业务流程
    • 2. 接口设计
    • 3. 数据库设计
      • 3.1 订单表orders
      • 3.2 订单明细表 order_detail
    • 4. 代码实现
  • 二、订单支付


前言

用户下单
因为订单信息中包含了其他业务中的数据,在逻辑处理中涉及了多个其他业务,比如要判断地址簿、购物车数据是否为空(查询地址簿和购物车)
订单表字段多,在插入数据的时候,要确保每个字段都有值
向订单表插入数据后,也得向订单明细表插入数据:具体来说,就是遍历购物车数据,把购物车中的商品详细信息(菜品、套餐、数量、价格…)赋给订单详情表
完成下单后要清空购物车
订单支付
需要商家号,跳过支付,模拟实现订单支付功能


一、用户下单

1. 业务流程

在这里插入图片描述

2. 接口设计

在这里插入图片描述

3. 数据库设计

在这里插入图片描述

3.1 订单表orders

在这里插入图片描述

3.2 订单明细表 order_detail

在这里插入图片描述

4. 代码实现

1、创建OrderController并提供用户下单方法

@PostMapping("/submit")
@ApiOperation("用户下单")
public Result<OrderSubmitVO> submit(@RequestBody OrdersSubmitDTO ordersSubmitDTO){log.info("用户下单,参数为:{}",ordersSubmitDTO);OrderSubmitVO orderSubmitVO = orderService.submitOrder(ordersSubmitDTO);return Result.success(orderSubmitVO);
}

2、在OrderService接口声明用户下单方法,OrderServiceImpl实现

@Transactional
public OrderSubmitVO submitOrder(OrdersSubmitDTO ordersSubmitDTO) {//1. 处理各种业务异常//地址簿为空AddressBook addressBook = addressBookMapper.getById(ordersSubmitDTO.getAddressBookId());if(addressBook == null){throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);}//购物车数据为空ShoppingCart shoppingCart = new ShoppingCart();Long userId = BaseContext.getCurrentId();shoppingCart.setUserId(userId);List<ShoppingCart> shoppingCartList = shoppingCartMapper.list(shoppingCart);if(shoppingCartList == null || shoppingCartList.size()==0){throw new ShoppingCartBusinessException(MessageConstant.SHOPPING_CART_IS_NULL);}//2. 向订单表插入一条数据Orders orders = new Orders();BeanUtils.copyProperties(ordersSubmitDTO,orders);orders.setOrderTime(LocalDateTime.now());orders.setPayStatus(Orders.UN_PAID);orders.setStatus(Orders.PENDING_PAYMENT);orders.setNumber(String.valueOf(System.currentTimeMillis()));orders.setPhone(addressBook.getPhone());orders.setConsignee(addressBook.getConsignee()); //收货人orders.setUserId(userId);//orders.setAddress(addressBook.getDetail());orderMapper.insert(orders);List<OrderDetail> orderDetailList = new ArrayList<>();//3. 向订单明细表插入n条数据for(ShoppingCart cart:shoppingCartList){//订单明细OrderDetail orderDetail = new OrderDetail();BeanUtils.copyProperties(cart,orderDetail);//设置当前订单明细关联的订单idorderDetail.setOrderId(orders.getId());orderDetailList.add(orderDetail);}orderDetailMapper.insertBatch(orderDetailList);//4. 清空用户购物车数据shoppingCartMapper.deleteByUserId(userId);//5. 封装VO返回结果OrderSubmitVO orderSubmitVO = OrderSubmitVO.builder().id(orders.getId()).orderTime(orders.getOrderTime()).orderNumber(orders.getNumber()).orderAmount(orders.getAmount()).build();return orderSubmitVO;
}

3、在OrderMapper接口定义insert方法,插入数据到订单表中,在OrderMapper.xml文件中编写sql语句

<insert id="insert" useGeneratedKeys="true" keyProperty="id">insert into sky_take_out.orders(number, status, user_id, address_book_id, order_time, checkout_time,pay_method, pay_status, amount, remark, phone, address, user_name,consignee, cancel_reason, rejection_reason, cancel_time,estimated_delivery_time,delivery_status, delivery_time, pack_amount, tableware_number, tableware_status)VALUES(#{number}, #{status}, #{userId}, #{addressBookId}, #{orderTime}, #{checkoutTime},#{payMethod}, #{payStatus}, #{amount}, #{remark}, #{phone}, #{address}, #{userName},#{consignee}, #{cancelReason}, #{rejectionReason}, #{cancelTime}, #{estimatedDeliveryTime},#{deliveryStatus}, #{deliveryTime}, #{packAmount}, #{tablewareNumber}, #{tablewareStatus})
</insert>

4、在OrderDetailMapper接口定义insertBatch方法,批量插入订单明细数据,在OrderDetailMapper.xml文件中编写sql语句

<insert id="insertBatch">insert into sky_take_out.order_detail(name, image, order_id, dish_id, setmeal_id, dish_flavor, amount)VALUES<foreach collection="orderDetailList" item="od" separator=",">(#{od.name}, #{od.image}, #{od.orderId}, #{od.dishId}, #{od.setmealId}, #{od.dishFlavor}, #{od.amount})</foreach>
</insert>

二、订单支付

需要注册微信支付商户号获取微信支付平台证书、商户私钥文件
(https://pay.weixin.qq.com/static/product/product_index.shtml)
微信支付时序图
在这里插入图片描述
获取临时域名:支付成功后微信服务通过该域名回调我们的程序 (cplor)
这部分因为没有商家号,所以选择跳过相关操作,模拟实现支付功能,实现代码如下:
1、用户端(小程序):pay->index.json->支付详情(200多行)

// 支付详情handleSave: function handleSave() {var _this = this;if (this.timeout) {(0, _api.cancelOrder)(this.orderId).then(function (res) {});uni.redirectTo({url: '/pages/details/index?orderId=' + this.orderId });} else {// 如果支付成功进入成功页clearTimeout(this.times);var params = {orderNumber: this.orderDataInfo.orderNumber,payMethod: this.activeRadio === 0 ? 1 : 2 };(0, _api.paymentOrder)(params).then(function (res) {if (res.code === 1) {wx.showModal({title: '提示',content: '支付成功',success:function(){uni.redirectTo({url: '/pages/success/index?orderId=' + _this.orderId });}})console.log('支付成功!')//uni.redirectTo({url: '/pages/success/index?orderId=' + _this.orderId });} else {wx.showModal({title: '提示',content: res.msg})}});}}

2、管理端(idea)
(1)在OderController中定义payment方法实现订单支付

 @PutMapping("/payment")@ApiOperation("订单支付")public Result<OrderPaymentVO> payment(@RequestBody OrdersPaymentDTO ordersPaymentDTO) throws Exception {log.info("订单支付:{}", ordersPaymentDTO);OrderPaymentVO orderPaymentVO = orderService.payment(ordersPaymentDTO);log.info("生成预支付交易单:{}", orderPaymentVO);//模拟交易成功,修改订单状态orderService.paySuccess(ordersPaymentDTO.getOrderNumber());return Result.success(orderPaymentVO);}

(2)在orderService定义相关方法,在orderServiceImpl中实现
订单支付

public OrderPaymentVO payment(OrdersPaymentDTO ordersPaymentDTO) throws Exception {// 当前登录用户idLong userId = BaseContext.getCurrentId();User user = userMapper.getById(userId);//生成空jsonObjectJSONObject jsonObject = new JSONObject();if (jsonObject.getString("code") != null && jsonObject.getString("code").equals("ORDERPAID")) {throw new OrderBusinessException("该订单已支付");}OrderPaymentVO vo = jsonObject.toJavaObject(OrderPaymentVO.class);vo.setPackageStr(jsonObject.getString("package"));return vo;}

支付成功,修改订单状态

 public void paySuccess(String outTradeNo) {// 根据订单号查询订单Orders ordersDB = orderMapper.getByNumber(outTradeNo);// 根据订单id更新订单的状态、支付方式、支付状态、结账时间Orders orders = Orders.builder().id(ordersDB.getId()).status(Orders.TO_BE_CONFIRMED).payStatus(Orders.PAID).checkoutTime(LocalDateTime.now()).build();orderMapper.update(orders);//通过websocket向客户端浏览器推送消息 type orderId contentMap map = new HashMap();map.put("type",1);  //1表示来单提醒 2表示客户催单map.put("orderId",ordersDB.getId());map.put("content","订单号:"+outTradeNo);String json = JSON.toJSONString(map);webSocketServer.sendToAllClient(json);}

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

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

相关文章

基于SSM+Vue的护工预约服务小程序和后台管理系统

1、系统演示视频&#xff08;演示视频&#xff09; 2、需要请联系

虚拟化+Docker基本管理

一、虚拟化简介 1、云端 华为云、谷歌云、腾讯云、阿里云、亚马逊、百度云、移动云、天翼云、西部数码云等 1.国内云 华为云、阿里云、腾讯云、天翼云(私有云) 2.国外云 谷歌云、亚马逊 2、云计算的服务模式是分层的 IaaS&#xff1a;Infrastructure&#xff08;基础设…

计算机网络【CN】Ch3 数据链路层

目录 数据链路层的功能 【※】VLAN 三种划分VLAN的方法&#xff1a; 【※】MAC帧格式 【※】三种可靠传输机制 ​编辑 【※】介质访问控制 信道划分介质访问控制 随机介质访问控制 CSMA CSMA/CD【有线】 CSMA/CA【无线】 信道利用率技巧 循环冗余校验CRC 以太网[802.3] 以太网…

项目实战 | 责任链模式 (下)

案例二&#xff1a;工作流&#xff0c;费用报销审核流程 同事小贾最近刚出差回来&#xff0c;她迫不及待的就提交了费用报销的流程。根据金额不同&#xff0c;分为以下几种审核流程。报销金额低于1000元&#xff0c;三级部门管理者审批即可&#xff0c;1000到5000元除了三级部…

智己汽车数据驱动中心PMO高级经理张晶女士受邀为第十三届中国PMO大会演讲嘉宾

全国PMO专业人士年度盛会 智己汽车科技有限公司数据驱动中心PMO高级经理张晶女士受邀为PMO评论主办的2024第十三届中国PMO大会演讲嘉宾&#xff0c;演讲议题为“规模化敏捷落地实践”。大会将于5月25-26日在北京举办&#xff0c;敬请关注&#xff01; 议题简要&#xff1a; 2…

【Java学习笔记】9.5 Java中的Lambda表达式

Lambda表达式是从Java8版本开始增加的语法。Lambda表达式有利于实现函数式编程&#xff0c;简化开发。 9.5.1 Lambda表达式入门 Lambda表达式由三部分组成&#xff1a;参数列表、箭头(->),及一个表达式或语句块。其完整的语法格式如下&#xff1a; (Type 1 param1 , Type…

hcip实验 — 路由策略实验

目录 实验拓扑 实验要求 实验思路 实验步骤 1.配置接口及环回ip 2.配置ospf协议及rip协议 3.在R2上进行路由引入 4.在R2上进行路由过滤 5.在R4上进行路由过滤&#xff08;地址前缀列表&#xff09; 6.在R2 RIP进程上配置静默接口使RIP报文无法进入OSPF区域 实验拓扑 …

HCF-Net:用于红外小目标检测的分层上下文融合网络

摘要 红外小目标检测是一项重要的计算机视觉任务&#xff0c;涉及在红外图像中识别和定位微小物体&#xff0c;这些物体通常仅包含几个像素。然而&#xff0c;由于物体尺寸极小以及红外图像中通常复杂的背景&#xff0c;这项任务面临困难。在本文中&#xff0c;我们提出了一种…

贪吃蛇代码实现

一.基本信息 实现目标&#xff1a;使用C语言在Windows环境的控制台中实现贪吃蛇游戏 游戏运行&#xff1a; 地图绘制基本玩法提示信息游戏的开始与结束 基本玩法&#xff1a; 通过上下左右键控制蛇的移动蛇可以加速减速吃掉食物可以得分并增加蛇的长度可以自动暂停 游戏结…

代码随想录算法训练营第三十四天|1005.K次取反后最大化的数组和、134. 加油站、135. 分发糖果

1005.K次取反后最大化的数组和 思路&#xff1a; 贪心的思路&#xff0c;局部最优&#xff1a;让绝对值大的负数变为正数&#xff0c;当前数值达到最大&#xff0c;整体最优&#xff1a;整个数组和达到最大。 局部最优可以推出全局最优。 那么如果将负数都转变为正数了&…

SAP DMS后台配置(4)

当DMS和CS文档服务器关联的时候,除了需要BASIS进行相关的配置以外,我们DMS也要进行相关的系统配置 路径:SPRO—跨应用组件—文档管理—常规数据—存储系统设置—维护还原系统 路径:SPRO—跨应用组件—文档管理—常规数据—存储系统设置—维护还原类别 当DMS和CS文档服…

HarmonyOS开发实例:【图片编辑应用】

介绍 本篇Codelab通过动态设置元素样式的方式&#xff0c;实现几种常见的图片操作&#xff0c;包括裁剪、旋转、缩放和镜像。效果如图所示&#xff1a; 相关概念 [image组件]&#xff1a;图片组件&#xff0c;用来渲染展示图片。[div组件]&#xff1a;基础容器组件&#xff0…

VMware虚拟机安装CentOS详细教程

前言 最近小白发现&#xff0c;有很多小伙伴在学习过程中都需要配置CentOS的系统&#xff0c;因此决定更新一篇在VMware虚拟机上安装CentOS的教程。 小白最近也去看了一下各种云的服务商出租的服务器&#xff0c;其中可选的系统中也有包括CentOS&#xff0c;所以在VMware配置…

用python做傅里叶变换和系统辨识

一、原始信号 1、理想数据 &#xff08;1&#xff09;系统参数 参数类型数值J0.5 k g ∗ m 2 kg*m^2 kg∗m2K0.2b5 &#xff08;2&#xff09;激励曲线 import matplotlib.pyplot as plt import numpy as np# 生成数据 x np.linspace(0, 10, 1000) # 生成0到10之间的100…

Midjourney与waifu2x双剑合璧:完美打造超高清动漫图像

在追求完美的动漫图像时&#xff0c;质量和分辨率是两个关键因素。Midjourney&#xff08;一个神秘而强大的AI图像生成工具&#xff09;与waifu2x&#xff08;一个专门用于放大动漫风格图像的AI工具&#xff09;的结合使得创造超高清的动漫图像变得触手可及。本文将引导您如何使…

【C++】---STL之vector详解

【C】---STL之vector详解 一、vector的介绍&#xff1a;二、vector的成员函数&#xff1a;1、vector类的构造函数2、vector的元素访问符3、vector的迭代器4、vector的模版5、vector的拷贝构造6、vector的容量&#xff08;1&#xff09;vector的增容机制&#xff08;2&#xff0…

Spring的过滤器、拦截器、切面区别及案例分析

Spring的过滤器、拦截器、切面 三者的区别&#xff0c;以及对应案例分析 一、三者的实现方式 1.1 过滤器 xxxFilter 过滤器的配置比较简单&#xff0c;直接实现Filter接口即可&#xff0c;也可以通过WebFilter注解实现对特定URL的拦截&#xff0c;Filter接口中定义了三个方法…

告别数据丢失,轻松掌握文件自动备份秘籍

在这个数字化高速发展的时代&#xff0c;我们的工作和生活都离不开电脑&#xff0c;而电脑中存储的文件和数据更是至关重要。然而&#xff0c;数据丢失的风险无处不在&#xff0c;可能因为硬件故障、软件崩溃、病毒攻击等原因而导致重要文件丢失。因此&#xff0c;文件自动备份…

Abaqus三维晶体塑性Voronoi泰森多边形晶格建模插件

插件介绍 AbyssFish Voronoi2D&3D 3D V3.0 插件可对Abaqus内已进行网格划分的部件&#xff08;Part&#xff09;生成Voronoi泰森多边形区块。插件可对任意形状的二维或三维部件、任意特征&#xff08;实体或壳&#xff09;、任意单元形状进行指派Voronoi晶格&#xff0c;可…

【STM32F4】按键开关

上一章&#xff0c;我们介绍了STM32F4的IO口作为输出的使用&#xff0c;这一章&#xff0c;将向大家介绍如何使用按键作为输入使用。 &#xff08;一&#xff09;硬件连接 根据正点原子的stm32f4阿波罗开发板&#xff0c;可以看见 按键KEY0连接在PH3上、 KEY1连接在PH2上、 …