uniCloud 实战开发小程序 --001(实现小程序登录)
整体思路:用户打开小程序,静默获取code,再使用微信官方提供的 通过code获取openid的API 获取openid 以及会话密钥session_key(服务端),这时可以使用 jsonwebtoken 等生成token的库 生成token,我本次使用的是微信官方提供的 接口调用凭据 生成的access_token 来作为我业务代码一个凭据(偷懒),将这些数据进行存储,也就是保存在uniCloud的云数据库中。
1. 步骤一 :生成使用uniCloud云开发的基础代码
非常简单,参考uniCloud官网 快速上手 的操作。
2. 步骤二:运行到小程序模拟器
相信有过uni-app 开发经验的 都不会陌生。操作如下:
需要注意的是,小程序开发工具需要开启 安全端口
3. 开始一个云函数
我相信在各种前端业务开发中,登录功能一定是逃不过的一环。 所以 创建一个云函数,我这里命名为了 ”login“
并在页面中 调用 它:
这里我 还调用了 一个 uni.login,是因为小程序需要获取code,uni-app 为我们封装了该方法,可查阅文档了解更多。
现在,需要去完善 login 云函数,在前面我们生成了简单的云函数结构,
我们了解到 event 就是我们客户端上传的参数,通过页面的调用,现在我们可以在 event 中获取到 code,我们需要通过 code 来获取 openid 和 会话密钥 ,
这里我们简单的应用了一下云数据库,我把appid 以及 secret 保存在了 一张表中,具体操作:新建表--> 添加记录 -->
4. 用户保存/更新用户Token(其他数据)
graph TB
subgraph 用户检查
A(获取到的用户信息) --> B{检查数据库是否存在}
end
B--存在-->C[判断Token过期]
B--不存在-->D[ 获取Token]
C--未过期--> E(获取表中的数据)
C--已过期--> F(获取新token)
D--> G(用户表添加新记录)
F--更新该用户的Token -->H(将用户信息返回客户端)
E-->H
G-->H
代码如下:
获取Token的 代码如下:
到此为止,已经基本完成了小程序最基础的登录功能,其中,token的生成,可以借助其他库来做,会可读性 更高一点;这里我们 还需要客户端代码 进行判断,是否需要重新登录(通过expires_in),避免每次打开都请求登录。
附login.js
'use strict';
const db = uniCloud.database()
exports.main = async (event, context) => {
//event为客户端上传的参数
// console.log('event : ', event)
let code = event.code;
let Appid = await db.collection('wx_config').where({
"key": "Appid"
}).get()
let secret = await db.collection('wx_config').where({
"key": "secret"
}).get()
const APPID = Appid.data[0].val
const APPSECRET = secret.data[0].val
let Wx_userinfo = {}
try {
let url =
`https://api.weixin.qq.com/sns/jscode2session?appid=${APPID}&secret=${APPSECRET}&js_code=${code}&grant_type=authorization_code`
const res = await uniCloud.httpclient.request(url, {
method: "GET",
contentType: 'json',
dataType: "json"
})
let data = res.data
if (!data.openid) {
return '微信登录失败!'
}
Wx_userinfo = res.data
} catch (e) {
//TODO handle the exception
return '异常错误'
}
let user = await db.collection('users').where({"openid": Wx_userinfo.openid}).get()
if (user.data.length == 0) {
let Token_res = await getToken({APPID,APPSECRET})
let res = await db.collection("users").add({...Wx_userinfo,...{'access_token':Token_res.data.access_token,"expires_in":Token_res.data.expires_in}})
} else {
if (user.data[0].expires_in > new Date().getTime()) {
Wx_userinfo = {...Wx_userinfo,...user.data[0]}
} else {
let Token_res = await getToken({APPID,APPSECRET})
let res = await db.collection('users').where({"openid":Wx_userinfo.openid}).update({'access_token':Token_res.data.access_token,"expires_in":Token_res.data.expires_in})
if(res.updated > 0){
console.log('token更新成功')
}
}
}
user = await db.collection('users').where({"openid": Wx_userinfo.openid}).get()
Wx_userinfo = {...Wx_userinfo,...user.data[0]}
//返回数据给客户端
return Wx_userinfo
};
var getToken = async (params)=>{
let {APPID,APPSECRET} = params;
let url =
`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${APPID}&secret=${APPSECRET}`
let res = await uniCloud.httpclient.request(url, {
method: "GET",
contentType: "json",
dataType: 'json'
})
if (!res.data.access_token) {
return 'Token获取失败!'
}
res.data.expires_in = res.data.expires_in * 1000 + new Date().getTime() - 5 * 60 * 1000
return res
}
源码: github地址 uniCloud-miniprogram