使用 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 参数传递的实际应用代码分析
Sep 13 Javascript
firefox firebug中文入门教程 脚本之家新年特别版
Jan 02 Javascript
正则表达式中特殊符号及正则表达式的几种方法总结(replace,test,search)
Nov 26 Javascript
Jquery uploadify图片上传插件无法上传的解决方法
Dec 16 Javascript
jQuery中clone()方法用法实例
Jan 16 Javascript
JS数字抽奖游戏实现方法
May 04 Javascript
Bootstrap3 内联单选和多选框
Dec 29 Javascript
关于vue.extend和vue.component的区别浅析
Aug 16 Javascript
vuex提交state&amp;&amp;实时监听state数据的改变方法
Sep 16 Javascript
如何在selenium中使用js实现定位
Aug 18 Javascript
react实现复选框全选和反选组件效果
Aug 25 Javascript
Element-ui树形控件el-tree自定义增删改和局部刷新及懒加载操作
Aug 31 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截取中文字符串不乱码的方法
2013/12/25 PHP
yii实现图片上传及缩略图生成的方法
2014/12/04 PHP
Laravel 5 框架入门(一)
2015/04/09 PHP
javascript 兼容鼠标滚轮事件
2009/04/07 Javascript
用JavaScript对JSON进行模式匹配 (Part 2 - 实现)
2010/07/17 Javascript
jQuery中jqGrid分页实现代码
2011/11/04 Javascript
jQuery EasyUI API 中文文档 - Tree树使用介绍
2011/11/19 Javascript
javascript浏览器兼容教程之事件处理
2014/06/09 Javascript
JavaScript列表框listbox全选和反选的实现方法
2015/03/18 Javascript
js显示文本框提示文字的方法
2015/05/07 Javascript
javascript实现网页端解压并查看zip文件
2015/12/15 Javascript
JS组件Bootstrap实现弹出框效果代码
2016/04/26 Javascript
JavaScript数据存储 Cookie篇
2016/07/02 Javascript
分享一个精简的vue.js 图片lazyload插件实例
2017/03/13 Javascript
JS实现简单短信验证码界面
2017/08/07 Javascript
webpack+vue中使用别名路径引用静态图片地址
2017/11/20 Javascript
微信web端后退强制刷新功能的实现代码
2018/03/04 Javascript
基于Vue 服务端Cookies删除的问题
2018/09/21 Javascript
Webpack中SplitChunksPlugin 配置参数详解
2020/03/24 Javascript
微信h5静默和非静默授权获取用户openId的方法和步骤
2020/06/08 Javascript
Vue 3自定义指令开发的相关总结
2021/01/29 Vue.js
python 参数列表中的self 显式不等于冗余
2008/12/01 Python
使用Python中的线程进行网络编程的入门教程
2015/04/15 Python
简单的Apache+FastCGI+Django配置指南
2015/07/22 Python
python字典的值可以修改吗
2020/06/29 Python
我们在web应用开发过程中经常遇到输出某种编码的字符,如iso8859-1等,如何输出一个某种编码的字符串?
2014/03/30 面试题
物流经理自我评价
2013/09/23 职场文书
领导干部培训感言
2014/01/23 职场文书
《云房子》教学反思
2014/04/20 职场文书
教师批评与自我批评
2014/10/15 职场文书
2014年采购员工作总结
2014/11/18 职场文书
语文复习计划
2015/01/19 职场文书
php TP5框架生成二维码链接
2021/04/01 PHP
详解MySQL集群搭建
2021/05/26 MySQL
详解Java实践之抽象工厂模式
2021/06/18 Java/Android
python 判断字符串当中是否包含字符(str.contain)
2022/06/01 Python