搜尋
首頁頭條網站接入qq,微信,微博第三方登陸詳解

網站接入qq,微信,微博第三方登陸詳解

Jan 16, 2018 pm 04:51 PM
微信登陸第三方

三方登陸的整體想法是取得第三方中的openid,然後與使用者關聯(存到資料庫),進行登陸。 本文主要和大家分享網站接入qq,微信,微博第三方登陸詳解,希望能幫助大家。

現在需求是:兩個(或多個)一級域名,如maxiye.cnyexima.com,同時每個域名下方有多個二級網域分佈,如:app.maxiye.cn,new.maxiye.cn,old.maxiye.cn,app.yexima.com,new.yexima.com,old.yexima.com.. .等,但是這些網域下使用了同一份代碼(對,就是馬甲),共享資料庫和session。同時旗下每個網域都包含pc,ios,Android端,如何全部接取第三方登陸?

qq,微信,微博存取要點:
1.申請入口:QQ是QQ互聯,微信是微信開放平台,微博是微博開放平台;
2.回呼域設定:QQ可以設定一級網域且可以有多個,必須http://開頭,;結束,如http://maxiye.cn;http://yexima.com;;微信只能設定到二級網域且只能一個,格式為:app.maxiye.cn
微博也可以設定一級網域且是一個:maxiye.cn;
3.unionid取得:多個app(同一開發者帳號下)共享資料庫,故需要使用unionid確認身分。 QQ取得uuid需要額外申請權限,具體參考相同開發者帳號下的不同appid應用如何打通;微信已有unionid取得介面;微博則uid即unionid;

坑:
1.QQ介面回傳的結果好多是jsonp格式,需要手動剝離callback();
2.微博取得取得access_token竟然必須使用 post,驚了;
3.微信不支援回呼地址填寫一級域名,所以需要使用統一域名(代理)作為回調地址,然後內部再重定向到發申請的網域名稱;

下邊是一個寫好的工具類別:

<?php /* PHP SDK 第三方登录授权验证
 * @version 1.0.0
 * @author zyl
 * @copyright
 */

namespace app\helpers;

use yii\helpers\Url;
use Yii;

class OauthLogin
{
    public $server = &#39;&#39;;//接入第三方的域名
    public $proxy = &#39;app.maxiye.cn&#39;;//微信登录代理中转站点
    private $type = &#39;&#39;;//第三方类型:qq,weixin,weibo
    private $app_id = &#39;&#39;;//分配给网站的appid。
    private $app_secret = &#39;&#39;;//分配给网站的appkey。
    private $state = &#39;&#39;;//client端的状态值。用于第三方应用防止CSRF攻击,成功授权后回调时会原样带回。请务必严格按照流程检查用户与state参数状态的绑定。
    private $code = &#39;&#39;;//用户成功登录并授权,则会跳转到指定的回调地址,并在URL中带上Authorization Code。
    private $access_token;
    private $config = [//配置多个网站的appid&appkey
        &#39;maxiye.cn&#39; => [
            'qq' => [
                'app_id' => '100000000',
                'app_secret' => 'f9038c3d07c*******7884edf3e31708',
            ],
            'weixin' => [
                'app_id' => 'wxee7c90a7744c2002',
                'app_secret' => '13e649627894*******7a85a0e2f50e7',
            ],
            'weibo' => [
                'app_id' => '1200000000',
                'app_secret' => 'e074de8*******d3818d0df9ca28c459',
            ],
        ],
        'yexima.com' => [
            'qq' => [
                'app_id' => '101111244',
                'app_secret' => '6ca59c6a1b1*******77e636a10ac334',
            ],
            'weixin' => [
                'app_id' => 'wx0b822222ea9ee323',
                'app_secret' => '7f9cbd*******f37ce7b4c267bdde029',
            ],
            'weibo' => [
                'app_id' => '911111998',
                'app_secret' => '5b21c452f88e2982*******1722d8fcd',
            ],
        ],
    ];

    function __construct($params = [])
    {
        $this->type = $params['type'];
        $this->server = $_SERVER['SERVER_NAME'];
        foreach ($this->config as $k => $v) {
            if (stristr($this->server, $k) && isset($v[$this->type])) {
                $this->app_id = $v[$this->type]['app_id'];
                $this->app_secret = $v[$this->type]['app_secret'];
            }
        }
        if (isset($params['code'])) {
            $this->code = $params['code'];
        }
    }

    /**
     * 获取用户授权验证的链接
     * @return string
     */
    public function getOauthUrl()
    {
        $this->state = md5(uniqid(rand(), TRUE));
        Yii::$app->session->setFlash('oauth_state', $this->state);
        $redirect_uri = urlencode(Url::to(['login-by-openid', 'type' => $this->type, true));
        if ($this->type == 'weixin' && $this->server != $this->proxy) {//微信回调多域名代理处理
            $redirect_uri = str_replace($this->server, $this->proxy, $redirect_uri) . '%26redirect%3D' . $this->server;
        }
        $url = '';
        switch ($this->type) {
            case 'qq'://qq回调域填写一级域名并以“;”结束:http://maxiye.cn;http://yexima.com;
                $url = "https://graph.qq.com/oauth/show?which=Login&display=pc&response_type=code&client_id={$this->app_id}&state={$this->state}&display=web&redirect_uri={$redirect_uri}";
                break;
            case 'weixin'://app.maxiye.cn不支持只填写二级域名
                $url = "https://open.weixin.qq.com/connect/qrconnect?response_type=code&appid={$this->app_id}&state={$this->state}&scope=snsapi_login&redirect_uri={$redirect_uri}#wechat_redirect";
                break;
            case 'weibo'://微博设置安全域名:maxiye.cn
                $url = "https://api.weibo.com/oauth2/authorize?response_type=code&client_id={$this->app_id}&state={$this->state}&display=web&redirect_uri={$redirect_uri}";
                break;

            default:

                break;
        }
        return $url;
    }

    /**
     * 获取针对开发者账号的惟一uuid
     * @return string unionid或uid
     */
    public function getUuid()
    {
        $openid = '';
        if ($this->type == 'qq') {
            $this->getAccessToken();
        } else {
            $openid = $this->getOpenid();
        }
        $access_token = $this->access_token;
        $uuid = '';
        if ($access_token) {
            switch ($this->type) {
                case 'qq':
                    $url = "https://graph.qq.com/oauth2.0/me?access_token={$access_token}&unionid=1";
                    // 返回示例...
                    /*callback({
                           "client_id":"YOUR_APPID",
                           "openid":"YOUR_OPENID",
                           "unionid":"YOUR_UNIONID"
                    });*/
                    $result = $this->get_contents($url);
                    if (strpos($result, "callback") !== false) {
                        $lpos = strpos($result, "(");
                        $rpos = strrpos($result, ")");
                        $result = json_decode(substr($result, $lpos + 1, $rpos - $lpos - 1), true);
                        $uuid = isset($result['unionid']) ? $result['unionid'] : '';
                    }
                    return $uuid;
                    // return $openid;
                    break;
                case 'weixin':
                    $url = "https://api.weixin.qq.com/sns/userinfo?access_token={$access_token}&openid={$openid}";
                    // 返回示例
                    /*{
                        "openid":"OPENID",
                        "nickname":"NICKNAME",
                        "sex":1,
                        "province":"PROVINCE",
                        "city":"CITY",
                        "country":"COUNTRY",
                        "headimgurl": "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
                        "privilege":[
                            "PRIVILEGE1",
                            "PRIVILEGE2"
                        ],
                        "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"

                    }*/
                    $result = json_decode($this->get_contents($url), true);
                    return isset($result['unionid']) ? $result['unionid'] : '';
                    break;
                case 'weibo':
                    return $openid;
                    break;

                default:

                    break;
            }
        }
        return $uuid;
    }

    /**
     * 获取access_token
     * @param boolean $true false表示获取原始结果,true获取真正的access_token
     * @return string json包|string
     */
    public function getAccessToken($true = true)
    {
        //验证state
        if (Yii::$app->request->get('state', '') != Yii::$app->session->getFlash('oauth_state')) {
            return '';
        }
        $redirect_uri = urlencode(Url::to(['login-by-openid', 'type' => $this->type], true));
        $url = '';
        switch ($this->type) {
            case 'qq':
                $url = "https://graph.qq.com/oauth2.0/token?grant_type=authorization_code&code={$this->code}&client_id={$this->app_id}&client_secret={$this->app_secret}&redirect_uri={$redirect_uri}";
                //返回示例...
                //access_token=15C0CE01C0311240F9091A7DB6828E62&expires_in=7776000&refresh_token=7BFCE2E5B773D4F5531561A10E1C2B2D
                break;
            case 'weixin':
                $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$this->app_id}&secret={$this->app_secret}&code={$this->code}&grant_type=authorization_code";
                //返回示例
                /*{
                "access_token":"ACCESS_TOKEN",
                "expires_in":7200,
                "refresh_token":"REFRESH_TOKEN",
                "openid":"OPENID",
                "scope":"SCOPE"
                }*/
                break;
            case 'weibo':
                $url = "https://api.weibo.com/oauth2/access_token?client_id={$this->app_id}&client_secret={$this->app_secret}&grant_type=authorization_code&redirect_uri={$redirect_uri}&code={$this->code}";//新浪微博
                $post_data = [];
                return $this->post($url, $post_data);//撒币制杖
                //返回示例
                /*{
                    "access_token": "SlAV32hkKG",
                    "remind_in": 3600,
                    "expires_in": 3600,
                    "uid":"12341234"
                }*/
                break;

            default:

                break;
        }
        if ($true) {
            $res_access_token = $this->get_contents($url);
            if ($this->type == 'qq' && strpos($res_access_token, "access_token") !== false) {
                $token_result = ['access_token' => explode('=', explode('&', $res_access_token)[0])[1]];
            } else {
                $token_result = json_decode($res_access_token ?: '{}', true);
            }
            $access_token = !empty($token_result['access_token']) ? $token_result['access_token'] : '';
            $this->access_token = $access_token;
            return $access_token;
        } else {
            return $this->get_contents($url);
        }
    }

    /**
     * post
     * post方式请求资源
     * @param string $url 基于的baseUrl
     * @param array $keysArr 请求的参数列表
     * @param int $flag 标志位
     * @return string           返回的资源内容
     */
    public function post($url, $keysArr, $flag = 0)
    {

        $ch = curl_init();
        if (!$flag) curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $keysArr);
        curl_setopt($ch, CURLOPT_URL, $url);
        $ret = curl_exec($ch);

        curl_close($ch);
        return $ret;
    }

    /**
     * get_contents
     * 服务器通过get请求获得内容
     * @param string $url 请求的url,拼接后的
     * @return string           请求返回的内容
     */
    public function get_contents($url)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($ch, CURLOPT_URL, $url);
        $response = curl_exec($ch);
        curl_close($ch);

        //-------请求为空
        if (empty($response)) {
            return '{}';
        }

        return $response;
    }

    /**
     * 获取openid
     * @return string openid
     */
    public function getOpenid()
    {
        $res_access_token = $this->getAccessToken(false);
        if ($this->type == 'qq' && strpos($res_access_token, "access_token") !== false) {
            $access_token = ['access_token' => explode('=', explode('&', $res_access_token)[0])[1]];
        } else {
            $access_token = json_decode($res_access_token ?: '{}', true);
        }
        $openid = '';
        if (isset($access_token['access_token'])) {
            $this->access_token = $access_token['access_token'];
            switch ($this->type) {
                case 'qq':
                    $url = "https://graph.qq.com/oauth2.0/me?access_token={$access_token['access_token']}";
                    // 返回示例...
                    // callback( {"client_id":"101406183","openid":"6C611CBE0C72F765572AE2472C9B59A4"} );
                    $result = $this->get_contents($url);
                    if (strpos($result, "callback") !== false) {
                        $lpos = strpos($result, "(");
                        $rpos = strrpos($result, ")");
                        $result = json_decode(substr($result, $lpos + 1, $rpos - $lpos - 1), true);
                        $openid = isset($result['openid']) ? $result['openid'] : '';
                    }
                    break;
                case 'weixin':
                    return $access_token['openid'];
                    break;
                case 'weibo':
                    return $access_token['uid'];
                    /*$url = "https://api.weibo.com/oauth2/get_token_info?access_token={$access_token['access_token']}";
                    //返回示例
                    {
                        "uid": 1073880650,
                        "appkey": 1352222456,
                        "scope": null,
                        "create_at": 1352267591,
                        "expire_in": 157679471
                    }
                    $result = $this->get_contents($url);
                    $openid = isset($result['uid'])?$result['uid']:'';*/
                    break;

                default:

                    break;
            }
        }
        return $openid;
    }
}

使用方法如下:

//第三方登录界面处理
public function actionLoginByOpenid(){
    Yii::$app->response->format= Response::FORMAT_HTML;
    $params = Yii::$app->request->get();
    $oauth = new OauthLogin($params);
    if(empty($params['code'])){
        $url = $oauth->getOauthUrl();
        return $this->redirect($url);
    }else{
        //微信代理跳转处理
        if(isset($params['redirect']) && $params['redirect'] != $oauth->server){
            $proxy = $oauth->proxy;
            $server = $params['redirect'];
            return $this->redirect(str_replace($proxy, $server, Url::current(['redirect'=>null], 'http')));
        }
        $openid = $oauth->getUuid();
        if (!$openid) {
            //失败处理TODO
        } else {
            //成功处理TODO
        }
        
    }
}

具體流程(qq為例)如下:
1.用戶點擊QQ登陸圖標,訪問鏈接http://app.maxiye.cn/site/login-by-openid?type=qq;
2.伺服器處理獲取QQ的授權鏈接,重定向;
3.QQ在回呼位址中加入code參數(Authorization Code),回呼http://app.maxiye.cn/site/login-by-openid?type=qq&state=4a78***&code =1CA8DF***;
4.伺服器根據code參數,驗證state,取得access_token,然後取得unionid(uid),處理結果。

相關推薦:

網站新增第三方登陸PHP版

#php QQ第三方登陸SDK程式碼_PHP教學

新浪微博第三方登陸


#
陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具