很早就了解与学习过微信小程序开发相关的技术栈与框架,小程序的账号也都已经申请过。但写过的 demo 项目也迟迟没有发布到小程序上。这主要的原因还是觉得不值得发布,加上各种审核相关的。而这次准备写一个搜题相关的小程序,也是时候实战发布一下,顺带记录下整个开发与发布过程。
在线体验:扫下图小程序二维码
小程序的源码地址:https://github.com/kuizuo/question-man
技术栈
小程序所采用的是 Taro + Vue3 + NutUI,之所以选这套技术栈,主要是想上 Vue3,而 uniapp 对 Vue3 的支持并不友好,在我的上篇文章中也有说明到,同时支持 uniapp 的 vue3 屈指可数。所以便选用了这套技术栈来进行开发。
页面设计
项目配置
项目搭建
taro init myApp
配置如下
安装完依赖,使用npm run dev:weapp
,在打开微信开发者工具,导入项目即可。
axios 封装
web 端 http 请求使用最多的库就是 axios 了,但是在小程序中使用 axios 会提示 adapter 未定义,原因是小程序不能解析 package.json 中的 browser module 等字段。
要使用 axios 的话可以安装 axios-miniprogram 或者 taro-axios 库(我选择后者,但前者稍小 5kb),也就是会适配小程序的 axios 的 adapter,引入和使用与 axios 并不特别大的差异。以下是我封装后的代码
import axios from 'taro-axios'
import Taro from '@tarojs/taro'
import { useAuthStore } from '@/stores/modules/auth'
const showErrorToast = msg => {
Taro.showToast({
title: msg,
icon: 'none',
})
}
const instance = axios.create({
baseURL: process.env.BASE_URL,
})
instance.interceptors.request.use(
config => {
Taro.showLoading({
title: '加载中',
mask: true,
})
let token = Taro.getStorageSync('token')
if (typeof token == 'undefined') {
token = ''
}
config.headers = {
'Content-Type': 'application/json;charset=utf-8',
Authorization: token,
}
return config
},
error => {
console.log(error)
return Promise.reject(error)
},
)
// respone拦截器
instance.interceptors.response.use(
(response: any) => {
Taro.hideLoading()
if (response.data.isError) {
showErrorToast(response.data.error.message)
} else {
return response
}
},
error => {
if (error.response) {
Taro.hideLoading()
console.log('err', error)
let res = error.response.data
switch (res.code) {
case 400:
showErrorToast(res.message || '非法请求')
break
case 401:
const authStore = useAuthStore()
authStore.login()
// showErrorToast(res.message || '当前登录已过期,请重新登录')
// Taro.navigateTo({
// url: '/pages/login/index'
// })
break
case 403:
showErrorToast(res.message || '非法请求')
break
case 404:
showErrorToast(res.message || '请求资源不存在')
break
case 500:
case 502:
showErrorToast(res.message || '服务器开小差啦')
break
default:
showErrorToast(res.message || res.statusText)
}
} else {
console.log(error)
showErrorToast('请检查网络连接状态')
}
return Promise.reject(error)
},
)
export default instance
没什么好说的,和网页端基本一致。主要是加了个 wx 的 Loading 与 Toast。然后在 token 失效的时候,应该是要跳转到登录页面,但我并没有编写登录页面,而是重新调用一遍 login,达到静默登录的效果。
获取用户唯一标识(openid)
借助微信小程序能十分方便的获取到微信用户。在微信中,为了识别用户,每个用户针对每个公众号或小程序等应用会产生一个安全的 openid,开发者可以通过这个标识识别出用户。
要获取 openid 有以下几种方法(这里以 Taro 为例子,而为 wx 官方文档),具体代码可在官方文档中查看到。
Taro.login(option) | Taro 文档 (jd.com)
首先调用Taro.login()
获取 5 分钟时长的 code,然向 api.weixin.qq.com 获取 openid 代码如下
Taro.login({
success(res) {
let code = res.code
let appId = '小程序->开发管理->开发设置->开发者ID获取'
let appSecret = '小程序->开发管理->开发设置->开发者ID获取'
Taro.request({
url: 'https://api.weixin.qq.com/sns/jscode2session',
data: {
appid: appId,
secret: appSecret,
js_code: res.code,
grant_type: 'authorization_code',
},
method: 'GET',
success(res) {
console.log('openid', res.data.openid) // 得到openid
console.log('session_key', res.data.session_key) // 得到 session_key
},
})
},
})
但现在小程序是无法添加 api.weixin.qq.com 域名,所以上面的方案在小程序端失效,只能转到后端上。小程序官方有张实践图
整个步骤
1、调用wx.login 获取 code,此时也可调用 wx.getUserInfo 来获取用户数据(昵称,头像)
2、由于小程序后台授权域名无法授权微信的域名,所以需要将 code 与用户数据传入到自己的服务器上。
3、服务器后台接收到 code,后台将 appid+appsecret+code 向微信 api 服务获取用户的登录态信息(openid 与 session_key),服务器对这些登录态信息进行封装,如 session 或者 jwt 的 token 都可以(这里以 token 为例),返回给小程序端
4、小程序接收到 token 时,将其保存到本地存储上(wx.setStorage),每次携带该 token 请求向服务器发送请求。
不过如果使用云开发可以免去很多鉴权相关的,但由于数据库存储相关的,所以我是采用自建后台服务器,而后端暂不考虑开源,故具体逻辑代码就不演示了(考虑安全为主),自行编写后端 login 接口。
获取手机号
注意:只有企业小程序才可以获取用户手机号,个人小程序没有办法获取的。
在这篇文章中有说明到如何获取 5 行代码获取小程序用户手机号 | 微信开放社区 (qq.com)
所以就没有然后了(因为我肯定是个人账号)。