uniCloud 实战开发小程序 --001(实现小程序登录)

739 阅读2分钟

uniCloud 实战开发小程序 --001(实现小程序登录)

整体思路:用户打开小程序,静默获取code,再使用微信官方提供的 通过code获取openid的API 获取openid 以及会话密钥session_key(服务端),这时可以使用 jsonwebtoken 等生成token的库 生成token,我本次使用的是微信官方提供的 接口调用凭据 生成的access_token 来作为我业务代码一个凭据(偷懒),将这些数据进行存储,也就是保存在uniCloud的云数据库中。

1. 步骤一 :生成使用uniCloud云开发的基础代码

非常简单,参考uniCloud官网 快速上手 的操作。 image.png

2. 步骤二:运行到小程序模拟器

相信有过uni-app 开发经验的 都不会陌生。操作如下:

image.png

需要注意的是,小程序开发工具需要开启 安全端口

image.png

3. 开始一个云函数

我相信在各种前端业务开发中,登录功能一定是逃不过的一环。 所以 创建一个云函数,我这里命名为了 ”login“

image.png

并在页面中 调用 它:

image.png

这里我 还调用了 一个 uni.login,是因为小程序需要获取code,uni-app 为我们封装了该方法,可查阅文档了解更多。

现在,需要去完善 login 云函数,在前面我们生成了简单的云函数结构,

image.png

我们了解到 event 就是我们客户端上传的参数,通过页面的调用,现在我们可以在 event 中获取到 code,我们需要通过 code 来获取 openid 和 会话密钥 ,

image.png 这里我们简单的应用了一下云数据库,我把appid 以及 secret 保存在了 一张表中,具体操作:新建表--> 添加记录 -->

image.png

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

代码如下:

image.png

获取Token的 代码如下:

image.png


image.png 到此为止,已经基本完成了小程序最基础的登录功能,其中,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