【项目实战 Day8】springboot + vue 苍穹外卖系统(地址簿模块 + 用户下单模块 + 微信支付模块代码导入 完结)
苍穹外卖项目开发训练day8内容,包含【地址簿模块】、【用户下单模块】、【微信支付模块】的代码开发内容,保姆级笔记教程!
目录
一、地址簿模块
1、新增地址 - POST接口
【1】controller层
/** * 新增地址 * @param addressBook * @return */ @PostMapping @ApiOperation("新增地址") public Result add(@RequestBody AddressBook addressBook){ log.info("新增地址:{}",addressBook); addressBookService.addAddress(addressBook); return Result.success(); }【2】service层
1、绑定当前用户id
2、将新增地址改为非默认地址
/** * 新增地址 * @param addressBook */ public void addAddress(AddressBook addressBook) { //绑定当前用户id addressBook.setUserId(BaseContext.getCurrentId()); //刚开始不设置为默认地址 addressBook.setIsDefault(0); addressBookMapper.insert(addressBook); }【3】mapper层
/** * 新增地址 * @param addressBook */ @Insert("insert into sky_take_out.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})") void insert(AddressBook addressBook);
2、查询当前用户的所有地址 - GET接口
【1】controller层
/** * 查询当前用户的所有地址信息 * @return */ @GetMapping("/list") @ApiOperation("查询当前用户的所有地址信息") public Result<List<AddressBook>> list(){ List<AddressBook> addressBookList = addressBookService.list(); return Result.success(addressBookList); }【2】service层
/** * 条件查询 * @return */ public List<AddressBook> list(AddressBook addressBook) { List<AddressBook> addressBookList = addressBookMapper.list(addressBook); return addressBookList; }【3】mapper层
/** * 条件查询 * @param addressBook * @return */ List<AddressBook> list(AddressBook addressBook);【4】mybatis文件
<select id="list" resultType="com.sky.entity.AddressBook"> select * from sky_take_out.address_book <where> <if test="userId != null"> and user_id = #{userId}</if> <if test="phone != null"> and phone = #{phone}</if> <if test="isDefault != null"> and is_default = #{isDefault}</if> </where> </select>
3、根据id查询地址 - GET接口
【1】controller层
/** * 根据id查询地址 * @param id * @return */ @GetMapping("/{id}") @ApiOperation("根据id查询地址") public Result<AddressBook> getById(@PathVariable Long id){ AddressBook addressBook = addressBookService.getById(id); return Result.success(addressBook); }【2】service层
/** * 根据id查询地址 * @param id * @return */ public AddressBook getById(Long id) { AddressBook addressBook = addressBookMapper.getById(id); return addressBook; }【3】mapper层
/** * 根据id查询地址 * @param id * @return */ @Select("select * from sky_take_out.address_book where id = #{id}") AddressBook getById(Long id);
4、根据id修改地址 - PUT接口
【1】controller层
/** * 根据id修改地址 * @param addressBook * @return */ @PutMapping @ApiOperation("根据id修改地址") public Result update(@RequestBody AddressBook addressBook){ log.info("修改地址:{}",addressBook.getId()); addressBookService.update(addressBook); return Result.success(); }【2】service层
/** * 根据id修改地址 * @param addressBook */ public void update(AddressBook addressBook) { addressBookMapper.update(addressBook); }【3】mapper层
/** * 修改地址 * @param addressBook */ void update(AddressBook addressBook);【4】mybatis文件
<update id="update" parameterType="addressBook"> update sky_take_out.address_book <set> <if test="consignee != null"> consignee = #{consignee}, </if> <if test="sex != null"> sex = #{sex}, </if> <if test="phone != null"> phone = #{phone}, </if> <if test="detail != null"> detail = #{detail}, </if> <if test="label != null"> label = #{label}, </if> <if test="isDefault != null"> is_default = #{isDefault}, </if> </set> where id = #{id} </update>
5、设置默认地址 - PUT接口
【1】controller层
/** * 设置默认地址" * @param addressBook * @return */ @PutMapping("/default") @ApiOperation("设置默认地址") public Result setDefaultAddress(@RequestBody AddressBook addressBook){ addressBookService.setDefaultAddress(addressBook); return Result.success(); }【2】service层
选一个默认地址,则需要先取消原先的默认地址,再设置当前的默认地址,因此我们只需要先把地址全部改为非默认地址,再设置当前地址为默认地址即可
/** * 设置默认地址 * @param addressBook */ public void setDefaultAddress(AddressBook addressBook) { //选一个默认地址,则需要先取消原先的默认地址,再设置当前的默认地址 //1.将当前用户的所有地址改为非默认地址 addressBook.setUserId(BaseContext.getCurrentId()); addressBook.setIsDefault(0); addressBookMapper.updateIsDefaultByUserId(addressBook); //2.将当前地址改为默认地址 addressBook.setIsDefault(1); addressBookMapper.update(addressBook); }【3】mapper层
/** * 根据用户id修改 是否为默认地址 * @param addressBook */ @Update("update sky_take_out.address_book set is_default = #{isDefault} where user_id = #{userId}") void updateIsDefaultByUserId(AddressBook addressBook);
6、查询默认地址 - GET接口
【1】controller层
查询默认地址直接可以复用list条件查询接口,只需要把user_id和is_default绑定查询即可
/** * 查询默认地址 * @return */ @GetMapping("/default") @ApiOperation("查询默认地址") public Result<AddressBook> getDefaultAddress(){ AddressBook addressBook = AddressBook.builder() .isDefault(1) .userId(BaseContext.getCurrentId()) .build(); //直接调用条件查询即可 List<AddressBook> list = addressBookService.list(addressBook); if(list != null && list.size() == 1){ return Result.success(addressBook); } return Result.error("没有查询到默认地址"); }
7、根据id删除地址 - DELETE接口
【1】controller层
/** * 根据id删除地址 * @param id * @return */ @DeleteMapping @ApiOperation("根据id删除地址") public Result delete(Long id){ log.info("删除地址:{}",id); addressBookService.delete(id); return Result.success(); }【2】service层
/** * 根据id删除地址 * @param id */ public void delete(Long id) { addressBookMapper.deleteById(id); }【3】mapper层
/** * 根据id删除地址 * @param id */ @Delete("delete from sky_take_out.address_book where id = #{id}") void deleteById(Long id);
【1】controller层
【2】service层
【3】mapper层
【4】mybatis文件
二、下单支付模块
1、用户下单 - POST接口
【1】controller层
/** * 用户下单 * @param ordersSubmitDTO * @return */ @PostMapping("/submit") @ApiOperation("用户下单") public Result<OrderSubmitVO> submit(@RequestBody OrdersSubmitDTO ordersSubmitDTO){ log.info("用户下单:{}",ordersSubmitDTO); OrderSubmitVO orderSubmitVO = orderService.submitOrder(ordersSubmitDTO); return Result.success(orderSubmitVO); }【2】service层
生成订单需要经过以下业务逻辑处理:
- 排除相关业务异常:地址簿为空、购物车内无商品
- 插入1条数据至order订单表
- 插入多条数据至order_detail订单明细表
- 清空当前用户购物车
- 封装成VO返回前端
/** * 用户下单 * @param ordersSubmitDTO * @return */ @Transactional public OrderSubmitVO submitOrder(OrdersSubmitDTO ordersSubmitDTO) { //1.处理各种业务异常(地址簿为空、购物车数据为空) AddressBook addressBook = addressBookMapper.getById(ordersSubmitDTO.getAddressBookId()); if(addressBook == null){ throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL); } Long currentId = BaseContext.getCurrentId(); ShoppingCart shoppingCart = new ShoppingCart(); shoppingCart.setUserId(currentId); List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart); if(list == null || list.size() == 0){ throw new ShoppingCartBusinessException(MessageConstant.SHOPPING_CART_IS_NULL); } //_____________________________________________________________________________________ //2.向订单表插入1条数据 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(currentId); orderMapper.insert(orders);//xml要返回主键值,因为订单明细表需要订单id //_____________________________________________________________________________________ //3.向订单明细表插入n条数据 //创建一个订单明细列表,用于存储多项订单明细,进行批量插入 List<OrderDetail> orderDetailList = new ArrayList<>(); //前边已经取出购物车中数据,这里遍历 for (ShoppingCart cart : list) { OrderDetail orderDetail = new OrderDetail(); BeanUtils.copyProperties(cart,orderDetail); orderDetail.setOrderId(orders.getId()); orderDetailList.add(orderDetail); } orderDetailMapper.insertBatch(orderDetailList); //_____________________________________________________________________________________ //4.清空当前用户购物车 shoppingCartMapper.deleteAllByUserId(currentId); //5.封装成VO返回给前端 OrderSubmitVO orderSubmitVO = OrderSubmitVO.builder() .id(orders.getId()) .orderTime(orders.getOrderTime()) .orderNumber(orders.getNumber()) .orderAmount(orders.getAmount()) .build(); return orderSubmitVO; }【3】mapper层
1)OrderMapper
/** * 插入订单 * @param orders */ void insert(Orders orders);2)OrderDetailMapper
/** * 批量插入订单明细 * @param orderDetailList */ void insertBatch(List<OrderDetail> orderDetailList);【4】mybatis文件
1)OrderMapper
<!-- useGeneratedKeys="true" keyProperty="id"含义:执行完插入语句后,会将主键值存入id这个属性--> <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>2)OrderDetailMapper
<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>
2、微信支付准备工作
(1)下载cpolar
安装包在day8资料中,点击下载
然后登录官网https://www.cpolar.com/download
注册一个号并登录
(2)启动cpolar.exe
在C盘路径下找到安装好的cpolar文件,选中地址框输入cmd进入控制台
然后在官网中找到自己的Authtoken并复制
在控制台输入下面的命令,注意最好不要全部复制粘贴
cpolar.exe authtoken xxxxx(Authtoken)
接着输入下面命令,注意8080是后端端口号
按下回车获得以下数据
这就是我们申请的公网域名,这里数据等会要写到application-dev.yml文件中
3、微信支付代码导入 (跳过支付版)
首先根据视频导入订单支付模块的代码!!!(在资料包day8中)
微信支付的准备工作需要下面2个文件:
- 获取微信微信支付平台证书文件:apiclient_key.pem
- 商户私钥文件:wechatpay_166D96F876F45C7D07CE98952A96EC980368ACFC.pem
但这两个文件实际上是需要企业认证才能有的,因此我们这里跳过微信支付这个功能开发
流程参考:https://blog.csdn.net/2301_80558092/article/details/149297251
(1)application.yml配置
wechat: appid: ${sky.wechat.appid} secret: ${sky.wechat.secret} mchid: ${sky.wechat.mchid} mchSerialNo: ${sky.wechat.mchid} #privateKeyFilePath: ${sky.wechat.privateKeyFilePath} apiV3Key: ${sky.wechat.apiV3Key} #weChatPayCertFilePath: ${sky.wechat.weChatPayCertFilePath} notifyUrl: ${sky.wechat.notifyUrl} refundNotifyUrl: ${sky.wechat.refundNotifyUrl}(2)application-dev配置
把notifyUrl和refundNotifyUrl改为在cmd命令行中获取的临时域名
wechat: appid: secret: mchid: 1561414331 mchSerialNo: 4B3B3DC35414AD50B1B755BAF8DE9CC7CF407606 #privateKeyFilePath: C:\software\apiclient_key.pem apiV3Key: CZBK51236435wxpay435434323FFDuv3 #weChatPayCertFilePat: C:\software\wechatpay_166D96F876F45C7D07CE98952A96EC980368ACFC.pem notifyUrl: https://xxxxxxxx.xxx.cpolar.top/notify/paySuccess refundNotifyUrl: https://xxxxxxxx.xxx.cpolar.top/notify/refundSuccess(3)修改小程序代码
(4)回到后端修改具体业务代码
在OrderServiceImpl中加一个全局变量
在submitOrder方法的插入1条数据代码处给全局变量赋值
在导入的OrderServiceImpl中的payment方法,先把中间部分的代码注释掉,再把下面黄色框的代码修改成如图部分代码(下面提供)
JSONObject jsonObject = new JSONObject(); jsonObject.put("code","ORDERPAID"); OrderPaymentVO vo = jsonObject.toJavaObject(OrderPaymentVO.class); vo.setPackageStr(jsonObject.getString("package")); Integer OrderPaidStatus = Orders.PAID;//支付状态,已支付 Integer OrderStatus = Orders.TO_BE_CONFIRMED; //订单状态,待接单 LocalDateTime check_out_time = LocalDateTime.now();//更新支付时间 orderMapper.updateStatus(OrderStatus, OrderPaidStatus, check_out_time, this.orders.getId()); return vo;补充一下OrderMapper中的updateStatus方法
/** * 修改订单状态 * @param orderStatus * @param orderPaidStatus * @param check_out_time * @param id */ @Update("update sky_take_out.orders set status = #{orderStatus},pay_status = #{orderPaidStatus} ,checkout_time = #{check_out_time} where id = #{id}") void updateStatus(Integer orderStatus, Integer orderPaidStatus, LocalDateTime check_out_time, Long id);(5)测试
我们启动小程序点一下餐,然后点击提交订单,点击支付,就会发现直接支付成功,这样我们的微信支付模块就成功开发
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
































所有评论(0)