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

embedded/2024/10/22 14:24:35/

文章目录

  • 前言
  • 一、用户下单
    • 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.ppmy.cn/embedded/10535.html

相关文章

【二轮征稿】经济金融发展国际会议(ICEFD 2024)

一、【会议简介】 经济金融发展国际会议(ICEFD 2024)将于2024年4月26-28日在长沙盛大举行。会议旨在为从事国际社会经济金融发展研究的专家学者提供一个共享科研成果和前沿技术&#xff0c;了解学术发展趋势&#xff0c;拓宽研究思路&#xff0c;加强学术研究和探讨&#xff0c…

【第五章】Java API-常用类库(上)

目录 1.字符串 String 1.1 不可变性&#xff08;Immutability&#xff09; 1.2 字符串常用方法 1.3 字符串常用方法举例 1.4 字符串 String——编程练习 2.基本类型与包装类型 2.1 包装类型 ( Wrapper Class) 2.2 基本类型和包装类型的转换&#xff1a; 2.3 包装类的作…

第十、十一章 折线图 + 地图 + 柱状图的绘制

第十章 折线图的绘制 官网&#xff1a;pyecharts - A Python Echarts Plotting Library built with love. 画廊官网&#xff1a;Document 懒人工具&#xff1a;懒人工具-手机APP工具下载-手机软件下载大全 - 173软件站 (ab173.com) 导学 json 定义 &#xff08;1&#xff…

数据可视化(五):Pandas高级统计——函数映射、数据结构、分组聚合等问题解决,能否成为你的工作备用锦囊?

Tips&#xff1a;"分享是快乐的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不仅有知识的海洋&#x1f30a;&#xff0c;还有满满的正能量加持&#x1f4aa;&#xff0c;快来和我一起分享这份快乐吧&#x1f60a;&#xff01; 喜欢我的博客的话&#xff0c;记得…

Linux i2c-tool工具基础使用

一.i2cdetect i2cdetect 是一个用户空间程序&#xff0c;用于扫描 I2C 总线上的设备。它输出一个表格&#xff0c;其中包含指定总线上检测到的设备列表。以下是 i2cdetect 的使用方法&#xff1a; 运行扫描&#xff1a; 要执行 I2C 扫描&#xff0c;请使用以下命令&#xff1…

【GD32】_时钟架构及系统时钟频率配置

文章目录 一、有关时钟源二、系统时钟架构三、时钟树分析四、修改参数步骤1、设置外部晶振2、选择外部时钟源。3、 设置系统主频率大小4、修改PLL分频倍频系数 学习系统时钟架构和时钟树&#xff0c;验证及学习笔记如下&#xff0c;如有错误&#xff0c;欢迎指正。主要记录了总…

分布式与微服务的区别

首先分布式是一种系统部署模式&#xff0c;将一个系统分成多个不分进行运行。而微服务架构是一种更加精细化的设计方法&#xff0c;它是分布式的一个分支&#xff0c;主要强调将一个单体应用拆分成一组小型松耦合的服务&#xff0c;每个服务专注于单一业务功能并能够独立部署和…

仓储管理解决方案:混合低代码与定制开发,实现高灵活性与高效率

引言 在当今竞争激烈的商业环境中&#xff0c;仓储管理成为了企业供应链中不可或缺的一环。有效的仓储管理不仅可以帮助企业降低库存成本、提高库存周转率&#xff0c;还能够提升客户满意度和整体运营效率。然而&#xff0c;随着市场需求的不断变化和业务规模的不断扩大&#…