使用 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 相关文章推荐
IE FF OPERA都可用的弹出层实现代码
Sep 29 Javascript
jQuery插件-jRating评分插件源码分析及使用方法
Dec 28 Javascript
基于jquery扩展漂亮的CheckBox(自己编写)
Nov 19 Javascript
关于延迟加载JavaScript
May 05 Javascript
javascript实现可键盘控制的抽奖系统
Mar 10 Javascript
jQuery多个版本和其他js库冲突的解决方法
Aug 11 Javascript
JSON 对象未定义错误的解决方法
Sep 29 Javascript
js实现自动轮换选项卡
Jan 13 Javascript
Bootstrap提示框效果的实例代码
Jul 12 Javascript
VueJs监听window.resize方法示例
Jan 17 Javascript
Vue项目引进ElementUI组件的方法
Nov 11 Javascript
通过实例解析JavaScript常用排序算法
Sep 02 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
实用函数4
2007/11/08 PHP
php多维数组去掉重复值示例分享
2014/03/02 PHP
PHP过滤黑名单关键字的方法
2014/12/01 PHP
php session的锁和并发
2016/01/22 PHP
twig模板获取全局变量的方法
2016/02/05 PHP
PHP-CGI远程代码执行漏洞分析与防范
2017/05/07 PHP
JavaScript中的私有成员
2006/09/18 Javascript
Javascript 按位与运算符 (&amp;)使用介绍
2014/02/04 Javascript
JS实现仿google、百度搜索框输入信息智能提示的实现方法
2015/04/20 Javascript
JavaScript设计模式经典之工厂模式
2016/02/24 Javascript
Javascript将双字节字符转换成单字节字符并计算长度
2016/06/22 Javascript
如何用js判断dom是否有存在某class的值
2017/02/13 Javascript
基于Bootstrap的网页设计实例
2017/03/01 Javascript
Material(包括Material Icon)在Angular2中的使用详解
2018/02/11 Javascript
python实现带声音的摩斯码翻译实现方法
2015/05/20 Python
Python3实现从指定路径查找文件的方法
2015/05/22 Python
Python首次安装后运行报错(0xc000007b)的解决方法
2016/10/18 Python
Python实现求两个csv文件交集的方法
2017/09/06 Python
用Python分析3天破10亿的《我不是药神》到底神在哪?
2018/07/12 Python
tensorflow实现图像的裁剪和填充方法
2018/07/27 Python
详解python实现识别手写MNIST数字集的程序
2018/08/03 Python
对Python3 序列解包详解
2019/02/16 Python
pygame实现成语填空游戏
2019/10/29 Python
Python模拟FTP文件服务器的操作方法
2020/02/18 Python
keras 多任务多loss实例
2020/06/22 Python
微软澳洲官方网站:Microsoft Australia
2017/01/10 全球购物
德国黑胶唱片、街头服装及运动鞋网上商店:HHV
2018/08/24 全球购物
Desigual美国官方网站:西班牙服装品牌
2019/03/29 全球购物
荣耀商城:HIHONOR
2020/11/03 全球购物
介绍一下MYSQL常用的优化技巧
2012/10/25 面试题
如何写一个Java类既可以用作applet也可以用作java应用
2016/01/18 面试题
考察现实表现材料
2014/05/19 职场文书
企业晚会策划方案
2014/05/29 职场文书
爱国主义影片观后感
2015/06/18 职场文书
2016年端午节寄语
2015/12/04 职场文书
2019年度开业庆典祝福语大全!
2019/07/05 职场文书