我们主要使用uniapp + uniCloud在没有后端的情况下实现小程序登录的整个过程,从而了解云函数、
学前准备
-
个人也是可以注册小程序的,只是有些功能不能使用
-
需要准备一个未注册过微信公众号和小程序的邮箱
-
前往注册小程序注册
-
获取AppID 和AppSecret
注册一个uniCloud
https://unicloud.dcloud.net.cn/如果您还未开通过uniCloud,请在web界面开通https://unicloud.dcloud.net.cn/
然后在开发之前我们需要详细了解一下小程序的登录流程
小程序登录流程
这图的意思是先要在小程序端通过wx.login获取到code,然后再通过http请求发送code到开发者服务器,然后再由开发者服务器通过http请求发送相关参数到微信接口服务器获取到openid. 开发者服务器获取到openid之后,便可以做相关操作,比如入库注册会员,然后再返回相关的数据状态给小程序端,一般是生成一个token返回给小程序端,小程序端拿到token,缓存起来,在请求相关接口的时候在http的header里带上token。 现在有了云函数,开发者服务器部分的工作则可以由前端来完成,这也是云开发的相关过程。 比如上述的小程序登录过程,小程序端获取到code之后,不再请求开发者服务器的api,而是请求一个云函数,然后再云函数里通过云函数提供的http请求工具函数去请求微信接口服务器获取openid,然后在云函数里把相关的数据进行入云数据库的操作,再把相关数据返回给小程序端。
创建uniCloud项目
按uniCloud官网文档指引建立一个uniCloud项目:https://doc.dcloud.net.cn/uniCloud/
学习阶段,服务商可以选择阿里云免费版
uniCloud实现微信登录
创建云空间
点击新建服务空间
我这里选择服务商是阿里云,每个账号可以选择一次免费版,根据个人情况选择服务商和套餐版本,然后点击立即购买即可拥有自己的云空间
关联云空间
点击uniCloud文件夹右键选择关联云服务空间
选择你自己创建的云空间关联即可
创建云数据库
新建登录云函数
云函数微信登录示例代码
'use strict';
//小程序的AppID 和 AppSecret
const appid = "********************"
const secret = "********************"
// 创建user数据表实例
const db = uniCloud.database()
const user = db.collection('user')
// 生成token和校验token公共模块
const {getToken,verifyToken} = require('wx-common')
exports.main = async (event, context) => {
//获取用户openid和session_key
const res = await uniCloud.httpclient.request('https://api.weixin.qq.com/sns/jscode2session', {
method: 'GET',
data: {
appid: appid,
secret: secret,
js_code: event.code,// 客户端传递过来的code
grant_type: 'authorization_code'
},
dataType: 'json'
})
//判断请求用户openid和session_key是否成功
if (res.status === 200) {
//成功返回的openid和session_key
const wx_openid = res.data.openid
const wx_session_key = res.data.session_key
// 生成token
const token = getToken(wx_openid)
//查询数据库判断用户是否已经注册 根据openid查找
const res_user = await user.where({
openid: wx_openid
}).get()
//用户未注册存储用户信息
if (res_user.data && res_user.data.length === 0) {
user.add({
avatarUrl: event.userinfo.avatarUrl,
nickName: event.userinfo.nickName,
gender: event.userinfo.gender,
openid: wx_openid,
session_key: wx_session_key,
mobile:"",
token:token
})
} else {
//用户已经存在更新token和session_key
user.where({
openid: wx_openid
}).update({
session_key: wx_session_key,
token:token
})
}
//将需要的个人信息返回到客户端例如:头像 昵称 等
return user.where({
openid: wx_openid
}).field({
avatarUrl: true,
gender: true,
nickName: true,
mobile:true,
token:true,
}).get()
} else {
//获取用户openid和session_key失败响应客户端
return {
msg: '获取微信服务失败',
code: 500
}
}
};
生成token公共模块的创建和使用
1.在common目录下新建公共模块
新建公共模块
2.在wx-common目录下 npm i jsonwebtoken 下载依赖
3.示例代码
// 生成token方法
const jwt = require('jsonwebtoken')
// 密匙
const secret = '***'
//生成token
function getToken(value) {
// sign(加密数据,加密辅助,过期时间(单位/s))
return jwt.sign({value}, secret, {expiresIn: 10800});
}
//解密token
function verifyToken(token) {
try {
return jwt.verify(token,secret)
}catch(e) {
return false
}
}
//导出方法
module.exports = {
getToken,
verifyToken
}
4.在需要使用公共模块的云函数右键管理公共模块或扩展依赖
5.选择刚才创建的公共模块
客户端代码的实现
在pages目录下新建login.vue
<!-- 登录按钮 -->
<view class="btn_box">
<button class="btn" open-type="getUserInfo" @getuserinfo="getUserInfo">登录</button>
</view>
// 获取授权
getUserInfo() {
uni.showModal({
title:"使用微信一键登录",
showCancel:true,
cancelColor:"#000000",
confirmColor:"#42b983",
success:(success) => {
if(success.confirm) {
uni.showLoading({
title:'登录中...'
})
uni.getUserProfile({
desc:'获取用户信息,进行登录',
success: (res) => {
//调用登录函数
this.getLogin(res.userInfo)
}
})
}
if(success.cancel) {
uni.showToast({
title: '用户取消登录!',
icon:'none',
duration: 2000
});
}
}
})
},
// 微信登录
getLogin(userInfo) {
uni.login({
provider:'weixin',
success: (res) => {
// 调用云函数
uniCloud.callFunction({
name:'Login', // 云函数名称
data:{ // 需要传递给云函数的参数
userinfo:userInfo,
code:res.code
}
}).then(ress => {
//判断是否返回了用户数据
if(ress.result.affectedDocs != 0) {
//存储用户信息
this.UpdaUserInfo(ress.result.data[0])
// 存储token
uni.setStorage({
key:'Token',
data:ress.result.data[0].token
})
uni.showToast({
title:'登录成功',
icon:'none',
duration: 2000
});
setTimeout(() => {
// 跳转首页
uni.switchTab({
url:'/pages/home/home'
})
},2000)
}else {
uni.showToast({
title:'登录失败',
icon:'none',
duration: 2000
});
}
uni.hideLoading()
}).catch(err => {
uni.showToast({
title:'登录失败',
icon:'none',
duration: 2000
});
})
}
})
}
},
封装公共请求方法
1.创建common目录和cloudApi.js
2.代码实现
// 公共请求方法
const http = (Name, Data = {}) => {
return new Promise((resolve, reject) => {
const token = uni.getStorageSync('Token')
// 判断是否存在token
if (!token) {
uni.showToast({
icon: 'error',
title: '请先登录!',
duration: 2000
})
// 返回登录页
setTimeout(() => {
uni.redirectTo({
url: '/pages/login/login'
})
}, 2000)
} else {
// 用户已经登录(验证token合法性)
uniCloud.callFunction({
name: 'VerifyToken',
data: {
token: token,
},
success: (TokenRes) => {
console.log("返回", TokenRes)
if (TokenRes.result === false) {
// token 过期
uni.showToast({
icon: 'error',
title: '登录失效',
duration: 2000
})
// 返回登录页
setTimeout(() => {
uni.redirectTo({
url: '/pages/login/login'
})
}, 2000)
} else {
uniCloud.callFunction({
name: FunctionName,
data: FunctionData,
success: (res) => {
resolve(res)
},
fail: (err) => {
reject(err)
}
})
}
}
})
}
})
}
export default http
3.在main.js挂载
4.使用公共请求方法
最后
这也是我第一次个人云开发微信小程序,有问题可以一起探讨交流,欢迎各位大佬指正,谢谢!