一、 导入地址簿功能代码
(1)需求分析和设计
①产品原型
地址簿,指的是消费者用户的地址信息,用户登录成功后可以维护自己的地址信息。同一个用户可以有多个地址信息,但是只能有一个默认地址。
效果图:
对于地址簿管理,我们需要实现以下几个功能:
-
查询地址列表
-
新增地址
-
修改地址
-
删除地址
-
设置默认地址
-
查询默认地址
②接口设计
根据上述原型图先粗粒度设计接口,共包含7个接口。
接口设计:
-
新增地址
-
查询登录用户所有地址
-
查询默认地址
-
根据id修改地址
-
根据id删除地址
-
根据id查询地址
-
设置默认地址
接下来细粒度分析每个接口,明确每个接口的请求方式、请求路径、传入参数和返回值。
1). 新增地址
2). 查询登录用户所有地址
3). 查询默认地址
4). 修改地址
5). 根据id删除地址
6). 根据id查询地址
7). 设置默认地址
③表设计
用户的地址信息会存储在address_book表,即地址簿表中。具体表结构如下:
这里面有一个字段is_default,实际上我们在设置默认地址时,只需要更新这个字段就可以了。
(2)代码导入
对于这一类的单表的增删改查,我们已经写过很多了,基本的开发思路都是一样的,那么本小节的用户地址簿管理的增删改查功能,我们就不再一一实现了,基本的代码我们都已经提供了,直接导入进来,做一个测试即可。
导入课程资料中的地址簿模块功能代码:
进入到sky-server模块中
①Mapper层
创建AddressBookMapper.java
创建AddressBookMapper.xml
②Service层
创建AddressBookService.java
③Controller层
(3)功能测试
可以通过如下方式进行测试:
-
查看控制台sql和数据库中的数据变化
-
Swagger接口文档测试
-
前后端联调
我们直接使用前后端联调测试:
启动后台服务,编译小程序
登录进入首页-->进入个人中心-->进入地址管理
1). 新增收货地址
添加两条收货地址:
查看收货地址:
查看数据库:
2). 设置默认收货地址
设置默认地址:
查看数据库:
3). 删除收货地址
进行编辑:
删除地址:
查看数据库:
(4)代码提交
二、用户下单
(1)需求分析和设计
①产品原型
用户下单业务说明: 在电商系统中,用户是通过下单的方式通知商家,用户已经购买了商品,需要商家进行备货和发货。 用户下单后会产生订单相关数据,订单数据需要能够体现如下信息:
用户将菜品或者套餐加入购物车后,可以点击购物车中的 "去结算" 按钮,页面跳转到订单确认页面,点击 "去支付" 按钮则完成下单操作。
用户点餐业务流程(效果图):
②接口设计
接口分析:
接口设计:
③表设计
用户下单业务对应的数据表为orders表和order_detail表(一对多关系,一个订单关联多个订单明细):
具体的表结构如下:
1). orders订单表
2). order_detail订单明细表
说明:用户提交订单时,需要往订单表orders中插入一条记录,并且需要往order_detail中插入一条或多条记录。
(2)代码开发
①DTO设计
根据用户下单接口的参数设计DTO:
在sky-pojo模块,OrdersSubmitDTO.java已定义
②VO设计
根据用户下单接口的返回结果设计VO:
在sky-pojo模块,OrderSubmitVO.java已定义
③Controller层
创建OrderController并提供用户下单方法:
④Service层接口
创建OrderService接口,并声明用户下单方法:
⑤Service层实现类
⑥Mapper层
(3)功能测试
登录小程序,完成下单操作
下单操作时,同时会删除购物车中的数据
查看shopping_cart表:
去结算-->去支付
查看orders表:
查看order_detail表:
同时,购物车表中数据删除:
(4)代码提交
三、订单支付
(1)微信支付介绍
前面的课程已经实现了用户下单,那接下来就是订单支付,就是完成付款功能。支付大家应该都不陌生了,在现实生活中经常购买商品并且使用支付功能来付款,在付款的时候可能使用比较多的就是微信支付和支付宝支付了。在苍穹外卖项目中,选择的就是微信支付这种支付方式。
要实现微信支付就需要注册微信支付的一个商户号,这个商户号是必须要有一家企业并且有正规的营业执照。只有具备了这些资质之后,才可以去注册商户号,才能开通支付权限。
个人不具备这种资质,所以我们在学习微信支付时,最重要的是了解微信支付的流程,并且能够阅读微信官方提供的接口文档,能够和第三方支付平台对接起来就可以了。
微信支付产品:
本项目选择小程序支付
微信支付接入流程:
微信小程序支付时序图:
微信支付相关接口:
JSAPI下单:商户系统调用该接口在微信支付服务后台生成预支付交易单(对应时序图的第5步)
微信小程序调起支付:通过JSAPI下单接口获取到发起支付的必要参数prepay_id,然后使用微信支付提供的小程序方法调起小程序支付(对应时序图的第10步)
(2)微信支付准备工作
①如何保证数据安全?
完成微信支付有两个关键的步骤:
第一个就是需要在商户系统当中调用微信后台的一个下单接口,就是生成预支付交易单。
第二个就是支付成功之后微信后台会给推送消息。
这两个接口数据的安全性,要求其实是非常高的。
解决:微信提供的方式就是对数据进行加密、解密、签名多种方式。要完成数据加密解密,需要提前准备相应的一些文件,其实就是一些证书。
获取微信支付平台证书、商户私钥文件:
在后绪程序开发过程中,就会使用到这两个文件,需要提前把这两个文件准备好。
②如何调用到商户系统?
微信后台会调用到商户系统给推送支付的结果,在这里我们就会遇到一个问题,就是微信后台怎么就能调用到我们这个商户系统呢?因为这个调用过程,其实本质上也是一个HTTP请求。
目前,商户系统它的ip地址就是当前自己电脑的ip地址,只是一个局域网内的ip地址,微信后台无法调用到。
解决:内网穿透。通过cpolar软件可以获得一个临时域名,而这个临时域名是一个公网ip,这样,微信后台就可以请求到商户系统了。
cpolar软件的使用:
1). 下载与安装
在资料中已提供,可无需下载。
安装过程中,一直下一步即可,不再演示。
2). cpolar指定authtoken
复制authtoken:
执行命令:
3). 获取临时域名
执行命令:
获取域名:
4). 验证临时域名有效性1
访问接口文档
使用localhost:8080访问
使用临时域名访问
证明临时域名生效。
(3)代码导入
导入资料中的微信支付功能代码即可
①微信支付相关配置
application-dev.yml
application.yml
WeChatProperties.java:读取配置(已定义)
②Mapper层
在OrderMapper.java中添加getByNumberAndUserId和update两个方法
在OrderMapper.xml中添加
③Service层
在OrderService.java中添加payment和paySuccess两个方法定义
在OrderServiceImpl.java中实现payment和paySuccess两个方法
④Controller层
在OrderController.java中添加payment方法
PayNotifyController.java
⑤微信支付(没有商户号)的解决方法
步骤1:我们根据老师提供的代码,将代码复制到我们自己的项目中
步骤2:修改微信小程序中的代码:
步骤3:修改OrderServiceImpl
中的代码
我们将原本的payment
代码替换为以下代码:
/** * 订单支付 * * @param ordersPaymentDTO * @return */ 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("该订单已支付"); // } JSONObject jsonObject = new JSONObject(); jsonObject.put("code", "ORDERPAID"); OrderPaymentVO vo = jsonObject.toJavaObject(OrderPaymentVO.class); vo.setPackageStr(jsonObject.getString("package")); // 替代微信支付成功后的数据库订单状态更新,直接在这里更新了 // 根据订单号查询当前用户的该订单 Orders ordersDB = orderMapper.getByNumberAndUserId(ordersPaymentDTO.getOrderNumber(), userId); // 根据订单id更新订单的状态、支付方式、支付状态、结账时间 Orders orders=new Orders(); orders.setId(ordersDB.getId()); orders.setStatus(Orders.TO_BE_CONFIRMED); orders.setPayStatus(Orders.PAID); orders.setCheckoutTime(LocalDateTime.now()); // Orders orders = Orders.builder() // .id(ordersDB.getId()) // .status(Orders.TO_BE_CONFIRMED) // 订单状态,待接单 // .payStatus(Orders.PAID) // 支付状态,已支付 // .checkoutTime(LocalDateTime.now()) // 更新支付时间 // .build(); orderMapper.update(orders); return vo; }
效果如下:
数据库中的数据也更新成功:
(4)功能测试
测试过程中,可通过断点方式查看后台每一步执行情况。
下单:
去支付:
确认支付:
(5)代码提交
四、问题及其解决方法
(1)No mapping for GET /user/addressBook/list
解决办法:解决方式,重启idea
(2) Parameter 'orderDetailList' not found. Available parameters are [orderDetails, collection, list]
解决办法:
(3)@Autowired private OrderMapper orderMapper; @Autowired private OrderDetailMapper orderDetailMapper; @Autowired private ShoppingCartMapper shoppingCartMapper; @Autowired private AddressBookMapper addressBookMapper;
解决办法: