ThinkPHP实现微信小程序微信授权登录
2021/4/7 20:09:00
本文主要是介绍ThinkPHP实现微信小程序微信授权登录,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
网上找了很多教程都不好使,最后自己又研究了一番,终于成功了
一、总体设计
小程序登录流程:客户端通过调用wx.login(),获取登录凭证(code),将此code发往服务器,服务器通过调用 auth.code2Session 接口,使用 code 换取 openid、unionid、session_key 等信息。
参考官方给出的时序图:
本实例中将openid作为用户唯一标识,存入数据库中。服务器后端通过ThinkPHP框架实现两个接口:
http://localhost/srclib/index.php/Home/User/wxlogin // 登录接口 http://localhost/srclib/index.php/Home/User/wxsign // 首次登录(微信授权登录)接口
1. 登录状态的维持
小程序在初始化时,在小程序onLaunch生命周期函数中调用wx.login(),向登录接口发送请求,将code发送给服务器。服务器接收到code后,调用https://api.weixin.qq.com/sns/jscode2session接口,将code,appid和appSecret发送给微信官方服务器,服务器会收到用户唯一标识openid和会话密钥 session_key等信息。
此时服务器后台在数据库User表中查询openid:
-
如果在User表中没有查到该记录,则说明此用户是新用户,还未授权微信登录,服务器返回客户端的状态码err_code值为1,表示不存在该用户,需要用户手动授权微信登录;
-
如果在User表中查到了该记录,则表示用户已授权微信登录,此时服务器返回客户端的状态码err_code值为0,表示登录成功,服务器将用户信息和状态码发送至前端。
客户端在接收到状态码后判断:
-
若状态码为0,则表示登录成功。客户端接收到用户信息后,通过调用wx.setStorageSync()将用户信息加入本地缓存,并将登录状态设置为true,此时实现了登录状态的维持;
-
若状态码为1,表示用户还未授权登录,此时跳转至auth页等待用户的授权操作。
首次授权后,小程序每次启动时,自动调用登录接口,并将在本地缓存中更新用户信息和登录状态,小程序其他页面在初始化时调用_initial()函数,从本地缓存中取出用户信息和登录状态,赋值给全局变量userInfo和loginState,此后小程序页面渲染时便可从全局变量获取用户信息,设置给页面对象的data属性值。
2. 微信授权登录的实现
微信官方提供了wx.getUserProfile接口,使用获取用户信息。在页面中加入一个button,监听用户点击,点击后获取用户信息,本实例中主要获取了用户昵称nickName和用户头像地址avatarUrl。之后向(微信授权登录)首次登录接口发送请求,输入数据为code、nickName和avatarUrl。
服务端接收到这些参数后,首先调用https://api.weixin.qq.com/sns/jscode2session接口,将code,appid和appSecret发送给微信官方服务器,服务器会收到用户唯一标识openid等参数,然后在数据库User表中查询该openid:
-
如果在User表中没有查到该记录,则将openid、nickName和avatarUrl构建为一条用户记录数据,插入User表中,服务器返回客户端的状态码err_code值为0,表示新用户授权登录成功,服务器将用户信息和状态码发送至前端;
-
如果在User表中查到了该记录,则表示该用户重复授权,抛出异常,此时服务器返回客户端的状态码err_code值为1。
二、步骤说明
1. 用户首次进入,显示授权登录按钮
2. 点击授权登录按钮,出现提示弹窗
3. 点击允许后,登录成功,跳转至个人中心页
4. 此后用户再次进入小程序,已自动登录,实现了登录状态的维持
三、完整代码:
1. 小程序前端:
app.js
// app.js App({ globalData: { loginState: false, // 用户登录状态 userInfo: null // 用户信息 }, onLaunch() { this.login() // 登录 }, _initial() { // Page初始化函数,用于读取本地缓存,并更新全局变量 this.globalData.userInfo = wx.getStorageSync('userInfo') this.globalData.loginState = wx.getStorageSync('loginState') console.log("登录状态:"+this.globalData.loginState) console.log("用户信息:") console.log(this.globalData.userInfo) }, login() { let _this = this // 登录请求 wx.login({ success: res => { wx.request({ url: 'http://localhost/srclib/index.php/Home/User/wxlogin', method: 'post', data: { code: res.code }, header: { "Content-Type": "application/x-www-form-urlencoded" }, success: function (res) { if(res.data.error_code == 1) { // 用户未授权登录 console.log("error") wx.setStorageSync('loginState', false) wx.navigateTo({ // 跳转至授权页,等待用户授权 url: '../auth/auth', }) } else if(res.data.error_code == 0) { // 登录成功 wx.setStorageSync('userInfo', res.data.data) // 更新本地缓存 wx.setStorageSync('loginState', true) } } }) } }) } })
profile.js
// pages/profile/profile.js const app = getApp() const globalData = getApp().globalData Page({ data: { userInfo: null }, onl oad() { app._initial() // 页面初始化 this.setData({ userInfo: globalData.userInfo }) } })
auth.js
// auth.js const app = getApp() const globalData = getApp().globalData Page({ data: { userInfo: null }, onl oad() { app._initial() // 页面初始化 }, getUserProfile(e) { // 使用wx.getUserProfile获取用户信息 wx.getUserProfile({ desc: '展示用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中 success: (res) => { globalData.userInfo = res.userInfo this.setData({ userInfo: globalData.userInfo }) this.sign() } }) }, sign() { let _this = this wx.showLoading({ title: '加载中', }) // 用户首次登录请求 wx.login({ success: res => { wx.request({ url: 'http://localhost/srclib/index.php/Home/User/wxsign', method: 'post', data: { code: res.code, name: globalData.userInfo.nickName, avatarUrl: globalData.userInfo.avatarUrl }, header: { "Content-Type": "application/x-www-form-urlencoded" }, success: function (res) { if(res.data.error_code == 1) { // 用户登录失败 console.log("error") } else if(res.data.error_code == 0) { // 用户登录成功 wx.setStorageSync('userInfo', res.data.data) // 更新本地缓存 wx.setStorageSync('loginState', true) wx.hideLoading() wx.showToast({ title: '授权成功', icon: 'success', duration: 2000, complete: (res) => { wx.navigateTo({ // 跳转至个人中心页 url: '../profile/profile', }) }, }) } } }) } }) } })
profile.wxml
<!--pages/profile/profile.wxml--> <view class="container"> <view class="userinfo"> <image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.face_url}}" mode="cover"></image> <text class="userinfo-nickname">{{userInfo.username}}</text> </view> <view class="usermotto"> <text class="user-motto">{{loginState}}</text> </view> </view>
auth.wxml
<!--auth.wxml--> <view class="container"> <button type="primary" bindtap="getUserProfile">授权微信登录</button> </view>
2. 服务器后端
<?php namespace Home\Controller; use Think\Controller; class UserController extends BaseController { /** * 微信登录 * @return [type] [description] */ public function wxlogin() { // 校验参数是否存在 if (!$_POST['code']) { $return_data = array(); $return_data['error_code'] = 2; $return_data['msg'] = '参数不足: code'; $this->ajaxReturn($return_data); } else { $appid = "wxc6a376950e1c45c0"; // appid $secret = "632hjdcba4c2b972c591738hdga91fvg"; // app密钥 $code = $_POST['code']; // 小程序传来的code值 $curl = curl_init(); $url = "https://api.weixin.qq.com/sns/jscode2session?appid=" . $appid . "&secret=" . $secret . "&js_code=" . $code . "&grant_type=authorization_code"; curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_HEADER, 0); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $result = curl_exec($curl); $json = json_decode($result); // 对json数据解码 $arr = get_object_vars($json); $openid = $arr['openid']; curl_close($curl); // 检验是否已经注册 $User = M('User'); // 构造查询条件 $where = array(); $where['openid'] = $openid; $user = $User->where($where)->find(); if ($user) { $return_data = array(); $return_data['error_code'] = 0; $return_data['msg'] = '登录成功'; $return_data['data']['userid'] = $user['userid']; $return_data['data']['username'] = $user['username']; $return_data['data']['face_url'] = $user['face_url']; $this->ajaxReturn($return_data); } else { $return_data = array(); $return_data['error_code'] = 1; $return_data['msg'] = '不存在该用户,请授权登录'; $this->ajaxReturn($return_data); } } } /** *首次授权登录 * @return [type] [description] */ public function wxsign() { // 校验参数是否存在 if (!$_POST['code']) { $return_data = array(); $return_data['error_code'] = 2; $return_data['msg'] = '参数不足: code'; $this->ajaxReturn($return_data); } else if (!$_POST['name']) { $return_data = array(); $return_data['error_code'] = 2; $return_data['msg'] = '参数不足: name'; $this->ajaxReturn($return_data); } else if (!$_POST['avatarUrl']) { $return_data = array(); $return_data['error_code'] = 2; $return_data['msg'] = '参数不足: avatarUrl'; $this->ajaxReturn($return_data); } else { $appid = "wxc6a376950e1c45c0"; // appid $secret = "632hjdcba4c2b972c591738hdga91fvg"; // app密钥 $code = $_POST['code']; // 小程序传来的code值 $curl = curl_init(); $url = "https://api.weixin.qq.com/sns/jscode2session?appid=" . $appid . "&secret=" . $secret . "&js_code=" . $code . "&grant_type=authorization_code"; curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_HEADER, 0); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $result = curl_exec($curl); $json = json_decode($result); // 对json数据解码 $arr = get_object_vars($json); $openid = $arr['openid']; curl_close($curl); // 检验是否已经授权过 $User = M('User'); // 构造查询条件 $where = array(); $where['openid'] = $openid; $user = $User->where($where)->find(); if ($user) { $return_data = array(); $return_data['error_code'] = 1; $return_data['msg'] = '登录失败'; $this->ajaxReturn($return_data); } else { // 如果用户尚未注册,则注册 // 构建插入的数据 $data = array(); $data['openid'] = $openid; $data['username'] = $_POST['name']; $data['face_url'] = $_POST['avatarUrl']; // 插入数据 $result = $User->add($data); // add数据添加成功之后,返回的就是该条数据的id if ($result) { // 插入数据执行成功 $return_data = array(); $return_data['error_code'] = 0; $return_data['msg'] = '登录成功'; $return_data['data']['userid'] = $result; $return_data['data']['username'] = $_POST['name']; $return_data['data']['face_url'] = $_POST['avatarUrl']; $this->ajaxReturn($return_data); } else { // 插入数据执行失败 $return_data = array(); $return_data['error_code'] = 1; $return_data['msg'] = '登录失败'; $this->ajaxReturn($return_data); } } } } }
这篇关于ThinkPHP实现微信小程序微信授权登录的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-03-29env: php: no such file or directory
- 2024-03-01php foreach break
- 2024-02-26Exception参数 php-icode9专业技术文章分享
- 2023-12-30PHP文件批量上传-icode9专业技术文章分享
- 2023-12-30thinkphp6 withJoin-icode9专业技术文章分享
- 2023-12-27MagicArray:像php一样,让Go业务代码不再卷!
- 2023-11-18centos7编译安装PHP教程。
- 2023-11-18centos7编译安装phpMyAdmin教程。
- 2023-10-13唱衰这么多年,PHP 仍然还是你大爷!
- 2023-07-25PHP8,性能更好,语法更好,类型安全更完善