圖解微信」網頁受權「自動登陸(附ThinkPHP5.1代碼)

零、前言

在初學微信開發的時候因爲沒有經驗,再加上微信的官方文檔不夠清晰,致使看完文檔以後只剩下」抓瞎「,根本不知道微信開發是怎樣一個流程,也不知道如何開始,因而不得不去查閱第三方博客。
後來終於完成了微信公衆號和服務器的對接,實現了網頁受權,而且,用戶能夠直接點擊公衆號下方的按鈕,自動獲取OpenID登陸,不用再進行傳統的手動登陸了。網頁受權自動登陸,也就是本文須要實現的功能。php

1、原理

1,什麼是網頁受權?

網頁受權,就是用戶向公衆號受權,讓開發者經過此用戶的惟一識別碼(OpenID)得到此用戶的身份。通俗的講,就是用戶給開發者提交一個「身份證」,讓開發者知道當前正在訪問的用戶是誰微信官方文檔——網頁受權html

2,使用網頁受權的優點

一般狀況下,用戶是直接訪問開發者的服務器,獲取服務器返回的數據。因爲http協議是匿名的,在這種狀況下,服務器不知道當前訪問的用戶是誰,識別用戶身份的惟一辦法就是經過CookieSession,然而,因爲Cookie具備時效性,用戶仍是在一些狀況下仍是要手動登陸。
直接鏈接開發者服務器的時序圖:
2016-07-06_577c9b3a28e87.png
(圖片出自夢雲智軟件開發團隊ThinkPHP5.1入門實例教程web

而微信網頁受權的優點在於,能夠給每個微信帳號分配一個惟一的識別碼(也就是OpenID),經過這個識別碼,微信服務器就能夠知道當前登陸的用戶是誰,而後把此用戶的信息告訴開發者的服務器,這樣開發者就獲取了用戶身份,而且能夠實現把用戶在網站的帳號和用戶的微信號綁定起來,這樣,之後用戶經過微信登陸網站時就再也不用手動登陸了。
經過鏈接微信服務器獲取用戶信息的時序圖:
圖片.pngthinkphp

3,什麼狀況下可使用網頁受權?

微信的公衆號有兩種——訂閱號和服務號,訂閱號一般適用於我的(自媒體、學校的小型組織),服務號適用於企業。訂閱號沒有網頁受權的權限,服務號只有在認證以後可使用網頁受權。微信接口權限說明
圖片.png
圖片.pngjson

因此,只有訂閱號的小夥伴能夠洗洗睡了...但是做爲開發者,若是出於學習的目的想嘗試網頁受權的話,能夠去申請微信測試號,測試號具備全部的微信接口權限。申請接口測試號api

2、操做

本文假設用戶已經完成了公衆號和服務器的綁定,設置好了服務器地址。
圖片.png服務器

1,設置公衆號的按鈕

在公衆號剛剛建立的時候,主頁面是這樣的,只有聊天框:
圖片.png
而咱們但願是這樣:
圖片.png微信

那麼,怎麼定義這些按鈕呢?微信爲咱們提供了一個很好的接口測試工具,咱們能夠利用這個工具來定義按鈕。
首先選擇基礎支持,獲取AccessToken(這個是公衆號的全局AccessToken而不是網頁受權的AccessToken)
圖片.png
填入正確的APPID和Secret以後,下面返回了AccessToken有效期7200秒。
圖片.png
複製這串字符,而後把接口切換到自定義菜單查詢接口,把剛剛獲取的token粘貼進去。
圖片.png
若是這個公衆號以前設置過按鈕,就會出現因此按鈕的代碼:
圖片.png網絡

{
    "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"{}刪掉,否則會報錯。
圖片.png
點擊建立以後,刷新公衆號,按鈕已經出現了。
圖片.png微信開發

3、代碼分析

咱們仍是要拿出這張時序圖
圖片.png

1,第一階段

實際上已經在剛纔完成了,就是在公衆號按鈕中設置連接,讓用戶經過按鈕訪問ThnkPHP的某個方法。

2,第二階段

//你的微信公衆號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

3,第三階段

//回調到這個方法
    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進行登陸操做,實現自動登陸,登陸以後把用戶請求的網頁返回給用戶了。

4、附上完整代碼

1,appindexcontrollerWxindexController.php

<?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';
        //跳轉內容請根據實際狀況本身編寫
    }
}

2,appindexcontrollerWxController.php

<?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;
    }
}

五,總結

整個過程的核心,是那張時序圖

相關文章
相關標籤/搜索