当前位置: 首页 > news >正文

苍穹外卖day8

用户下单

导入地址簿

需求分析

需要实现的功能如图一

  • 新增地址:
    • 与新增员工相似,将用户id,信息等插入数据库
  • 查询所有信息
    • 根据用户id查询用户所有地址信息
  • 查询默认地址
    • 查询当前用户default为1的地址
  • 根据id修改地址
    • 接收前端传入地址更新数据库中的内容
  • 根据id删除地址
    • 根据主键id删除数据库的地址
  • 根据id查询地址
    • 根据主键id查询地址
  • 设置默认地址
    • 根据主键id更新default

Controller

packagecom.sky.controller.user;importcom.sky.context.BaseContext;importcom.sky.entity.AddressBook;importcom.sky.result.Result;importcom.sky.service.AddressBookService;importio.swagger.annotations.Api;importio.swagger.annotations.ApiOperation;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.*;importjava.util.List;@RestController@RequestMapping("/user/addressBook")@Api(tags="C端地址簿接口")publicclassAddressBookController{@AutowiredprivateAddressBookServiceaddressBookService;/** * 查询当前登录用户的所有地址信息 * * @return */@GetMapping("/list")@ApiOperation("查询当前登录用户的所有地址信息")publicResult<List<AddressBook>>list(){AddressBookaddressBook=newAddressBook();addressBook.setUserId(BaseContext.getCurrentId());List<AddressBook>list=addressBookService.list(addressBook);returnResult.success(list);}/** * 新增地址 * * @param addressBook * @return */@PostMapping@ApiOperation("新增地址")publicResultsave(@RequestBodyAddressBookaddressBook){addressBookService.save(addressBook);returnResult.success();}@GetMapping("/{id}")@ApiOperation("根据id查询地址")publicResult<AddressBook>getById(@PathVariableLongid){AddressBookaddressBook=addressBookService.getById(id);returnResult.success(addressBook);}/** * 根据id修改地址 * * @param addressBook * @return */@PutMapping@ApiOperation("根据id修改地址")publicResultupdate(@RequestBodyAddressBookaddressBook){addressBookService.update(addressBook);returnResult.success();}/** * 设置默认地址 * * @param addressBook * @return */@PutMapping("/default")@ApiOperation("设置默认地址")publicResultsetDefault(@RequestBodyAddressBookaddressBook){addressBookService.setDefault(addressBook);returnResult.success();}/** * 根据id删除地址 * * @param id * @return */@DeleteMapping@ApiOperation("根据id删除地址")publicResultdeleteById(Longid){addressBookService.deleteById(id);returnResult.success();}/** * 查询默认地址 */@GetMapping("default")@ApiOperation("查询默认地址")publicResult<AddressBook>getDefault(){//SQL:select * from address_book where user_id = ? and is_default = 1AddressBookaddressBook=newAddressBook();addressBook.setIsDefault(1);addressBook.setUserId(BaseContext.getCurrentId());List<AddressBook>list=addressBookService.list(addressBook);if(list!=null&&list.size()==1){returnResult.success(list.get(0));}returnResult.error("没有查询到默认地址");}}

Service实现类

packagecom.sky.service.impl;importcom.sky.context.BaseContext;importcom.sky.entity.AddressBook;importcom.sky.mapper.AddressBookMapper;importcom.sky.service.AddressBookService;importlombok.extern.slf4j.Slf4j;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;importorg.springframework.transaction.annotation.Transactional;importjava.util.List;@Service@Slf4jpublicclassAddressBookServiceImplimplementsAddressBookService{@AutowiredprivateAddressBookMapperaddressBookMapper;/** * 条件查询 * * @param addressBook * @return */publicList<AddressBook>list(AddressBookaddressBook){returnaddressBookMapper.list(addressBook);}/** * 新增地址 * * @param addressBook */publicvoidsave(AddressBookaddressBook){addressBook.setUserId(BaseContext.getCurrentId());addressBook.setIsDefault(0);addressBookMapper.insert(addressBook);}/** * 根据id查询 * * @param id * @return */publicAddressBookgetById(Longid){AddressBookaddressBook=addressBookMapper.getById(id);returnaddressBook;}/** * 根据id修改地址 * * @param addressBook */publicvoidupdate(AddressBookaddressBook){addressBookMapper.update(addressBook);}/** * 设置默认地址 * * @param addressBook */@TransactionalpublicvoidsetDefault(AddressBookaddressBook){//1、将当前用户的所有地址修改为非默认地址 update address_book set is_default = ? where user_id = ?addressBook.setIsDefault(0);addressBook.setUserId(BaseContext.getCurrentId());addressBookMapper.updateIsDefaultByUserId(addressBook);//2、将当前地址改为默认地址 update address_book set is_default = ? where id = ?addressBook.setIsDefault(1);addressBookMapper.update(addressBook);}/** * 根据id删除地址 * * @param id */publicvoiddeleteById(Longid){addressBookMapper.deleteById(id);}}

Mapper

packagecom.sky.mapper;importcom.sky.entity.AddressBook;importorg.apache.ibatis.annotations.*;importjava.util.List;@MapperpublicinterfaceAddressBookMapper{/** * 条件查询 * @param addressBook * @return */List<AddressBook>list(AddressBookaddressBook);/** * 新增 * @param addressBook */@Insert("insert into address_book"+" (user_id, consignee, phone, sex, province_code, province_name, city_code, city_name, district_code,"+" district_name, detail, label, is_default)"+" values (#{userId}, #{consignee}, #{phone}, #{sex}, #{provinceCode}, #{provinceName}, #{cityCode}, #{cityName},"+" #{districtCode}, #{districtName}, #{detail}, #{label}, #{isDefault})")voidinsert(AddressBookaddressBook);/** * 根据id查询 * @param id * @return */@Select("select * from address_book where id = #{id}")AddressBookgetById(Longid);/** * 根据id修改 * @param addressBook */voidupdate(AddressBookaddressBook);/** * 根据 用户id修改 是否默认地址 * @param addressBook */@Update("update address_book set is_default = #{isDefault} where user_id = #{userId}")voidupdateIsDefaultByUserId(AddressBookaddressBook);/** * 根据id删除地址 * @param id */@Delete("delete from address_book where id = #{id}")voiddeleteById(Longid);}
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPEmapperPUBLIC"-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mappernamespace="com.sky.mapper.AddressBookMapper"><selectid="list"parameterType="AddressBook"resultType="AddressBook">select * from address_book<where><iftest="userId != null">and user_id = #{userId}</if><iftest="phone != null">and phone = #{phone}</if><iftest="isDefault != null">and is_default = #{isDefault}</if></where></select><updateid="update"parameterType="addressBook">update address_book<set><iftest="consignee != null">consignee = #{consignee},</if><iftest="sex != null">sex = #{sex},</if><iftest="phone != null">phone = #{phone},</if><iftest="detail != null">detail = #{detail},</if><iftest="label != null">label = #{label},</if><iftest="isDefault != null">is_default = #{isDefault},</if></set>where id = #{id}</update></mapper>

接口文档与需求分析

此时用到了两张表,orders以及order_detail

orders表记录用户下单的完整流程,下单,支付,派送

order_detail表记录下单菜品信息,金额,图片,下单数量

后端需要接收前端的传入的数据,并用传入的地址簿查询其他信息存入orders中,并进行初始设置

Controller

/** * 用户下单 * @param ordersSubmitDTO * @return */@PostMapping("/submit")@ApiOperation("用户下单")publicResult<OrderSubmitVO>submit(@RequestBodyOrdersSubmitDTOordersSubmitDTO){log.info("用户订单信息:{}",ordersSubmitDTO);OrderSubmitVOorderSubmitVO=orderService.submit(ordersSubmitDTO);returnResult.success(orderSubmitVO);}

接收前端DTO交给逻辑层处理

Service实现类

逻辑层需要实现的内容:

  • 根据传入的DTO中的地址簿信息查询地址簿
  • 获取当前用户并获取购物车数据
  • 插入订单数据,将前端传入的金额等浅克隆,设置订单支付状态为未支付,状态为等待支付,用当前时间戳设置单号(姑且这么办)设置用户手机号,用户id,用户名称
  • 设置订单的基础信息并存入数据库
  • 清空购物车
  • 封装前端需要返回的内容为VO对象返回
/** * 用户下单 * @param ordersSubmitDTO * @return */publicOrderSubmitVOsubmit(OrdersSubmitDTOordersSubmitDTO){//处理各种业务异常(地址簿为空,购物车数据为空)AddressBookaddressBook=addressBookMapper.getById(ordersSubmitDTO.getAddressBookId());if(addressBook==null){thrownewAddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);}LonguserId=BaseContext.getCurrentId();ShoppingCartshoppingCart=newShoppingCart();shoppingCart.setUserId(userId);List<ShoppingCart>list=shoppingCartMapper.list(shoppingCart);if(list==null||list.isEmpty()){//抛出业务异常thrownewShoppingCartBusinessException(MessageConstant.SHOPPING_CART_IS_NULL);}//插入一条订单数据Ordersorders=newOrders();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);orderMapper.insert(orders);List<OrderDetail>orderDetailList=newArrayList<>();//向订单明细表插入n条数据for(ShoppingCartcart:list){OrderDetailorderDetail=newOrderDetail();BeanUtils.copyProperties(cart,orderDetail);orderDetail.setOrderId(orders.getId());orderDetailList.add(orderDetail);}orderDetailMapper.insertBatch(orderDetailList);//清空购物车shoppingCartMapper.clean(userId);//封装VO对象返回前端returnOrderSubmitVO.builder().id(orders.getId()).orderNumber(orders.getNumber()).orderAmount(orders.getAmount()).orderTime(orders.getOrderTime()).build();}

Mapper

批量插入订单基础信息

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

清空购物车

@Delete("delete from shopping_cart where user_id=#{userId}")voidclean(LonguserId);

微信小程序下单

流程简述

1. 初始下单阶段

此处为用户点击去下单确认支付的阶段

  • 进入下单:微信用户通过微信小程序发起下单请求。
  • 创建订单:小程序向商户系统发送下单指令。
  • 返回信息:商户系统处理后,返回订单号等相关信息给小程序。

2. 支付申请与预处理阶段

此处为点击确认支付后阶段

  • 申请支付:小程序向商户系统发起微信支付申请。
  • 预下单:商户系统调用微信后台的下单接口。
  • 获取标识:微信后台返回预支付交易标识给商户系统。
  • 签名处理:商户系统对数据进行再次签名,并将支付参数返回给小程序。

3. 用户确认与执行支付阶段

此处为支付完成后阶段

  • 确认支付:微信用户在小程序端确认支付。
  • 调起支付:小程序调起微信支付功能并请求微信后台执行。
  • 返回结果:微信后台将支付结果反馈给小程序。

4. 结果展示与状态更新阶段

此处为支付成功后回显订单阶段

  • 结果显示:小程序向用户展示最终的支付结果。
  • 后台通知:与此同时,微信后台将支付结果推送给商户系统。
  • 更新状态:商户系统根据接收到的结果更新内部订单状态。

接口文档

代码实现

Controller

接收前端传入单号以及支付方式,交付给service处理

/** * 订单支付 * * @param ordersPaymentDTO * @return */@PutMapping("/payment")@ApiOperation("订单支付")publicResult<OrderPaymentVO>payment(@RequestBodyOrdersPaymentDTOordersPaymentDTO)throwsException{log.info("订单支付:{}",ordersPaymentDTO);OrderPaymentVOorderPaymentVO=orderService.payment(ordersPaymentDTO);log.info("生成预支付交易单:{}",orderPaymentVO);returnResult.success(orderPaymentVO);}

Service实现类

下单后按照流程此时为调用下单接口,将返回的prepay_id给开发者服务器作为预支付交易会话标识,后端进一步进行签名加密。由于只有企业才可获得mchid,如果实现支付可以将VO按如下方式封装后返回给前端,虽然有内容但是并没有实质内容

/** * 订单支付 * @param ordersPaymentDTO * @return */publicOrderPaymentVOpayment(OrdersPaymentDTOordersPaymentDTO)throwsException{// 当前登录用户idLonguserId=BaseContext.getCurrentId();Useruser=userMapper.getById(userId);// 模拟支付数据OrderPaymentVOvo=newOrderPaymentVO();vo.setNonceStr("testNonceStr");vo.setPaySign("testPaySign");vo.setTimeStamp(String.valueOf(System.currentTimeMillis()));vo.setSignType("RSA");vo.setPackageStr("prepay_id=test");paySuccess(ordersPaymentDTO.getOrderNumber());returnvo;}

总结

实现了用户下单,微信支付。在用户下单方面按照需要实现的功能独立实现了大部分内容,但是有一部分内容没有分析出,比如清空购物车;实现微信支付,了解了微信支付流程,对于后端支付有了进一步的认识。最后的支付代码由ai修改为当前形式。

学习了cpolar,用于将本地运行的springboot程序映射到公网域名,可以通过公网URL访问前端

http://www.jsqmd.com/news/818173/

相关文章:

  • 通过cmdline-jmxclient.jar采集TongWeb8.0监控值
  • 安顺制造业工厂如何做线上全网获客?2026年GEO优化与AI搜索推广指南 - 年度推荐企业名录
  • 别再一张张手动改了!用Python脚本批量解密微信PC版dat图片(附完整代码)
  • 红牛肝哪家好:此山中野生菌上乘臻品 - 17329971652
  • 别再“氛围编程”:Matt Pocock Skills 如何把 AI Agent 拉回真实工程
  • 3步搞定Live2D模型提取:UnityLive2DExtractor完整指南
  • MCP服务器集合:为AI编辑器注入本地环境访问与记忆能力
  • 基于YOLO与PyTorch的零售货架智能分析系统:从原理到部署实战
  • 全域矩阵系统增长引擎:自动化流程编排与事件驱动营销技术实践
  • Kafka 核心组件及其作用(全解)
  • 红菇哪家好:此山中野生菌地道精纯 - 13724980961
  • 3个简单步骤掌握NVIDIA Profile Inspector:解锁显卡隐藏性能的完整指南
  • 什么是模力方舟与口袋龙虾?开源中国的AI生态双核战略解析
  • 六盘水制造业工厂如何做线上全网获客?2026年AI搜索推广与GEO优化指南 - 年度推荐企业名录
  • 为树莓派Pico添加CAN总线通信:从硬件选型到软件调试全攻略
  • 英雄联盟终极游戏助手:LeagueAkari完全指南
  • 《Agent设计模式》 学习笔记
  • UI/UX设计师生产力革命:从Design Tokens到自动化交付的全链路工作流
  • 谷歌面试官:“以后面试都允许用 Gemini。” 我:“那还考什么?” 面试官:“考你会不会被 AI 带沟里。”
  • CircuitPython嵌入式开发实战:从macOS环境配置到硬件调试全攻略
  • 松茸哪家好:此山中野生菌顶级正宗 - 17322238651
  • 中小型创业公司如何利用Taotoken多模型能力支撑产品迭代
  • 智能对话机器人架构解析:从状态管理到工具调用的工程实践
  • 2026北京性价比高的AI优化公司推荐 - 余小铁
  • AI浪潮下的“卖铲子”生意:API中转站暴利背后藏多少猫腻?
  • 2026年主流项目管理工具选型指南:聚焦技术驱动与本土化协作
  • 拯救Turnitin标蓝:实测英文论文AI率降至20%以下的5大方法(附工具测评)
  • 在Linux Centos7上部署DNS服务——主从架构
  • 竹荪哪家好:此山中野生菌纯净优质 - 13425704091
  • NVIDIA Profile Inspector:解锁显卡隐藏性能的终极调校工具