目录

一、地址簿模块

1、新增地址 - POST接口

2、查询当前用户的所有地址 - GET接口

3、根据id查询地址 - GET接口

4、根据id修改地址 - PUT接口

5、设置默认地址 - PUT接口

6、查询默认地址 - GET接口

7、根据id删除地址 - DELETE接口

二、下单支付模块

1、用户下单 - POST接口

2、微信支付准备工作

(1)下载cpolar

(2)启动cpolar.exe

3、微信支付代码导入 (跳过支付版)

(1)application.yml配置

(2)application-dev配置

(3)修改小程序代码

(4)回到后端修改具体业务代码

(5)测试


一、地址簿模块

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. 排除相关业务异常:地址簿为空、购物车内无商品
  2. 插入1条数据至order订单表
  3. 插入多条数据至order_detail订单明细表
  4. 清空当前用户购物车
  5. 封装成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)测试

我们启动小程序点一下餐,然后点击提交订单,点击支付,就会发现直接支付成功,这样我们的微信支付模块就成功开发

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐