
导入地址簿功能代码代码已上传用户下单需求分析和设计流程接口设计数据库设计订单表和订单明细表的关系一对多代码开发DTOVO小程序提交下单 JSON → Controller 接收封装 OrdersSubmitDTO → 调用 service.submitOrder → service 校验地址、购物车组装 Orders 实体插入主表遍历购物车组装明细批量插入清空购物车组装 OrderSubmitVO 返回 → Controller 包装 Result 返回小程序。OrderController/** * 订单 */ RestController(userOrderController) RequestMapping(/user/order) Slf4j Api(tags C端-订单接口) public class OrderController { Autowired private OrderService orderService; /** * 用户下单 * * param ordersSubmitDTO * return */ PostMapping(/submit) ApiOperation(用户下单) public ResultOrderSubmitVO submit(RequestBody OrdersSubmitDTO ordersSubmitDTO) { log.info(用户下单{}, ordersSubmitDTO); OrderSubmitVO orderSubmitVO orderService.submitOrder(ordersSubmitDTO); return Result.success(orderSubmitVO); } }OrderServicepublic interface OrderService { /** * 用户下单 * param ordersSubmitDTO * return */ OrderSubmitVO submitOrder(OrdersSubmitDTO ordersSubmitDTO); }OrderServiceImpl/** * 订单 */ Service //把当前实现类交给Spring容器管理Controller才能注入OrderService Slf4j //lombok生成log日志对象本方法没写log但是类上加了 public class OrderServiceImpl implements OrderService { //注入各个mapper操作不同数据表 Autowired private OrderMapper orderMapper; //操作订单主表 orders Autowired private OrderDetailMapper orderDetailMapper; //操作订单明细表 order_detail Autowired private ShoppingCartMapper shoppingCartMapper; //操作购物车表 shopping_cart Autowired private AddressBookMapper addressBookMapper; //操作地址簿表 addressBook /** * 用户下单 * * param ordersSubmitDTO controller传过来的【DTO入参】小程序提交下单的json数据 * return OrderSubmitVO 返回给controller最后给到小程序前端 */ Transactional //✅重点事务这一整个方法里面所有数据库操作要么全部成功要么全部失败回滚 public OrderSubmitVO submitOrder(OrdersSubmitDTO ordersSubmitDTO) { // 第一步各种异常校验下单之前先判断条件是否合法 //根据地址id查询收货地址DTO里面传过来addressBookId用户选的收货地址id AddressBook addressBook addressBookMapper.getById(ordersSubmitDTO.getAddressBookId()); //地址查不到说明地址已经被删除不能下单抛自定义业务异常 if (addressBook null) { throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL); } //从ThreadLocal获取当前登录小程序用户的userIdBaseContext拦截器存进去的 Long userId BaseContext.getCurrentId(); //构建购物车查询条件对象 ShoppingCart shoppingCart new ShoppingCart(); shoppingCart.setUserId(userId); //查询该用户全部购物车商品 ListShoppingCart shoppingCartList shoppingCartMapper.list(shoppingCart); //如果购物车为空抛出异常不让下单 if (shoppingCartList null || shoppingCartList.size() 0) { throw new ShoppingCartBusinessException(MessageConstant.SHOPPING_CART_IS_NULL); } // 第二步组装订单主表实体 Orders实体类对应数据库orders表 Orders order new Orders(); //属性拷贝把DTO里面的字段复制到order实体。DTO来自前端但是缺少数据库需要的部分字段 BeanUtils.copyProperties(ordersSubmitDTO,order); //从查询出来的addressBook地址对象补全订单缺少的字段DTO不带这些信息 order.setPhone(addressBook.getPhone()); //收货人手机号 order.setAddress(addressBook.getDetail()); //收货详细地址你注释写老师少写这行不写数据库地址为空 order.setConsignee(addressBook.getConsignee()); //收货人姓名 order.setNumber(String.valueOf(System.currentTimeMillis()));//订单号用当前时间毫秒值充当唯一订单编号 order.setUserId(userId); //下单用户id order.setStatus(Orders.PENDING_PAYMENT); //订单状态待付款 order.setPayStatus(Orders.UN_PAID); //支付状态未支付 order.setOrderTime(LocalDateTime.now()); //下单时间取系统当前时间 //向订单主表插入一条记录插入之后order对象会回填数据库自增主键idorder.getId()才能拿到订单id orderMapper.insert(order); // 第三步组装订单明细一个订单对应多条明细购物车每一条就是一条订单明细 ListOrderDetail orderDetailList new ArrayList(); //遍历购物车全部商品 for (ShoppingCart cart : shoppingCartList) { OrderDetail orderDetail new OrderDetail(); BeanUtils.copyProperties(cart, orderDetail); //把购物车数据拷贝到订单明细实体 orderDetail.setOrderId(order.getId()); //⭐关键给每一条明细设置所属订单id就是上面刚插入的订单主键 orderDetailList.add(orderDetail); } //批量插入多条订单明细 orderDetailMapper.insertBatch(orderDetailList); // 第四步下单成功清空该用户的购物车 shoppingCartMapper.deleteByUserId(userId); // 第五步封装VO返回给上层ControllerVO是给前端展示用的 //builder构建者模式构建OrderSubmitVOVO不需要全部数据库字段只返回小程序需要的几个字段 OrderSubmitVO orderSubmitVO OrderSubmitVO.builder() .id(order.getId()) //订单id .orderNumber(order.getNumber()) //订单编号 .orderAmount(order.getAmount()) //订单总金额 .orderTime(order.getOrderTime()) //下单时间 .build(); return orderSubmitVO; } }OrderMapperMapper public interface OrderMapper { /** * 插入订单数据 * param order */ void insert(Orders order); }OrderMapper.xmlmapper namespacecom.sky.mapper.OrderMapper insert idinsert parameterTypeOrders useGeneratedKeystrue keyPropertyid insert into orders (number, status, user_id, address_book_id, order_time, checkout_time, pay_method, pay_status, amount, remark, phone, address, consignee, estimated_delivery_time, delivery_status, pack_amount, tableware_number, tableware_status) values (#{number}, #{status}, #{userId}, #{addressBookId}, #{orderTime}, #{checkoutTime}, #{payMethod}, #{payStatus}, #{amount}, #{remark}, #{phone}, #{address}, #{consignee}, #{estimatedDeliveryTime}, #{deliveryStatus}, #{packAmount}, #{tablewareNumber}, #{tablewareStatus}) /insert /mapperOrderDetailMapperMapper public interface OrderDetailMapper { /** * 批量插入订单明细数据 * param orderDetails */ void insertBatch(ListOrderDetail orderDetails); }OrderDetailMapper.xmlmapper namespacecom.sky.mapper.OrderDetailMapper insert idinsertBatch parameterTypelist insert into order_detail (name, order_id, dish_id, setmeal_id, dish_flavor, number, amount, image) values foreach collectionorderDetails itemod separator, (#{od.name},#{od.orderId},#{od.dishId},#{od.setmealId},#{od.dishFlavor}, #{od.number},#{od.amount},#{od.image}) /foreach /insert /mapper订单支付微信支付流程跳过微信支付这一步我是照着Purse Wind这个博主操作的微信开发者工具里面找到pages/pay/index.js找到这一段代码修改的跟我一样保存并且重新编译导入微信支付功能代码已上传修改OrderServiceImpl如下public OrderPaymentVO payment(OrdersPaymentDTO ordersPaymentDTO) throws Exception { // // 当前登录用户id // Long userId BaseContext.getCurrentId(); // User user userMapper.getById(userId); // // //调用微信支付接口生成预支付交易单 // JSONObject jsonObject weChatPayUtil.pay( // ordersPaymentDTO.getOrderNumber(), //商户订单号 // new BigDecimal(0.01), //支付金额单位 元 // 苍穹外卖订单, //商品描述 // user.getOpenid() //微信用户的openid // ); // // 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; log.info(跳过微信支付支付成功); paySuccess(ordersPaymentDTO.getOrderNumber()); return new OrderPaymentVO(); }测试通过