乐优商城(十三)订单

1. 订单接口系统

之前我们尝试过基于前端系统开发后台接口,也尝试过基于接口文档开发后台接口。现在我们尝试一下别人已经开发好的后台接口,该如何调用

1.1 导入订单微服务

  1. 复制 leyou-order 到我们的 leyou 工程下

    在这里插入图片描述

  2. 打开 IDEA,导入 leyou-order 模块

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  3. 在父工程 leyou 的 pom 文件中添加 leyou-order 模块

    在这里插入图片描述

  4. 修改一下 pom 配置文件,成功启动 leyou-order

    在这里插入图片描述

  5. 最后在 leyou-gateway 中添加 leyou-order 的路由,并重启 leyou-gateway

    在这里插入图片描述

1.2 Swagger-UI

1.2.1 OpenAPI 介绍

随着互联网技术的发展,现在的网站架构基本都由原来的后端渲染,变成了前端渲染、前后端分离的形态,而且前端技术和后端技术在各自的道路上越走越远。 前端和后端的唯一联系,变成了 API 接口,API 文档变成了前后端开发人员联系的纽带,变得越来越重要。没有 API 文档工具之前,大家都是手写 API 文档的, API 文档没有统一规范和格式,这无疑给开发带来了灾难

OpenAPI 规范(OpenAPI Specification 简称 OAS)是 Linux 基金会的一个项目,OpenAPI 试图通过定义一种用来描述 API 格式的语言,来规范 RESTful 服务开发过程

1.2.2 Swagger 介绍

前面说了 OpenAPI 是一个编写 API 文档的规范,然而如果手动去编写 OpenAPI 规范的文档,是非常麻烦的。Swagger 就是一个实现了 OpenAPI 规范的工具集

Swagger包含的工具集:

  • Swagger 编辑器: Swagger Editor 允许您在浏览器中编辑 YAML 中的 OpenAPI 规范并实时预览文档。
  • Swagger UI: Swagger UI 是 HTML,Javascript 和 CSS 资产的集合,可以从符合 OAS 标准的 API 动态生成漂亮的文档。
  • Swagger Codegen:允许根据 OpenAPI 规范自动生成 API 客户端库(SDK 生成),服务器存根和文档。
  • Swagger Parser:用于解析来自 Java 的 OpenAPI 定义的独立库
  • Swagger Core:与 Java 相关的库,用于创建,使用和使用 OpenAPI 定义
  • Swagger Inspector(免费): API 测试工具,可让您验证您的 API 并从现有 API 生成 OpenAPI 定义
  • SwaggerHub(免费和商业):API 设计和文档,为使用 OpenAPI 的团队构建。

1.2.3.快速入门

SpringBoot 已经集成了 Swagger,使用简单注解即可生成 Swagger 的 API 文档。

  1. 引入依赖

    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <version>2.8.0</version>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger-ui</artifactId>
        <version>2.8.0</version>
    </dependency>
    
  2. 编写配置类

    @Configuration
    @EnableSwagger2
    public class SwaggerConfig {
    
        @Bean
        public Docket api() {
            return new Docket(DocumentationType.SWAGGER_2)
                    .host("localhost:8089")
                    .apiInfo(apiInfo())
                    .select()
                    .apis(RequestHandlerSelectors.basePackage("com.leyou.order.controller"))
                    .paths(PathSelectors.any())
                    .build();
    }
    
        private ApiInfo apiInfo() {
            return new ApiInfoBuilder()
                    .title("乐优商城订单系统")
                    .description("乐优商城订单系统接口文档")
                    .version("1.0")
                    .build();
        }
    }
    
  3. 接口声明

    在 Controller 的每个 handler 上添加接口说明注解:

    @RestController
    @RequestMapping("order")
    @Api("订单服务接口")
    public class OrderController {
    
        @Autowired
        private OrderService orderService;
    
        @Autowired
        private PayHelper payHelper;
    
        /**
         * 创建订单
         *
         * @param order 订单对象
         * @return 订单编号
         */
        @PostMapping
        @ApiOperation(value = "创建订单接口,返回订单编号", notes = "创建订单")
        @ApiImplicitParam(name = "order", required = true, value = "订单的json对象,包含订单条目和物流信息")
        public ResponseEntity<Long> createOrder(@RequestBody @Valid Order order) {
            Long id = this.orderService.createOrder(order);
            return new ResponseEntity<>(id, HttpStatus.CREATED);
        }
    
        /**
         * 分页查询当前用户订单
         *
         * @param status 订单状态
         * @return 分页订单数据
         */
        @GetMapping("list")
        @ApiOperation(value = "分页查询当前用户订单,并且可以根据订单状态过滤", notes = "分页查询当前用户订单")
        @ApiImplicitParams({
                @ApiImplicitParam(name = "page", value = "当前页", defaultValue = "1", type = "Integer"),
                @ApiImplicitParam(name = "rows", value = "每页大小", defaultValue = "5", type = "Integer"),
                @ApiImplicitParam(name = "status", value = "订单状态:1未付款,2已付款未发货,3已发货未确认,4已确认未评价,5交易关闭,6交易成功,已评价", type = "Integer"),
        })
        @ApiResponses({
                @ApiResponse(code = 200, message = "订单的分页结果"),
                @ApiResponse(code = 404, message = "没有查询到结果"),
                @ApiResponse(code = 500, message = "查询失败"),
        })
        public ResponseEntity<PageResult<Order>> queryUserOrderList(
                @RequestParam(value = "page", defaultValue = "1") Integer page,
                @RequestParam(value = "rows", defaultValue = "5") Integer rows,
                @RequestParam(value = "status", required = false) Integer status) {
            PageResult<Order> result = this.orderService.queryUserOrderList(page, rows, status);
            if (result == null) {
                return new ResponseEntity<>(HttpStatus.NOT_FOUND);
            }
            return ResponseEntity.ok(result);
        }
    }
    
    

    常用注解说明:

    /**
    @Api:修饰整个类,描述Controller的作用
    @ApiOperation:描述一个类的一个方法,或者说一个接口
    @ApiParam:单个参数描述
    @ApiModel:用对象来接收参数
    @ApiProperty:用对象接收参数时,描述对象的一个字段
    @ApiResponse:HTTP响应其中1个描述
    @ApiResponses:HTTP响应整体描述
    @ApiIgnore:使用该注解忽略这个API
    @ApiError :发生错误返回的信息
    @ApiImplicitParam:一个请求参数
    @ApiImplicitParams:多个请求参数
    */
    
  4. 打开浏览器,访问下面网址

    http://localhost:8089/swagger-ui.html
    

    在这里插入图片描述

  5. 点击 order-controller,查看接口信息

    在这里插入图片描述

  6. 点击任意一个接口,即可看到详细信息

    在这里插入图片描述

1.3 测试接口

1.3.1 创建订单接口

接口说明

  • 请求方式:POST
  • 请求路径:/order
  • 请求参数:包含订单、订单详情等数据的 JSON 对象。
  • 返回结果:订单编号

测试

  1. 点击 Try It Out 测试

    在这里插入图片描述

  2. 输入 JSON 对象

    {
      "totalPay": 236800,
      "postFee": 0,
      "paymentType": 2,
      "actualPay": 236800,
      "buyerMessage": null,
      "buyerNick": "huge",
      "orderDetails": [
        {
          "skuId": 3893493,
          "num": 1,
          "title": "苹果(Apple)iPhone 6 (A1586) 16GB 金色 移动联通电信4G手机3",
          "price": 236800,
          "ownSpec": "{\"机身颜色\":\"钻雕蓝\",\"内存\":\"4GB\",\"机身存储\":\"64GB\"}",
          "image": "http://image.leyou.com/images/9/4/1524297342728.jpg"
        }
      ],
      "receiver": "锋哥",
      "receiverMobile": "15800000000",
      "receiverState": "上海",
      "receiverCity": "上海",
      "receiverDistrict": "浦东新签",
      "receiverAddress": "航头镇航头路18号传智播客3号楼",
      "receiverZip": "210000",
      "invoiceType": 0,
      "sourceType":2
    }
    
  3. 点击 execute,成功响应订单编号

    在这里插入图片描述

  4. 查看 MySQL 中的订单编号

    在这里插入图片描述

注意

浏览器订单编号:1260526782893920300
MySQL订单编号:1260526782893920256

我们发现浏览器响应的订单编号和 MySQL 订单编号后三位不一样,这是因为 JS 的长整数精度有限,java 的 Long 类型数据超出了范围,所以出现了精度损失。解决办法是 JS 将订单编号转换为字符串处理,就不会精度损失了。

1.3.2 查询订单接口

接口说明

  • 请求方式:GET
  • 请求路径:/order/{id}
  • 请求参数:id,订单编号
  • 返回结果:Order,订单的 JSON 对象

测试

  1. 输入订单编号

    在这里插入图片描述

  2. 点击 execute,成功响应订单对象

    在这里插入图片描述

1.3.3 更新订单状态

接口说明

  • 请求参数:PUT
  • 请求路径:/order/{id}/{status}
  • 请求参数:
    • id:订单编号,String 类型,不能为空
    • status:订单状态,不能为空
  • 返回结果:null

测试

  1. 更新前的订单状态,值为 1

    在这里插入图片描述

  2. 输入订单编号和订单状态

    在这里插入图片描述

  3. 点击 execute,响应 204

    在这里插入图片描述

  4. 再次查看订单状态,已经修改值为 2

    在这里插入图片描述

1.3.4 分页查询订单

接口说明

  • 请求方式:Get
  • 请求路径:/order/list
  • 请求参数:
    • page:当前页,Integer 类型,默认为 1
    • rows:每页大小,Integer 类型,默认为 5
    • status:订单状态,String 类型,默认查询全部状态订单
  • 返回结果:PageResult 对象,包含下面属性:
    • total:总条数
    • items:当前页订单数组

测试

  1. 输入当前页、每页大小、订单状态

    在这里插入图片描述

  2. 点击 execute,成功响应 PageResult 对象

    在这里插入图片描述

1.3.5 查询支付状态

接口说明

  • 请求方式: Get
  • 请求路径: /state/{id}
  • 请求参数: id,订单编号
  • 返回结果:0,未查询到支付信息;1,支付成功;2,支付失败

测试

  1. 输入订单编号

    在这里插入图片描述

  2. 点击 execute,成功响应支付结果

    在这里插入图片描述

1.3.6 生成微信付款链接

接口说明

  • 请求方式:Get
  • 请求路径:/order/url/{id}
  • 请求参数:id,订单编号
  • 返回结果:String 类型,生成的微信支付链接

测试

  1. 输入订单编号

    在这里插入图片描述

  2. 点击 execute,成功响应微信支付链接

    在这里插入图片描述

2. 订单结算页

2.1 页面跳转

我们接下来实现点击结算按钮跳转到订单结算页:

  1. 找到 cart.html 中的结算按钮,我们给这个按钮绑定点击事件

    在这里插入图片描述

  2. 创建点击事件方法:如果未登录,跳转到登录页面;如果已登陆,保存已选购的购物车到 Local Storage,再跳转到订单结算页。

    在这里插入图片描述

测试

  1. 登录后点击加入购物车

    在这里插入图片描述

  2. 成功跳转到结算页

    在这里插入图片描述

  3. 查看 Local Storage,成功保存已选购物车

    在这里插入图片描述

2.2 渲染订单结算页

在这里插入图片描述
分析一下订单结算页需要渲染的内容:

  • 收货人信息
  • 支付方式
  • 商品信息

2.2.1 收货人信息

这里的收货人信息肯定是当前登录用户的收货地址。所以需要根据当前登录用户去查询,目前我们在页面是写的假数据:

在这里插入图片描述

2.2.2 支付方式

支付方式有 2 种:

  • 微信支付
  • 货到付款

与我们订单数据中的 paymentType 关联:

在这里插入图片描述

所以我们可以在 Vue 实例中定义一个属性来记录支付方式:

在这里插入图片描述

然后在页面渲染时与这个变量关联:

在这里插入图片描述

2.2.3 商品信息

  1. 在 created 钩子函数中获取购物车数据,保存到 carts 数组中。

    在这里插入图片描述

  2. 将 carts 中的数据渲染到页面上

    在这里插入图片描述

  3. 计算商品总价,总数,最终实际价格

    在这里插入图片描述

  4. 将计算数据渲染到页面

    在这里插入图片描述

2.2.4 最终效果

在这里插入图片描述

2.3 提交订单

  1. 找到提交订单按钮,我们给这个按钮绑定点击事件

    在这里插入图片描述

  2. 然后编写方法,组织数据并提交,提交成功则跳转到支付页面,并在 url 中携带 orderId 和 actualPay

    submit() {
        //1.判断是否登录
        ly.verify().then(({data}) => {
            //2.已登录
            const address = this.addresses[this.selectedAddress];
            let addr = {
                receiver: address.name,
                receiverMobile: address.phone,
                receiverState: address.state,
                receiverCity: address.city,
                receiverDistrict: address.district,
                receiverAddress: address.address,
                receiverZip: address.zipCode,
                invoiceType: 0,
                sourceType: 2
            };
            const orderDetail = {orderDetails: this.carts};
            Object.assign(this.order, addr, orderDetail, {
                totalPay: this.totalPrice,
                actualPay: this.actualPrice,
                buyerMessage: null,
                buyerNick: data.username
            });
            ly.http.post("/order/order", this.order, {
                transformResponse: [
                    function (data) {
                        return data;
                    }
                ]
            }).then(({data}) => {
                window.location.href = "http://www.leyou.com/pay.html?orderId=" + data+"&actualPay="+ly.formatPrice(this.order.actualPay);
            });
        }).catch(() => {
            window.location.href = "http://www.leyou.com/login.html?returnUrl=http://www.leyou.com/getOrderInfo.html";
        })
    }
    

    测试

    1. 点击提交订单,成功跳转到支付页面

      在这里插入图片描述

    2. 查看数据库,生成订单成功

      在这里插入图片描述

3. 支付页面

支付页面我们一共需要展示三个部分:

  • 支付二维码:根据付款链接生成二维码
  • 订单号:从 url 中获取 orderId
  • 应付金额:从 url 中获取 actualPay

3.1 生成二维码

  1. 调用后台的生成微信付款链接接口,生成付款链接
  2. 根据付款链接生成二维码
  3. 因为不清楚用户何时会付款,因此这里开启定时任务,查询付款状态

代码如下:

ly.verify().then(res => {
    this.orderId = ly.getUrlParam("orderId");
    this.actualPay = ly.getUrlParam("actualPay");
    ly.http.get("/order/order/url/" + this.orderId).then(({data}) => {
        new QRCode("qrcode", {
            text: data,
            width: 256,
            height: 256,
            colorDark: "#000000",
            colorLight: "#ffffff",
            correctLevel: QRCode.CorrectLevel.H
        });
    })
    // 开启定时任务,查询付款状态
    const taskId = setInterval(() => {
        ly.http.get("/order/order/state/" + this.orderId)
            .then(resp => {
            let i = resp.data;
            if (i === 1) {
                // 付款成功
                clearInterval(taskId);
                // 跳转到付款成功页
                location.href = "/paysuccess.html?orderId=" + this.orderId + "&actualPay=" + this.actualPay;
            } else if (i === 2) {
                // 付款失败
                clearInterval(taskId);
                // 跳转到付款失败页
                location.href = "/payfail.html";
            }
        })
    }, 3000);
}).catch(() => {
    window.location.href = "http://www.leyou.com/login.html?returnUrl=http://www.leyou.com/getOrderInfo.html";
})

3.2 订单号和应付金额

在这里插入图片描述

3.3 最终效果

在这里插入图片描述

3.4 支付成功页面

在这里插入图片描述

3.5 支付失败页面

在这里插入图片描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bm1998

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值