在初学微信开发的时候因为没有经验,再加上微信的官方文档不够清晰,致使看完文档以后只剩下”抓瞎“,根本不知道微信开发是怎样一个流程,也不知道如何开始,因而不得不去查阅第三方博客。
后来终于完成了微信公众号和服务器的对接,实现了网页受权,而且,用户能够直接点击公众号下方的按钮,自动获取OpenID登陆,不用再进行传统的手动登陆了。网页受权自动登陆,也就是本文须要实现的功能。php
网页受权,就是用户向公众号受权,让开发者经过此用户的惟一识别码(OpenID)得到此用户的身份。通俗的讲,就是用户给开发者提交一个“身份证”,让开发者知道当前正在访问的用户是谁。微信官方文档——网页受权html
一般状况下,用户是直接访问开发者的服务器,获取服务器返回的数据。因为http协议是匿名的,在这种状况下,服务器不知道当前访问的用户是谁,识别用户身份的惟一办法就是经过Cookie和Session,然而,因为Cookie具备时效性,用户仍是在一些状况下仍是要手动登陆。
直接链接开发者服务器的时序图:
(图片出自梦云智软件开发团队ThinkPHP5.1入门实例教程)web
而微信网页受权的优点在于,能够给每个微信帐号分配一个惟一的识别码(也就是OpenID),经过这个识别码,微信服务器就能够知道当前登陆的用户是谁,而后把此用户的信息告诉开发者的服务器,这样开发者就获取了用户身份,而且能够实现把用户在网站的帐号和用户的微信号绑定起来,这样,之后用户经过微信登陆网站时就再也不用手动登陆了。
经过链接微信服务器获取用户信息的时序图:thinkphp
微信的公众号有两种——订阅号和服务号,订阅号一般适用于我的(自媒体、学校的小型组织),服务号适用于企业。订阅号没有网页受权的权限,服务号只有在认证以后可使用网页受权。微信接口权限说明json
因此,只有订阅号的小伙伴能够洗洗睡了...但是做为开发者,若是出于学习的目的想尝试网页受权的话,能够去申请微信测试号,测试号具备全部的微信接口权限。申请接口测试号api
本文假设用户已经完成了公众号和服务器的绑定,设置好了服务器地址。服务器
在公众号刚刚建立的时候,主页面是这样的,只有聊天框:
而咱们但愿是这样:微信
那么,怎么定义这些按钮呢?微信为咱们提供了一个很好的接口测试工具,咱们能够利用这个工具来定义按钮。
首先选择基础支持,获取AccessToken(这个是公众号的全局AccessToken而不是网页受权的AccessToken)
填入正确的APPID和Secret以后,下面返回了AccessToken有效期7200秒。
复制这串字符,而后把接口切换到自定义菜单查询接口,把刚刚获取的token粘贴进去。
若是这个公众号以前设置过按钮,就会出现因此按钮的代码:网络
{ "menu": { "button": [ { "name": "学生菜单", "sub_button": [ { "type": "view", "name": "学生主页", "url": "http://awjdjsz.jincheng4917.cn/index/WxIndex/page", "sub_button": [ ] }, { "type": "view", "name": "课程查询", "url": "http://awjdjsz.jincheng4917.cn/index/WxIndex/course", "sub_button": [ ] }, { "type": "view", "name": "成绩查询", "url": "http://awjdjsz.jincheng4917.cn/index/WxIndex/score", "sub_button": [ ] }, { "type": "view", "name": "我的信息", "url": "http://awjdjsz.jincheng4917.cn/index/WxIndex/info", "sub_button": [ ] } ] }, { "name": "教师菜单", "sub_button": [ { "type": "view", "name": "教师主页", "url": "http://awjdjsz.jincheng4917.cn/index/WxIndex/tpage", "sub_button": [ ] }, { "type": "view", "name": "课程管理", "url": "http://awjdjsz.jincheng4917.cn/index/WxIndex/tcourse", "sub_button": [ ] }, { "type": "view", "name": "成绩录入", "url": "http://awjdjsz.jincheng4917.cn/index/WxIndex/tgrade", "sub_button": [ ] } ] }, { "type": "scancode_push", "name": "扫码进入课堂", "key": "rselfmenu_0_1", "sub_button": [ ] } ] } }
若是是一次设置,能够把上面的代码加以改造,而后把接口改成自定义菜单建立接口,而后输入改好的代码。
注意:查询结果的代码用于建立按钮时,必须把第二行和倒数第二行的"menu"{}删掉,否则会报错。
点击建立以后,刷新公众号,按钮已经出现了。微信开发
咱们仍是要拿出这张时序图
实际上已经在刚才完成了,就是在公众号按钮中设置连接,让用户经过按钮访问ThnkPHP的某个方法。
//你的微信公众号appid protected $appid='wx4b4890b3f8c0ada5'; //你的微信公众号secret protected $appsecret = '7634c6e2889e0d366e4ff2e58bc520fa'; //用户访问这个方法 public function weChatAccredit($buttonType) { //这个地址是回调地址 $url = 'http://'.$_SERVER['HTTP_HOST'].'/index/WxIndex/getChatInfo'; //调用方法 accredit($url,$buttonType); } //用于访问服务器的方法 public function accredit($redirect_url,$state){ //拼接URL $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->appid}&redirect_uri={$redirect_url}&response_type=code&scope=snsapi_userinfo&state={$state}#wechat_redirect"; //重定向 $this->redirect($url); }
到目前为止,用户重定向访问微信服务器以后,就会带着code回调开发者服务器,所以咱们就要拿code继续换取AccessToken
//回调到这个方法 public function getChatInfo(){ $we_chat = new WxController();//实例化微信类 $code = $_GET['code']; //获取跳转后的code $state = $_GET['state']; //获取state $access_token = getAccessToken($code); //根据code获取token 根据access_token和openid获取到用户信息 $we_chat_user_info = getWeChatUserInfo($access_token['access_token'],$access_token['openid']); $this->gogogo($state,$access_token["openid"]); public function getAccessToken($code){ $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$this->appid}&secret={$this->appsecret}&code={$code}&grant_type=authorization_code"; $res = file_get_contents($url); //获取文件内容或获取网络请求的内容 $access_token = json_decode($res,true); return $access_token; } public function getWeChatUserInfo($access_token,$openid){ $url = "https://api.weixin.qq.com/sns/userinfo?access_token={$access_token}&openid={$openid}&lang=zh_CN"; $output = file_get_contents($url); $weChatUserInfo = json_decode($output,true); return $weChatUserInfo; }
到此,开发者服务器已经成功获取到用户信息,而后就能够自行编写gogogo()这个方法,经过OpenID进行登陆操做,实现自动登陆,登陆以后把用户请求的网页返回给用户了。
<?php namespace app\index\controller; use app\index\controller\WxController; use app\index\controller\StudentController; use app\index\controller\LoginController; use app\index\model\Student; use app\index\model\Teacher; use app\index\model\Term; class WxindexController extends WxController { public static $openIdTest = 'openIdTest'; public static $page = 'page'; public static $score = 'score'; public static $course = 'course'; public static $info = 'info'; public function page(){ // 跳转到主页 $this->weChatAccredit($this::$page); } public function course(){ // 跳转到课程查询 $this->weChatAccredit($this::$course); } public function score(){ // 跳转到成绩查询 $this->weChatAccredit($this::$score); } public function info(){ // 跳转到我的信息 $this->weChatAccredit($this::$info); } /** * 微信按钮跳转受权 */ public function weChatAccredit($buttonType) { $url = 'http://'.$_SERVER['HTTP_HOST'].'/index/WxIndex/getChatInfo'; $we_chat = new WxController(); //实例化类 $we_chat->accredit($url,$buttonType); //调用方法 } /** * 获取微信用户信息 */ public function getChatInfo(){ $we_chat = new WxController();//实例化微信类 $code = $_GET['code']; //获取跳转后的code $state = $_GET['state']; //获取state $access_token = $we_chat->getAccessToken($code); //根据code获取token $this->gogogo($state,$access_token["openid"]); } //用于跳转到各个方法,传入OpenId和要跳转的方法 public function gogogo($state,$openid) { Student::login($openid); return 'success'; //跳转内容请根据实际状况本身编写 } }
<?php namespace app\index\controller; use think\Controller; class WxController extends Controller{ protected $appid='xxxxxxx'; //你的微信公众号appid protected $appsecret = 'xxxxxxxx'; //你的微信公众号secret //拼接URL public function accredit($redirect_url,$state){ $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->appid}&redirect_uri={$redirect_url}&response_type=code&scope=snsapi_userinfo&state={$state}#wechat_redirect"; $this->redirect($url); } /** * @param $code * @return bool|string */ public function getAccessToken($code){ $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$this->appid}&secret={$this->appsecret}&code={$code}&grant_type=authorization_code"; $res = file_get_contents($url); //获取文件内容或获取网络请求的内容 $access_token = json_decode($res,true); return $access_token; } /** * 获取用户信息 * @param unknown $openid * @param unknown $access_token * @return unknown */ public function getWeChatUserInfo($access_token,$openid){ $url = "https://api.weixin.qq.com/sns/userinfo?access_token={$access_token}&openid={$openid}&lang=zh_CN"; $output = file_get_contents($url); $weChatUserInfo = json_decode($output,true); return $weChatUserInfo; } }
整个过程的核心,是那张时序图