微信公衆號開發(十二)OAuth2.0網頁受權

OAuth容許用戶提供一個令牌,而不是用戶名和密碼來訪問它們存放在特定服務器上的數據,每個令牌受權一個特定的網站在特定時段內訪問特定的資源。javascript

受權過程以下:php

一、引導用戶進入受權頁面贊成受權,獲取code css

二、經過code換取網頁受權access_token(與基礎支持中的access_token不一樣) html

三、若是須要,開發者能夠刷新網頁受權access_token,避免過時 java

四、經過網頁受權access_token和openid獲取用戶基本信息(支持UnionID機制) json

一、配置受權回調頁面域名
在測試號權限列表中找到OAuth2.0網頁受權,而後點擊修改,填寫本身的域名,注意不能帶http://,若是經過,會提示「經過安全檢測」的字樣。


二、用戶受權獲取code
接口:https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

scope的兩種區別:
snsapi_base:不彈出受權頁面,直接跳轉,只能獲取用戶openid
snsapi_userinfo:彈出受權頁面,可經過openid拿到暱稱、性別、所在地。而且,即便在未關注的狀況下,只要用戶受權,也能獲取其信息。

redirect_uri:受權後重定向的回調連接地址,請使用urlencode對連接進行處理。

尤爲注意:因爲受權操做安全等級較高,因此在發起受權請求時,微信會對受權連接作正則強匹配校驗,若是連接的參數順序不對,受權頁面將沒法正常訪問。

在根目錄下新建一個文件夾oauth,並在該文件夾下新建oauth2.php。該文件就是,接口中redirect_uri域名回調頁面。

具體獲取code的方法步驟是:提供用戶請求受權頁面的URL,也就是以上的接口,用戶點擊受權頁面URL向服務器發起請求,服務器詢問用戶是否贊成(scope爲snsapi_base時無此步驟),用戶贊成(scope爲snsapi_base時無此步驟),服務器將code經過回調傳給公衆帳號開發者。

這裏咱們只是簡單的輸出如下code。
oauth2.php
<?php
if (isset($_GET['code'])){
    echo "code:".$_GET['code']."<br>";
    echo "state:".$_GET["state"];
}else {
    echo "no code";
}
而後在index.php中向用戶發送受權URL,以下所示。
index.php
<?php
@header('Content-type: text/html;charset=UTF-8');
//設置時區
date_default_timezone_set("Asia/Shanghai");
//定義TOKEN常量,這裏的"weixin"就是在公衆號裏配置的TOKEN

require_once("Utils.php");
//打印請求的URL查詢字符串到query.xml
Utils::traceHttp();

$wechatObj = new wechatCallBackapiTest();
$wechatObj->responseMsg();

class wechatCallBackapiTest
{
    public function responseMsg()
    {
        //獲取post過來的數據,它一個XML格式的數據
        $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
        //將數據打印到log.xml
        Utils::logger($postStr);
        if (!empty($postStr)) {
            //將XML數據解析爲一個對象
            $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
            $RX_TYPE = trim($postObj->MsgType);
            //消息類型分離
            switch($RX_TYPE)
            {
                case "text":
                    $result = $this->receiveText($postObj);
                    break;
                default:
                    $result = "";
                    break;
            }
            Utils::logger($result, '公衆號');
            echo $result;
        }else {
            echo "";
            exit;
        }
    }

    private function receiveText($object)
    {
        $appid = "wx07fff9c79a410b69";
        $redirect_uri = urlencode("http://weiweiyi.duapp.com/oauth/oauth2.php");

        $keyword = trim($object->Content);
        if(strstr($keyword, "base")){
            $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=$appid&redirect_uri=".
                "$redirect_uri&response_type=code&scope=snsapi_base&state=123#wechat_redirect";
            $content = "用戶受權snsapi_base實現:<a href='$url'>單擊這裏體驗OAuth受權</a>";
        }else if (strstr($keyword, "userinfo")){
            $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=$appid&redirect_uri=".
                "$redirect_uri&response_type=code&scope=snsapi_userinfo&state=123#wechat_redirect";
            $content = "用戶受權snsapi_userInfo實現:<a href='$url'>單擊這裏體驗OAuth受權</a>";
        }else{
            $content = "";
        }
        $result = $this->transmitText($object, $content);
        return $result;
    }
    /**
     * 回覆文本消息
     */
    private function transmitText($object, $content)
    {
        $xmlTpl = "<xml>
    <ToUserName><![CDATA[%s]]></ToUserName>
    <FromUserName><![CDATA[%s]]></FromUserName>
    <CreateTime><![CDATA[%s]]></CreateTime>
    <MsgType><![CDATA[text]]></MsgType>
    <Content><![CDATA[%s]]></Content>
</xml>";
        $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, time(), $content);
        return $result;
    }
}


向公衆號分別發送「base」和"baseInfo",則返回如圖所示:


點擊base連接後,直接重定向到oauth2.php頁面,能夠看到返回的參數中不只有code,還返回了url中填寫的state字段。


點擊userinfo,則先返回以下頁面,須要用戶點擊「確認」後才能重定向到oauth2.php。

三、使用code換取access_token
若是網頁受權做用域是snsapi_base,則本步驟獲取到網頁受權access_token的同時,也獲取到了openid,snsapi_base式的網頁受權流程到此爲止。注意這裏的access_token和基礎接口中的access_token不一樣。
接口:https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code。
get_token.php
<?php
@header('Content-type: text/plain;charset=UTF-8');
require_once("../Utils.php");

$appid = "wx07fff9c79a410b69";
$appsecret = "092c0c0c5bd62f66b76ad241612915fb";
$code = "0016Q5kn0zdDFp1E3rjn0VUjkn06Q5km";

$url = "https://api.weixin.qq.com/sns/oauth2/access_token?"
    ."appid=$appid&secret=$appsecret&code=$code&grant_type=authorization_code";
$result = Utils::https_request($url);
echo $result;
若是是base,受權流程到此結束,返回:
{
    "access_token": "b3e1GZdT1E-sjKzeKRCr9XUE6IQglkBBxrFXdsmZ8DVW4O5t16EXbIxCoob6pGXwA5Z9JubOZnIytGcM5xC20g",
    "expires_in": 7200,
    "refresh_token": "yJkiFmmRVq5Kst6PiZpwGPvJh0bcegccx-KFIZEIwYKRmdiLC5dG8-iMRkjl1Stf8cSrHjDauzZtEGNHlnGckA",
    "openid": "o4WmZ0h-4huBUVQUczx2ezaxIL9c",
    "scope": "snsapi_base"
}
若是是userinfo,返回:
{
    "access_token": "iUIP_RnPmjVICZtmq6fFRcslRD1yJax3IkeT_fXKFlDv5W_9y5JS4Z4QgC1W33Qi2BbQ5pWLWt-6LYT7u1Egvg",
    "expires_in": 7200,
    "refresh_token": "rKwY7NF0BqfSpLVwmVO-htyvlrFWQVRmCdimoaLG2JiHz8wEJZ2H7fcQ5wtJylixBt-dCENgasbaSs8_7M-Kmw",
    "openid": "o4WmZ0h-4huBUVQUczx2ezaxIL9c",
    "scope": "snsapi_userinfo"
}
四、刷新access_token(可選)
因爲access_token擁有較短的有效期,當access_token超時後,可使用refresh_token進行刷新,refresh_token有效期爲30天,當refresh_token失效以後,須要用戶從新受權。
接口:https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN。
get_refresh_token.php
<?php
@header('Content-type: text/plain;charset=UTF-8');
require_once("../Utils.php");

$appid = "wx07fff9c79a410b69";
$appsecret = "092c0c0c5bd62f66b76ad241612915fb";
$refresh_token = "rKwY7NF0BqfSpLVwmVO-htyvlrFWQVRmCdimoaLG2JiHz8wEJZ2H7fcQ5wtJylixBt-dCENgasbaSs8_7M-Kmw";

$url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?"
    ."appid=$appid&grant_type=refresh_token&refresh_token=$refresh_token";
$result = Utils::https_request($url);
echo $result;
返回:
{
    "openid": "o4WmZ0h-4huBUVQUczx2ezaxIL9c",
    "access_token": "iUIP_RnPmjVICZtmq6fFRcslRD1yJax3IkeT_fXKFlDv5W_9y5JS4Z4QgC1W33Qi2BbQ5pWLWt-6LYT7u1Egvg",
    "expires_in": 7200,
    "refresh_token": "rKwY7NF0BqfSpLVwmVO-htyvlrFWQVRmCdimoaLG2JiHz8wEJZ2H7fcQ5wtJylixBt-dCENgasbaSs8_7M-Kmw",
    "scope": "snsapi_base,snsapi_userinfo,"
}
五、使用access_token獲取用戶信息
接口:https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN。
get_userinfo.php
<?php
@header('Content-type: text/plain;charset=UTF-8');
require_once("../Utils.php");

$access_token = "iUIP_RnPmjVICZtmq6fFRcslRD1yJax3IkeT_fXKFlDv5W_9y5JS4Z4QgC1W33Qi2BbQ5pWLWt-6LYT7u1Egvg";
$openid = "o4WmZ0h-4huBUVQUczx2ezaxIL9c";

$url = "https://api.weixin.qq.com/sns/userinfo?"
    ."access_token=$access_token&openid=$openid&lang=zh_CN ";
$result = Utils::https_request($url);
echo $result;
返回:
{
    "openid": "o4WmZ0h-4huBUVQUczx2ezaxIL9c",
    "nickname": "Promise",
    "sex": 1,
    "language": "zh_CN",
    "city": "",
    "province": "",
    "country": "",
    "headimgurl": "http://wx.qlogo.cn/mmopen/vi_32/um6ptBDhpau47ctyJHMakZgyHJsYHzjMfouyWqP6DNxNEPLf2uk6V6TBNnsbanrUcABJiaEa74W8VB7JRk9k0kg/0",
    "privilege": []
}
受權過程到此結束。

下面來個完整版的,新建一個oauth_complete.php文件。
將index.php中重定向url改成:$redirect_uri = urlencode("http://weiweiyi.duapp.com/oauth/oauth_complete.php");
oauth.complete.php
<?php

@header('Content-type: text/plain;charset=UTF-8');
require_once("../Utils.php");
$code = $_GET["code"];
$userinfo = getUserInfo($code);
echo $userinfo;

function getUserInfo($code)
{
    $appid = "wx07fff9c79a410b69";
    $appsecret = "092c0c0c5bd62f66b76ad241612915fb";

    //根據code得到access_token
    $access_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?"
        ."appid=$appid&secret=$appsecret&code=$code&grant_type=authorization_code";
    $access_token_json = Utils::https_request($access_token_url);
    $access_token_array = json_decode($access_token_json, true);
    //access_token
    $access_token = $access_token_array["access_token"];
    //openid
    $openid = $access_token_array["openid"];

    //根據access_token和openid得到用戶信息
    $userinfo_url = "https://api.weixin.qq.com/sns/userinfo?"
        ."access_token=$access_token&openid=$openid&lang=zh_CN ";
    $userinfo_json = Utils::https_request($userinfo_url);
    return $userinfo_json;
}
注意:獲取的code只能使用一次,超過一次會報40163的錯誤,這時會獲取不到access_token。
若是不是官方微信網頁,會彈出如下界面:

其實在這以前已經發送了一次請求,點擊「繼續訪問」實際上至關於第二次訪問該頁面,因此code也是第二次使用,會報錯。
相關文章
相關標籤/搜索