使用 UniApp 实现小程序的微信登录功能


Posted in Javascript onJune 09, 2020

1.微信登录思路:

  • 在main.js 中封装公共函数,用于判断用户是否登录
  • 在main.js 中分定义全局变量,用于存储接口地址
  • 如果没有登录、则跳转至登录页面
  • 进入登录页面
  • 通过 wx.login 获取用户的 code
  • 通过 code 获取用户的 SessionKey、OpenId 等信息【本应后台接口、但是此处使用js发送请求】
  • 通过 openId 调用后台 Api 获取用户的信息
  • 获取成功,则说明已经授权过了,直接登录成功
  • 获取失败,则说明没有授权过,需要授权之后才能进行登录
  • 用户点击页面微信登录按钮【 <button open-type="getUserInfo"></button>】
  • 获取用户数据,然后调用后台接口写入数据库

2.在 applets/main.js 中添加如下

// 封装全局登录函数
// backpage, backtype 2个参数分别代表:
// backpage : 登录后返回的页面
// backtype : 打开页面的类型[1 : redirectTo 2 : switchTab]
Vue.prototype.checkLogin = function( backpage, backtype ){
	// 同步获取本地数据(uid、随机码、用户名、头像)
	var user_id = uni.getStorageSync('user_id');
	var user_nu = uni.getStorageSync('user_nu');
	var user_nm = uni.getStorageSync('user_nm');
	var user_fa = uni.getStorageSync('user_fa');
	if( user_id == '' || user_nu == '' || user_fa == ''){
		// 使用重定向的方式跳转至登录页面
		uni.redirectTo({url:'../login/login?backpage='+backpage+'&backtype='+backtype});
		return false;
	}
	// 登录成功、已经登录返回数组 [用户 id, 用户随机码, 用户昵称, 用户表情]
	return [user_id, user_nu, user_nm, user_fa];
}
// 定义一个全局的请求地址
Vue.prototype.apiServer = 'http://0608.cc/'

3.在 pages/login/login.vue 中添加如下

<template>
	<view>
		<!-- login view html start -->
		<view>
			<view>
				<view class="header"><image src="/static/img/public/login-wx.png"></image></view>
				<view class="content">
					<view>申请获取以下权限</view>
					<text>获得你的公开信息(昵称,头像、地区等)</text>
				</view>
				<button class="bottom" type="primary" open-type="getUserInfo" withCredentials="true" lang="zh_CN" @getuserinfo="wxGetUserInfo">授权登录</button>
			</view>
		</view>
		<!-- login view html end -->
	</view>
</template>

<script>
export default {
	data() {
		return {
			appid: '*************',
			secret: '*************************',
			code: '',
			sessionKey: '',
			openId: '',
			userInfo: {
				avatarUrl: '',
				city: '',
				country: '',
				gender: 1,
				language: '',
				nickName: ''
			},
			pageOption: {}
		};
	},
	methods: {
		// 第一授权获取用户信息 ===》按钮触发
		wxGetUserInfo() {
			let _self = this;
			// 1.获取用户的信息
			uni.getUserInfo({
				provider: 'weixin',
				success: ( infoRes ) => {
					console.log( infoRes )
					_self.userInfo = infoRes.userInfo
					// 2.提交数据到后台、写入数据库
					uni.request({
						url: _self.apiServer + 'appletsUserInfo',
						data: {
							openid: _self.openId,
							avatarUrl: _self.userInfo.avatarUrl,
							city: _self.userInfo.city,
							country: _self.userInfo.country,
							gender: _self.userInfo.gender,
							language: _self.userInfo.language,
							nickName: _self.userInfo.nickName
						},
						method: 'POST',
						success: res => {
							if( res.data.code != 0 )
							{
								uni.showToast({ title: res.data.msg, icon: 'none' });
								return false;
							}
							// 用户信息写入缓存
							uni.showToast({title: '登录成功'})
							uni.setStorageSync( 'user_id', res.data.res.u_id );
							uni.setStorageSync( 'user_nm', res.data.res.u_nickName );
							uni.setStorageSync( 'user_fa', res.data.res.u_avatarUrl );
							uni.setStorageSync( 'user_nu', res.data.res.u_regtime );
							// 然后跳回原页面
							if( _self.pageOption.backtype == 1 )
							{
								uni.redirectTo({ url: _self.pageOption.backpage })
							}else{
								uni.switchTab({ url: _self.pageOption.backpage })
							}
						},
						fail: () => {
							uni.showToast({ title: '用户信息操作失败', icon: 'none' });
						}
					});
				},
				fail: () => {
					uni.showToast({ title: '获取用户信息失败', icon: 'none' });
				}
			});
			return false
		},
		// 登录
		login() {
			let _self = this;

			// 0. 显示加载的效果
			uni.showLoading({
				title: '登录中...'
			});

			// 1. wx 获取登录用户 code
			uni.login({
				provider: 'weixin',
				success: loginRes => {
					console.log(loginRes);
					_self.code = loginRes.code;
					// 2. 将用户登录code传递到后台置换用户SessionKey、OpenId等信息
					uni.request({
						url:
							'https://api.weixin.qq.com/sns/jscode2session?appid=' +
							_self.appid +
							'&secret=' +
							_self.secret +
							'&js_code=' +
							_self.code +
							'&grant_type=authorization_code',
						success: codeRes => {
							console.log(codeRes);
							_self.openId = codeRes.data.openid;
							_self.sessionKey = codeRes.data.session_key;
							// 3.通过 openId 判断用户是否授权
							uni.request({
								url: _self.apiServer + 'loginApplets',
								data: {
									openid: _self.openId
								},
								method: 'POST',
								success: openIdRes => {
									console.log(openIdRes);
									// 隐藏loading
									uni.hideLoading();
									// 还没授权登录、请先授权然后登录
									if (openIdRes.data.code == 1) {
										// 提示消息、让用户授权
										uni.showToast({ title: openIdRes.data.msg, icon: 'none' });
									}
									// 已经授权了、查询到用户的数据了
									if (openIdRes.data.code == 0) {
										// 用户信息写入缓存
										uni.showToast({title: '登录成功'})
										uni.setStorageSync( 'user_id', openIdRes.data.res.u_id );
										uni.setStorageSync( 'user_nm', openIdRes.data.res.u_nickName );
										uni.setStorageSync( 'user_fa', openIdRes.data.res.u_avatarUrl );
										uni.setStorageSync( 'user_nu', openIdRes.data.res.u_regtime );
										// 然后跳回原页面
										if( _self.pageOption.backtype == 1 )
										{
											uni.redirectTo({ url: _self.pageOption.backpage })
										}else{
											uni.switchTab({ url: _self.pageOption.backpage })
										}
									}
								},
								fail: () => {
									uni.showToast({ title: '获取授权信息失败', icon: 'none' });
									return false;
								}
							});
						},
						fail: () => {
							uni.showToast({ title: '获取 SesssionKey OpenId 失败', icon: 'none' });
							return false;
						}
					});
				},
				fail: () => {
					uni.showToast({ title: '获取 code 失败', icon: 'none' });
					return false;
				}
			});
			return false;
		}
	},
	onLoad( options ) {
		// 接收跳转的参数
		this.pageOption = options
		//默认加载
		this.login();
	}
};
</script>

<style>
.header {
	margin: 90rpx 0 90rpx 50rpx;
	border-bottom: 1px solid #ccc;
	text-align: center;
	width: 650rpx;
	height: 300rpx;
	line-height: 450rpx;
}

.header image {
	width: 200rpx;
	height: 200rpx;
}

.content {
	margin-left: 50rpx;
	margin-bottom: 90rpx;
}

.content text {
	display: block;
	color: #9d9d9d;
	margin-top: 40rpx;
}

.bottom {
	border-radius: 80rpx;
	margin: 70rpx 50rpx;
	font-size: 35rpx;
}
</style>

在 pages/my/my.vue 中添加如下:

<template>
	<view>我的页面</view>
</template>

<script>
var loginRes;
export default {
	data() {
		return {};
	},
	onLoad() {
		// 加载定义好的方法
		loginRes = this.checkLogin('../my/my', 2);
		// 没有登录成功,返回空
		if (!loginRes) {
			return;
		}
	},
	methods: {}
};
</script>

<style></style>

5.PHP 接口 loginApplets

public function loginApplets(Request $request, UserInfo $userInfo)
{
 // 获取数据
 $data['u_openid'] = $request->param('openid', '');
 // 验证数据
 $rule = [
  'u_openid' => 'require|max:200|min:10'
 ];
 $message = [
  'u_openid.require' => 'openid 不能为空',
  'u_openid.max'  => 'openid 格式错误',
  'u_openid.min'  => 'openid 格式错误'
 ];
 $validate = Validate::rule($rule)->message($message);
 if (!$validate->check($data)) {
  return json(['code' => 1, 'msg' => $validate->getError(), 'res' => null]);
 }
 // 根据 openid 判断是否存在
 $where['u_openid'] = $data['u_openid'];
 $user = $userInfo->selOne($where);
 if (!$user) {
  return json(['code' => 1, 'msg' => '还没授权登录、请先授权然后登录', 'res' => $user]);
 }
 return json(['code' => 0, 'msg' => '已授权获取到用户的数据', 'res' => $user]);
}

6.PHP 接口 appletsUserInfo

public function appletsUserInfo(Request $request, UserInfo $userInfo)
{
 // 获取数据
 $data['u_openid'] = $request->param('openid', '');
 $data['u_avatarUrl'] = $request->param('avatarUrl', '');
 $data['u_city'] = $request->param('city', '');
 $data['u_country'] = $request->param('country', '');
 $data['u_gender'] = $request->param('gender', '');
 $data['u_language'] = $request->param('language', '');
 $data['u_nickName'] = $request->param('nickName', '');
 // 验证数据
 $rule = [
  'u_openid' => 'require|max:200|min:10',
  'u_avatarUrl' => 'require',
  'u_nickName' => 'require'
 ];
 $message = [
  'u_openid.require'  => 'openid 不能为空',
  'u_openid.max'   => 'openid 格式错误',
  'u_openid.min'   => 'openid 格式错误',
  'u_avatarUrl.require' => '用户头像 不能为空',
  'u_nickName.max'  => '用户名 格式错误',
 ];
 $validate = Validate::rule($rule)->message($message);
 if (!$validate->check($data)) {
  return json(['code' => 1, 'msg' => $validate->getError(), 'res' => null]);
 }

 // 根据 openid 判断是否存在
 $where['u_openid'] = $data['u_openid'];
 $user = $userInfo->selOne($where);

 // 存在、执行修改
 if ($user) {
  $user_res = $userInfo->updOne($where, $data);
  $res = [];
  $res['u_id'] = $user['u_id'];
  $res['u_regtime'] = $user['u_regtime'];
 }

 // 不存在、执行添加
 if (empty($user)) {
  $res = [];
  $res = $data;
  $res['u_regtime'] = time();
  $res['u_id'] = $userInfo->addOne($res);
 }

 // 判断是否添加成功
 if (empty($res['u_id'])) {
  return json(['code' => 1, 'msg' => '注册失败,返回重试', 'res' => null]);
 }
 return json(['code' => 0, 'msg' => 'ok', 'res' => $res]);
}

总结

到此这篇关于使用 UniApp 实现小程序的微信登录的文章就介绍到这了,更多相关使用 UniApp 实现小程序的微信登录内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
JS下拉框内容左右移动效果的具体实现
Jul 10 Javascript
jQuery实现鼠标单击网页文字后在文本框显示的方法
May 06 Javascript
jquery实现Li滚动时滚动条自动添加样式的方法
Aug 10 Javascript
解析JavaScript面向对象概念中的Object类型与作用域
May 10 Javascript
JS常用知识点整理
Jan 21 Javascript
Vue.js实现简单动态数据处理
Feb 13 Javascript
jQuery插件HighCharts实现的2D面积图效果示例【附demo源码下载】
Mar 15 Javascript
原生JS+Canvas实现五子棋游戏实例
Jun 19 Javascript
layui中layer前端组件实现图片显示功能的方法分析
Oct 13 Javascript
Vue内部渲染视图的方法
Sep 02 Javascript
vue实现户籍管理系统
May 29 Javascript
解决vue+webpack项目接口跨域出现的问题
Aug 10 Javascript
详解vue高级特性
Jun 09 #Javascript
vue实例的选项总结
Jun 09 #Javascript
微信小程序中的列表切换功能实例代码详解
Jun 09 #Javascript
vue项目或网页上实现文字转换成语音播放功能
Jun 09 #Javascript
浅谈vue的第一个commit分析
Jun 08 #Javascript
从零开始在vue-cli4配置自适应vw布局的实现
Jun 08 #Javascript
详解Vue Cli浏览器兼容性实践
Jun 08 #Javascript
You might like
PHP统计目录下的文件总数及代码行数(去除注释及空行)
2011/01/17 PHP
php curl 伪造IP来源的实例代码
2012/11/01 PHP
smarty中改进truncate使其支持中文的方法
2016/05/30 PHP
详解phpstorm2020最新破解方法
2020/09/17 PHP
类似CSDN图片切换效果脚本
2009/09/17 Javascript
基于JQuery框架的AJAX实例代码
2009/11/03 Javascript
js从Cookies里面取值的简单实现
2014/06/30 Javascript
Javascript基础教程之变量
2015/01/18 Javascript
jQuery插件slicebox实现3D动画图片轮播切换特效
2015/04/12 Javascript
jquery实现Slide Out Navigation滑出式菜单效果代码
2015/09/07 Javascript
基于jquery编写分页插件
2016/03/07 Javascript
Javascript数组Array基础介绍
2016/03/13 Javascript
JS与Ajax Get和Post在使用上的区别实例详解
2016/06/08 Javascript
Bootstrap基本插件学习笔记之模态对话框(16)
2016/12/08 Javascript
Node.js Express 框架 POST方法详解
2017/01/23 Javascript
Vue.js使用$.ajax和vue-resource实现OAuth的注册、登录、注销和API调用
2017/05/10 Javascript
js异步编程小技巧详解
2017/08/14 Javascript
JS遍历DOM文档树的方法实例详解
2018/04/03 Javascript
通过封装scroll.js 获取滚动条的值
2018/07/13 Javascript
Flutter 超实用简单菜单弹出框 PopupMenuButton功能
2019/08/06 Javascript
基于Echarts图表在div动态切换时不显示的解决方式
2020/07/20 Javascript
[04:00]DOTA2解说界神雕侠侣 CJ第四天谷子现场过生日
2013/07/30 DOTA
Python中urllib+urllib2+cookielib模块编写爬虫实战
2016/01/20 Python
在python中实现调用可执行文件.exe的3种方法
2019/07/07 Python
django删除表重建的实现方法
2019/08/28 Python
python常用排序算法的实现代码
2019/11/08 Python
Python爬虫Scrapy框架CrawlSpider原理及使用案例
2020/11/20 Python
吉列剃须刀美国官网:Gillette美国
2018/07/13 全球购物
C++:memset ,memcpy和strcpy的根本区别
2013/04/27 面试题
师范生实习的个人自我鉴定
2013/10/20 职场文书
资料员岗位职责
2013/11/17 职场文书
总经理驾驶员岗位职责
2013/12/04 职场文书
装修五一活动策划案
2014/01/23 职场文书
楼面经理岗位职责范本
2014/02/18 职场文书
施工员岗位职责
2014/03/16 职场文书
校园标语大全
2014/06/19 职场文书