目录
十、登录与支付
10.0 创建 settle 分支
10.1 点击结算按钮进行条件判断
10.2 登录
10.2.1 定义 my 页面的编译模式
10.2.2 实现登录和用户信息组件的按需展示
10.2.3 实现登录组件的基本布局
10.2.4 点击登录按钮获取微信用户的基本信息
10.2.5 将用户的基本信息存储到 vuex
10.2.6 登录获取 Token 字符串
10.2.7 将 Token 存储到 vuex
10.3 用户信息
10.3.1 实现用户头像昵称区域的基本布局
10.3.2 渲染用户的头像和昵称
10.3.3 渲染第一个面板区域
10.3.4 渲染第二个面板区域
10.3.5 渲染第三个面板区域
10.3.6 实现退出登录的功能
10.4 三秒后自动跳转
10.4.1 三秒后自动跳转到登录页面
10.4.2 登录成功之后再返回之前的页面
10.5 微信支付
10.5.1 在请求头中添加 Token 身份认证的字段
10.5.2 微信支付的流程
10.5.3 创建订单
10.5.4 订单预支付
10.5.5 发起微信支付
10.6 分支的合并与提交
十一、发布
11.1 为什么要发布
11.2 发布小程序的流程
11.3 发布为 Android App 的流程
十、登录与支付
10.0 创建 settle 分支
运行如下的命令,基于 master 分支在本地创建 settle 子分支,用来开发登录与支付相关的功能:
git checkout -b settle

10.1 点击结算按钮进行条件判断
说明:用户点击了结算按钮之后,需要先后判断是否勾选了要结算的商品、是否选择了收货地址、是否登录。
1. 在 my-settle 组件中,为结算按钮绑定点击事件处理函数:

2. 在 my-settle 组件的 methods 节点中声明 settlement 事件处理函数如下:

3. 在 my-settle 组件中,使用 mapGetters 辅助函数,从 m_user 模块中将 addstr 映射到当前组件中使用:

4. 在 store/user.js 模块的 state 节点中,声明 token 字符串:

5. 在 my-settle 组件中,使用 mapState 辅助函数,从 m_user 模块中将 token 映射到当前组件中使用:








10.2 登录
10.2.1 定义 my 页面的编译模式
1. 点击 微信开发者工具 工具栏上的编译模式下拉菜单,选择 添加编译模式:

2. 勾选启动页面的路径之后,点击确定按钮:

10.2.2 实现登录和用户信息组件的按需展示
1. 在 components 目录中新建登录组件:
2. 在 components 目录中新建用户信息组件:

3. 在 my.vue 页面中,通过 mapState 辅助函数,导入需要的 token 字符串:

4. 在 my.vue 页面中,实现登录组件和用户信息组件的按需展示:








10.2.3 实现登录组件的基本布局

1. 为 my-login 组件定义如下的 UI 结构:

2. 美化登录组件的样式:








10.2.4 点击登录按钮获取微信用户的基本信息

需求描述:需要获取微信用户的头像、昵称等基本信息。
1. 为登录的 button 按钮绑定 open-type="getUserInfo" 属性,表示点击按钮时,希望获取用户的基本信息:

2. 在 methods 节点中声明 getUserInfo 事件处理函数如下:











10.2.5 将用户的基本信息存储到 vuex
1. 在 store/user.js 模块的 state 节点中,声明 userinfo 的信息对象如下:

2. 在 store/user.js 模块的 mutations 节点中,声明如下的两个方法:

3. 使用 mapMutations 辅助函数,将需要的方法映射到 my-login 组件中使用:




10.2.6 登录获取 Token 字符串
需求说明:当获取到了微信用户的基本信息之后,还需要进一步调用登录相关的接口,从而换取登录成功之后的 Token 字符串。
1. 在 getUserInfo 方法中,预调用 this.getToken() 方法,同时把获取到的用户信息传递进去:

2. 在 methods 中定义 getToken 方法,调用登录相关的 API,实现登录的功能:









10.2.7 将 Token 存储到 vuex
1. 在 store/user.js 模块的 mutations 节点中,声明如下的两个方法:

2. 修改 store/user.js 模块的 state 节点如下:

3. 在 my-login 组件中,把 vuex 中的 updateToken 方法映射到当前组件中使用:





10.3 用户信息
10.3.1 实现用户头像昵称区域的基本布局
1. 在 my-userinfo 组件中,定义如下的 UI 结构:

2. 美化当前组件的样式:

3. 在 my.vue 页面中,为最外层包裹性质的 view 容器,添加 class="my-container" 的类名,并美化样式如下:





10.3.2 渲染用户的头像和昵称
1. 在 my-userinfo 组件中,通过 mapState 辅助函数,将需要的成员映射到当前组件中使用:

2. 将用户的头像和昵称渲染到页面中:



10.3.3 渲染第一个面板区域
1. 在 my-userinfo 组件中,定义如下的 UI 结构:

2. 美化第一个面板的样式:




10.3.4 渲染第二个面板区域
1. 定义第二个面板区域的 UI 结构:

2. 对之前的 SCSS 样式进行改造,从而美化第二个面板的样式:





10.3.5 渲染第三个面板区域
1. 定义第三个面板区域的 UI 结构:

2. 美化第三个面板区域的样式:



10.3.6 实现退出登录的功能
1. 为第三个面板区域中的 退出登录 项绑定 click 点击事件处理函数:

2. 在 my-userinfo 组件的 methods 节点中定义 logout 事件处理函数:

3. 使用 mapMutations 辅助方法,将需要用到的 mutations 方法映射到当前组件中:






10.4 三秒后自动跳转
10.4.1 三秒后自动跳转到登录页面
需求描述:在购物车页面,当用户点击 “结算” 按钮时,如果用户没有登录,则 3 秒后自动跳转到登录页面
1. 在 my-settle 组件的 methods 节点中,声明一个叫做 showTips 的方法,专门用来展示倒计时的提示消息:

2. 在 data 节点中声明倒计时的秒数:

3. 改造 结算 按钮的 click 事件处理函数,如果用户没有登录,则预调用一个叫做 delayNavigate 的方法,进行倒计时的导航跳转:

4. 定义 delayNavigate 方法,初步实现倒计时的提示功能:

上述代码的问题:定时器不会自动停止,此时秒数会出现等于 0 或小于 0 的情况!
5. 在 data 节点中声明定时器的 Id 如下:

6. 改造 delayNavigate 方法如下:

上述代码的问题:seconds 秒数不会被重置,导致第 2 次,3 次,n 次 的倒计时跳转功能无法正常工作。
7. 进一步改造 delayNavigate 方法,在执行此方法时,立即将 seconds 秒数重置为 3 即可:





10.4.2 登录成功之后再返回之前的页面
核心实现思路:在自动跳转到登录页面成功之后,把返回页面的信息存储到 vuex 中,从而方便登录成功之后,根据返回页面的信息重新跳转回去。
返回页面的信息对象,主要包含 { openType, from } 两个属性,其中 openType 表示以哪种方式导航回之前的页面;from 表示之前页面的 url 地址;
1. 在 store/user.js 模块的 state 节点中,声明一个叫做 redirectInfo 的对象如下:

2. 在 store/user.js 模块的 mutations 节点中,声明一个叫做 updateRedirectInfo 的方法:

3. 在 my-settle 组件中,通过 mapMutations 辅助方法,把 m_user 模块中的 updateRedirectInfo 方法映射到当前页面中使用:

4. 改造 my-settle 组件 methods 节点中的 delayNavigate 方法,当成功跳转到 my 页面 之后,将重定向的信息对象存储到 vuex 中:

5. 在 my-login 组件中,通过 mapState 和 mapMutations 辅助方法,将 vuex 中需要的数据和方法,映射到当前页面中使用:

6. 改造 my-login 组件中的 getToken 方法,当登录成功之后,预调用 this.navigateBack() 方法返回登录之前的页面:

7. 在 my-login 组件中,声明 navigateBack 方法如下:







10.5 微信支付
10.5.1 在请求头中添加 Token 身份认证的字段
1. 原因说明:只有在登录之后才允许调用支付相关的接口,所以必须为有权限的接口添加身份认证的请求头字段
2. 打开项目根目录下的 main.js,改造 $http.beforeRequest 请求拦截器中的代码如下:






10.5.2 微信支付的流程
创建订单
-
请求创建订单的 API 接口:把(订单金额、收货地址、订单中包含的商品信息)发送到服务器
-
服务器响应的结果:订单编号
订单预支付
-
请求订单预支付的 API 接口:把(订单编号)发送到服务器
-
服务器响应的结果:订单预支付的参数对象,里面包含了订单支付相关的必要参数
发起微信支付
-
调用 uni.requestPayment() 这个 API,发起微信支付;把步骤 2 得到的 “订单预支付对象” 作为参数传递给 uni.requestPayment() 方法
-
监听 uni.requestPayment() 这个 API 的 success,fail,complete 回调函数
10.5.3 创建订单
1. 改造 my-settle 组件中的 settlement 方法,当前三个判断条件通过之后,调用实现微信支付的方法:

2. 在 my-settle 组件中定义 payOrder 方法如下,先实现创建订单的功能:
// 微信支付
async payOrder() {
// 1. 创建订单
// 1.1 组织订单的信息对象
const orderInfo = {
// 开发期间,注释掉真实的订单价格,
// order_price: this.checkedGoodsAmount,
// 写死订单总价为 1 分钱
order_price: 0.01,
consignee_addr: this.addstr,
goods: this.cart.filter(x => x.goods_state).map(x => ({ goods_id: x.goods_id, goods_number: x.goods_count, goods_price: x.goods_price }))
}
// 1.2 发起请求创建订单
const { data: res } = await uni.$http.post('/api/public/v1/my/orders/create', orderInfo)
if (res.meta.status !== 200) return uni.$showMsg('创建订单失败!')
// 1.3 得到服务器响应的“订单编号”
const orderNumber = res.message.order_number
// 2. 订单预支付
// 3. 发起微信支付
}






10.5.4 订单预支付
1. 改造 my-settle 组件的 payOrder 方法,实现订单预支付功能:
// 微信支付
async payOrder() {
// 1. 创建订单
// 1.1 组织订单的信息对象
const orderInfo = {
// 开发期间,注释掉真实的订单价格,
// order_price: this.checkedGoodsAmount,
// 写死订单总价为 1 分钱
order_price: 0.01,
consignee_addr: this.addstr,
goods: this.cart.filter(x => x.goods_state).map(x => ({ goods_id: x.goods_id, goods_number: x.goods_count, goods_price: x.goods_price }))
}
// 1.2 发起请求创建订单
const { data: res } = await uni.$http.post('/api/public/v1/my/orders/create', orderInfo)
if (res.meta.status !== 200) return uni.$showMsg('创建订单失败!')
// 1.3 得到服务器响应的“订单编号”
const orderNumber = res.message.order_number
// 2. 订单预支付
// 2.1 发起请求获取订单的支付信息
const { data: res2 } = await uni.$http.post('/api/public/v1/my/orders/req_unifiedorder', { order_number: orderNumber })
// 2.2 预付订单生成失败
if (res2.meta.status !== 200) return uni.$showError('预付订单生成失败!')
// 2.3 得到订单支付相关的必要参数
const payInfo = res2.message.pay
// 3. 发起微信支付
}




10.5.5 发起微信支付
1. 改造 my-settle 组件的 payOrder 方法,实现微信支付的功能:
// 微信支付
async payOrder() {
// 1. 创建订单
// 1.1 组织订单的信息对象
const orderInfo = {
// 开发期间,注释掉真实的订单价格,
// order_price: this.checkedGoodsAmount,
// 写死订单总价为 1 分钱
order_price: 0.01,
consignee_addr: this.addstr,
goods: this.cart.filter(x => x.goods_state).map(x => ({ goods_id: x.goods_id, goods_number: x.goods_count, goods_price: x.goods_price }))
}
// 1.2 发起请求创建订单
const { data: res } = await uni.$http.post('/api/public/v1/my/orders/create', orderInfo)
if (res.meta.status !== 200) return uni.$showMsg('创建订单失败!')
// 1.3 得到服务器响应的“订单编号”
const orderNumber = res.message.order_number
// 2. 订单预支付
// 2.1 发起请求获取订单的支付信息
const { data: res2 } = await uni.$http.post('/api/public/v1/my/orders/req_unifiedorder', { order_number: orderNumber })
// 2.2 预付订单生成失败
if (res2.meta.status !== 200) return uni.$showError('预付订单生成失败!')
// 2.3 得到订单支付相关的必要参数
const payInfo = res2.message.pay
// 3. 发起微信支付
// 3.1 调用 uni.requestPayment() 发起微信支付
const [err, succ] = await uni.requestPayment(payInfo)
// 3.2 未完成支付
if (err) return uni.$showMsg('订单未支付!')
// 3.3 完成了支付,进一步查询支付的结果
const { data: res3 } = await uni.$http.post('/api/public/v1/my/orders/chkOrder', { order_number: orderNumber })
// 3.4 检测到订单未支付
if (res3.meta.status !== 200) return uni.$showMsg('订单未支付!')
// 3.5 检测到订单支付完成
uni.showToast({
title: '支付完成!',
icon: 'success'
})
}






10.6 分支的合并与提交
1. 将 settle 分支进行本地提交:
git add .
git commit -m "完成了登录和支付功能的开发"


2. 将本地的 settle 分支推送到码云:
git push -u origin settle

3. 将本地 settle 分支中的代码合并到 master 分支:
git checkout master
git merge settle
git push

4. 删除本地的 settle 分支:
git branch -d settle

十一、发布
11.1 为什么要发布
小程序只有发布之后,才能被用户搜索并使用
开发期间的小程序为了便于调试,含有 sourcemap 相关的文件,并且代码没有被压缩,因此体积较大,不适合直接当作线上版本进行发布
通过执行 “小程序发布”,能够优化小程序的体积,提高小程序的运行性能
11.2 发布小程序的流程
1. 点击 HBuilderX 菜单栏上的 发行 -> 小程序-微信(仅适用于uni-app):

2. 在弹出框中填写要发布的小程序的名称和AppId之后,点击发行按钮:

3. 在 HBuilderX 的控制台中查看小程序发布编译的进度:

4. 发布编译完成之后,会自动打开一个新的微信开发者工具界面,此时,点击工具栏上的上传按钮:

5. 填写版本号和项目备注之后,点击上传按钮:

6. 上传完成之后,会出现如下的提示消息,直接点击确定按钮即可:

7. 通过微信开发者工具上传的代码,默认处于版本管理的开发版本列表中,如图所示:

8. 将 开发版本提交审核 -> 再将 审核通过的版本发布上线,即可实现小程序的发布和上线:

11.3 发布为 Android App 的流程
1. 点击 HBuilderX 状态栏左侧的未登录按钮,弹出登录的对话框:

2. 在弹出的登录对话框中,填写账号和密码之后,点击登录即可:

3. 打开项目根目录中的 manifest.json 配置文件,在基础配置面板中,获取uni-app 应用标识,并填写应用名称:

4. 切换到 App 图标配置面板,点击浏览按钮,选择合适的图片之后,再点击自动生成所有图标并替换即可:

5. 点击菜单栏上的 发行 -> 原生 App-云打包:

6. 勾选打包配置如下:

7. 在控制台中查看打包的进度信息:

8. 点击链接下载 apk 的安装包,并安装到 Android 手机中查看打包的效果。
注意:由于开发期间没有进行多端适配,所以有些功能在 App 中无法正常运行,例如:选择收货地址、微信登录、微信支付。





