# 3 litemall小商城 技术: * 小商城前端,即litemall-wx模块 * 微信小程序 * 小商城后端,即litemall-wx-api模块 * Spring Boot 1.5.10 * Spring MVC * [weixin-java-tools](https://gitee.com/binary/weixin-java-tools) 目前发现需要完善的: * 支付功能 * 优惠券功能 * 商品搜索 * 进一步区分商品和货品的关系 * 地址优化,目前每一次点击都会请求后台,应该缓存已有的数据 * 商品数量和规格中,如果货品数量不足,则显示不能点击的效果 * 商品好评计算与显示 ## 3.1 litemall-wx-api ### 3.1.1 业务 #### 3.1.1.1 运费计算 订单费用小于88时,则需要运费8元; 否则运费0元。 目前运费8元是写在后台代码中,未来可能允许设置管理员设置其他值; 或者采用更加符合实际情况的运费计算方式。 ### 3.1.2 安全 #### 3.1.2.1 Token 用户登录成功以后,后端会返回`token`,之后用户的请求都会携带token。 目前token的失效和跟新机制没有涉及。 #### 3.1.2.2 CROS 如果litemall-admin-api不配置CROS,则Spring Boot会失败。 但是,这里litemall-wx-api没有配置CROS,Spring Boot却不会报错,需要进一步研究。 #### 3.1.2.3 账号密码加盐 如果是微信登录,那么无需账号和密码。 而如果用户采用了账号和密码的形式登录,那么后端需要把用户密码加盐。 #### 3.1.2.4 限制登录 如果采用账号密码登录,那么登录失败一定次数,应该限制登录。 进一步地,如果项目启用了短信功能,应该短信提醒用户,防止他人登录。 目前这里没有实现,仅列出。 ### 3.1.3 支付 准备采用weixin-java-tools工具简化微信支付代码的开发。 由于需要商户相关信息,目前没有开发。 ## 3.2 litemall-wx 这里的代码基于[nideshop-mini-program](https://gitee.com/tumobi/nideshop-mini-program),但是做了一定的修改: * 数据属性名称调整,原项目中数据属性名称是下划线法命名(例如goods_id),而这里采用骆驼式命名法(例如goodsId),因此代码中需要进行相应调整; * 代码清理重构,删除了一些目前不必要的文件,梳理一些逻辑功能; * BUG修补,修改了一些错误; * 功能完善拓展,例如商品立即购买功能、商品评价功能; 具体变化可以采用工具进行对比。 注意 > 目前litemall-wx项目代码基于nideshop-mini-program的commit版本[acbf6276eb27abc6a48887cddd223d7261f0088e](https://github.com/tumobi/nideshop-mini-program/commit/acbf6276eb27abc6a48887cddd223d7261f0088e)。由于改动变化较大,因此之后litemall-wx将独立开发,nideshop-mini-program的跟新不一定会合并到litemall-wx中。 ### 3.2.1 业务API切换 业务API存放在`config/api.js`。 但是可以发现这样的代码: ``` // 本机开发时使用 var WxApiRoot = 'http://localhost:8082/wx/'; // 局域网测试使用 // var WxApiRoot = 'http://192.168.0.101:8082/wx/'; // 云平台部署时使用 // var WxApiRoot = 'http://122.152.206.172:8082/wx/'; ``` 也就是说这里存在三种类型的API服务地址,这里是考虑到开发存在三种情况: 1. 本机开发时,localhost是当前开发机的地址; 2. 手机预览时,192.168.0.101是开发机的IP地址; 3. 当后台部署在云主机中时,122.152.206.172是云主机的IP地址; 4. 此外,更最重要的是,如果小程序正式部署时,这里的地址必须是域名, 而不能是IP地址。 因此,开发阶段用户可以按照具体情况切换1,2或3的选项。 ### 3.2.2 登录 按照官方文档,开发者采用`wx.login`方法即可实现登录操作; 然而,由于`wx.login`只能返回临时登录凭证`code`,从服务器也只能返回对应的sessionId, 因此虽然已经可以视作登录,但是在小程序中不能显示有意义的登录状态, 因此实际很多小程序是继续采用`wx.getUserInfo`来进一步请求用户信息。 因此本模块中,用户的登录状态也是由`wx.login`和`wx.getUserInfo`组成。 #### 3.2.2.1 登录检测 用户可以采用`user.checkLogin`来检查是否`已登录`,而其检测逻辑是: 1. 可以从storage获取`userInfo`和`token` 2. 同时`wx.checkSession`也成功。 但是如果每次都使用`checkLogin`可能也不太好,因此目前机制是: 1. 应用启动时就检测一次,如果登录则设置app.globalData.hasLogin为已登录状态; 之后,其他页面只要查看这个状态即可知道目前是否已登录; 2. 此外,如果后台token过期返回401代码时,则及时清除过期的登录状态信息; 而用户登录失败时则app.globalData.hasLogin为未登录状态。 注意: > 这里的逻辑可能有点乱。。。,但是目前实际效果看没有问题。 #### 3.2.2.2 登录时机 登录请求用户信息的时机存在两种设计: 1. 一种是小程序加载时,即申请用户信息,这种实现较简单; 2. 另外一种是小程序加载时不需要,但是小程序用户需要真正用户信息时才申请用户信息, 而这种实现较复杂。 目前采用第二张实现,可以分成两种情况: * 用户主动登录 用户主动登录,指的是`我的`页面中用户没有登录显示`点击登录`的效果。 * 用户被动登录 用户被动登录,指的是用户想购买商品或者需要用户登录才能操作的行为, 此时因为向服务器请求时token没有设置,因此服务器拒绝用户的请求,同时返回`401`业务代码。 目前需要检测用户登录的页面有: * 购物车 * 我的主页 讨论: > 对于第二张情况,原nideshop-mini-program项目是采取一种自动登录的方式。 > 这里则采用跳转登录页面的方式。 #### 3.2.2.3 登录操作 如前面讨论,这里的登录操作实际包含两个操作`wx.login`和`wx.getUserInfo`。 用户可以采用`user.loginByWeixin`来进行登录操作。 按照官网文档,用户登录前应该检测以下,来避免频繁无意义的登录操作, 因此较合适的做法如下所示: ``` user.checkLogin().catch(() => { user.loginByWeixin().then(res => { this.setData({ userInfo: res.data.userInfo, }); }).catch((err) => { util.showErrorToast('登录失败'); }); }); ``` #### 3.2.2.4 登录拒绝授权 还存在一个问题,当用户登录时,会出现"微信授权"的对话框。 如果用户选择”拒绝“,那么之后用户的登录操作总是失败的。 目前的做法是,用户拒绝授权后,如果再次登录,则: 1. 弹出对话框,请求用户授权 2. 如果用户仍然拒绝,则返回 3. 如果用户接受授权,则弹出系统权限配置页面,等待用户给与授权。 ### 3.2.3 立即购买和放入购物车 ### 3.2.3 ### 3.2.4 storage使用 本模块中采用storage来存储一些数据,以及组件间进行通信。 #### 3.2.4.1 userInfo和token #### 3.2.4.2 cartId #### 3.2.4.3 addressId