uniapp云开发--微信登录

前言

我们主要使用uniapp + uniCloud 实现小程序登录,并将用户数据存入云数据库。

小程序 wx.getUserProfile 调整,接口将被收回 详情,所以需要用户自己填写资料。

注:填写个人资料是一个组件,覆盖在登录之上而已,还是在同一个页面

uniCloud

创建 uniapp + uniCloud 项目,创建云数据库 数据表 uniCloud传送门

开始

创建项目

关联云服务空间

创建云数据库 数据表

不使用模版,输入名称直接创建即可。

编辑表结构,想了解更多可以去看云数据库 DB Schema 数据结构文档 传送门

json 复制代码
{
  "bsonType": "object",
  "required": [],
  "permission": {
    "read": true,
    "create": true,
    "update": true,
    "delete": false
  },
  "properties": {
    "_id": {
      "description": "ID,系统自动生成"
    },
    "nickName": {
      "bsonType": "string",
      "label": "昵称",
      "description": "用户昵称,登录获取的"
    },
    "avatarUrl": {
      "bsonType": "string",
      "label": "头像",
      "description": "用户头像图片的 URL,登录获取的"
    },
    "gender": {
      "bsonType": "number",
      "label": "性别",
      "description": "用户性别,1: 男;2: 女"
    },
	"personalize": {
	  "bsonType": "string",
	  "label": "个性签名",
	  "description": "个性签名,编辑资料获取"
	},
	"background": {
	  "bsonType": "object",
	  "label": "个人中心背景图",
	  "description": "个人中心背景图,编辑资料获取"
	},
    "mp_wx_openid": {
      "bsonType": "string",
      "description": "微信小程序平台openid"
    },
    "register_date": {
      "bsonType": "timestamp",
      "description": "注册时间",
      "forceDefaultValue": {
        "$env": "now"
      }
    }
  }
}

创建云函数

云函数代码

云函数 将 uni.login 取得的 code 获取到用户 session, 并对 数据库进行 增加、修改、查询 操作,第一次注册必须用户主动填写用户资料。

对云数据库的相关操作 传送门

js 复制代码
'use strict';

//小程序的AppID 和 AppSecret
const mp_wx_data = {AppID: '************', AppSecret: '***********************'}

//event为客户端上传的参数
exports.main = async (event, context) => {    

    //使用云数据库
    const db = uniCloud.database();    
    // 获取 `users` 集合的引用
    const pro_user = db.collection('users');
    // 通过 action 判断请求对象

    let result = {};
    switch (event.action) {        
        // 通过 code 获取用户 session
        case 'code2Session':
            const res_session = await uniCloud.httpclient.request('https://api.weixin.qq.com/sns/jscode2session', {
                    method: 'GET', data: {
                        appid: mp_wx_data.AppID,
                        secret: mp_wx_data.AppSecret,
                        js_code: event.js_code,
                        grant_type: 'authorization_code'
                    }, dataType: 'json'
                }
            )
            const success = res_session.status === 200 && res_session.data && res_session.data.openid
            if (!success) {
                return {
                    status: -2, msg: '从微信获取登录信息失败'
                }
            }
            
            //从数据库查找是否已注册过
            const res_user = await pro_user.where({
                mp_wx_openid: res_session.data.openid
            }).get()
            // 没有用户信息,进入注册
            if (res_user.data && res_user.data.length === 0) {
                //event.user_info 用户信息
                if (event.user_info) {
                    //有信息则进入注册,向数据库写入数据
                    const register = await uniCloud.callFunction({
                        name: 'user',
                        data: {
                            action: 'register',
                            open_id: res_session.data.openid,
                            user_info: event.user_info
                        }
                    }).then(res => {
                        result = res
                    })
                } else {
                    //没有信息返回{register: true}
                    result = {
                        result: {
                            result: {register: true}
                        }
                    }
                }
            } else {
                result = {
                    result: {
                        result:  res_user.data[0]
                    }
                }
            }
            break;
        //注册 向数据库写入数据
        case 'register':
            const res_reg = await pro_user.add({
                nickName: event.user_info.nickName,
                avatarUrl: event.user_info.avatarUrl,
                gender: event.user_info.gender,
                mp_wx_openid: event.open_id,
                register_date: new Date().getTime()
            })
            if (res_reg.id) {
                const res_reg_val = await uniCloud.callFunction({
                    name: 'user', data: {
                        action: 'getUser', open_id: event.open_id
                    }
                }).then(res => {
                    result = res
                })
            } else {
                result = {
                    status: -1, msg: '微信登录'
                }
            }
            break;
        case 'update':
            if (event._id && event.info) {
                const res_update = await pro_user.doc(event._id).update(event.info)
                if (res_update.updated >= 0) {
                    result = {status: 200, msg: '修改成功'}
                } else {
                    result = {status: -1, msg: '修改失败'}
                }
            } else {
                result = {status: -1, msg: '修改失败'}
            }
            break;
        case 'getUser':
            const res_val = await pro_user.where({
                mp_wx_openid: event.open_id
            }).get()
            return res_val.data[0]
            break;
    }
    return result;
};

微信登录操作

如上面所说,用户需手动上传资料,对于用户头像我们需要上传至云储存。

上传用户头像

上传图片函数参数为微信本地图片路径,我们对路径用/进行分割,取最后的图片名称进行上传

js 复制代码
/**
 * 上传图片至云存储
 */
export async function uploadImage(url) {
    const fileName = url.split('/')
    return new Promise(resolve => {
        uniCloud.uploadFile({
            filePath: url,
            cloudPath: fileName[fileName.length - 1],
            success(res) {
                resolve(res)
            },
            fail() {
                uni.showToast({
                    title: '图片上传失败!',
                    icon: 'none'
                })
                resolve(false)
            }
        })
    })
}

登录函数

如果用户第一次上传资料,我们需要先上传头像并取得图片链接,再将用户资料写入数据库。

js 复制代码
async wxLogin() {
      if (this.userInfo && this.userInfo.avatarUrl) {
        uni.showLoading({
          title: '正在上传图片...',
          mask: true
        });
        //上传头像至云储存并返回图片链接
        const imageUrl = await uploadImage(this.userInfo.avatarUrl)
        if (!imageUrl) {
          return
        }
        this.userInfo = {...this.userInfo, avatarUrl: imageUrl.fileID}
      }
      uni.showLoading({
        title: '登陆中...',
        mask: true
      });
      const _this = this
      uni.login({
        provider: 'weixin',
        success: (res) => {
          if (res.code) {
            //取得code并调用云函数
            uniCloud.callFunction({
              name: 'user',
              data: {
                action: 'code2Session',
                js_code: res.code,
                user_info: _this.userInfo
              },
              success: (res) => {
                 //如register为true,用户未填写资料
                if (res.result.result.result.register) {
                   //_this.showUserInfo 显示填写资料组件
                  _this.showUserInfo = true
                  uni.hideLoading();
                  return
                }
                if (res.result.result.result._id) {
                  const data = {
                    _id: res.result.result.result._id,
                    mp_wx_openid: res.result.result.result.mp_wx_openid,
                    register_date: res.result.result.result.register_date
                  }
                  this.loginSuccess(data)
                }
              },
              fail: () => {
                this.loginFail()
              }
            })
          }
        }
      })
    },

登录成功与失败

在用户登录成功后将数据存入 Storage 中,添加登录过期时间,我这里设置的是七天的登录有效期。

js 复制代码
loginSuccess(data) {
      updateTokenStorage(data)
      updateIsLoginStorage(true)
      uni.showToast({
        title: '登陆成功!',
        icon: 'none'
      });
      uni.navigateBack()
    },

将用户数据存入 Storage,并设置过期时间 expiresTime

js 复制代码
export function updateTokenStorage(data = null) {
    if (data) {
        const expiresTime = new Date().getTime() + 7 * 24 * 60 * 60 * 1000
        data = {...data, expiresTime: expiresTime}
    }
    uni.setStorageSync('user', data)
}

isLogin 用于判断是否是否登录

js 复制代码
export function updateIsLoginStorage(data = null) {
    uni.setStorageSync('isLogin', data)
}

登录失败

js 复制代码
loginFail() {
      updateTokenStorage()
      updateIsLoginStorage()
      uni.showToast({
        title: '登陆失败!',
        icon: 'none'
      });
    }

判断是否登录

除了判断 isLogin 还要判断 expiresTime 是否登录过期

js 复制代码
//判断是否登陆
export function isLogin() {
    try {
        const user = uni.getStorageSync('user')
        const isLogin = uni.getStorageSync('isLogin')
        const nowTime = new Date().getTime()
        return !!(isLogin && user && user._id && user.expiresTime > nowTime);
    } catch (error) {

    }
}

最后

至此就实现了微信登录并将用户信息存入数据库中,我们也可以通过云函数获取用户数据,做出用户个人主页。

以上是我做个人小程序时用的登录流程,整个小程序项目已上传至 GitHub。

GitHub地址

小程序码

相关推荐
瑶琴AI前端1 小时前
uniapp组件实现省市区三级联动选择
java·前端·uni-app
mosen8681 小时前
Uniapp去除顶部导航栏-小程序、H5、APP适用
vue.js·微信小程序·小程序·uni-app·uniapp
尚梦9 小时前
uni-app 封装刘海状态栏(适用小程序, h5, 头条小程序)
前端·小程序·uni-app
尚学教辅学习资料16 小时前
基于SSM+uniapp的营养食谱系统+LW参考示例
java·uni-app·ssm·菜谱
Bessie23416 小时前
微信小程序eval无法使用的替代方案
微信小程序·小程序·uni-app
qq22951165021 天前
小程序Android系统 校园二手物品交换平台APP
微信小程序·uni-app
qq22951165022 天前
微信小程序uniapp基于Android的流浪动物管理系统 70c3u
微信小程序·uni-app
qq22951165022 天前
微信小程序 uniapp+vue老年人身体监测系统 acyux
vue.js·微信小程序·uni-app
摇头的金丝猴2 天前
uniapp vue3 使用echarts-gl 绘画3d图表
前端·uni-app·echarts
小远yyds2 天前
跨平台使用高德地图服务
前端·javascript·vue.js·小程序·uni-app