登录  /  注册
首页 > 头条 > 正文

网站接入qq,微信,微博第三方登陆详解

小云云
发布: 2018-01-16 16:51:42
原创
5253人浏览过

三方登陆的整体思路是获取第三方中的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' =&gt; [
                'app_id' =&gt; '100000000',
                'app_secret' =&gt; 'f9038c3d07c*******7884edf3e31708',
            ],
            'weixin' =&gt; [
                'app_id' =&gt; 'wxee7c90a7744c2002',
                'app_secret' =&gt; '13e649627894*******7a85a0e2f50e7',
            ],
            'weibo' =&gt; [
                'app_id' =&gt; '1200000000',
                'app_secret' =&gt; 'e074de8*******d3818d0df9ca28c459',
            ],
        ],
        'yexima.com' =&gt; [
            'qq' =&gt; [
                'app_id' =&gt; '101111244',
                'app_secret' =&gt; '6ca59c6a1b1*******77e636a10ac334',
            ],
            'weixin' =&gt; [
                'app_id' =&gt; 'wx0b822222ea9ee323',
                'app_secret' =&gt; '7f9cbd*******f37ce7b4c267bdde029',
            ],
            'weibo' =&gt; [
                'app_id' =&gt; '911111998',
                'app_secret' =&gt; '5b21c452f88e2982*******1722d8fcd',
            ],
        ],
    ];

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

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

            default:

                break;
        }
        return $url;
    }

    /**
     * 获取针对开发者账号的惟一uuid
     * @return string unionid或uid
     */
    public function getUuid()
    {
        $openid = '';
        if ($this-&gt;type == 'qq') {
            $this-&gt;getAccessToken();
        } else {
            $openid = $this-&gt;getOpenid();
        }
        $access_token = $this-&gt;access_token;
        $uuid = '';
        if ($access_token) {
            switch ($this-&gt;type) {
                case 'qq':
                    $url = "https://graph.qq.com/oauth2.0/me?access_token={$access_token}&amp;unionid=1";
                    // 返回示例...
                    /*callback({
                           "client_id":"YOUR_APPID",
                           "openid":"YOUR_OPENID",
                           "unionid":"YOUR_UNIONID"
                    });*/
                    $result = $this-&gt;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}&amp;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-&gt;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-&gt;request-&gt;get('state', '') != Yii::$app-&gt;session-&gt;getFlash('oauth_state')) {
            return '';
        }
        $redirect_uri = urlencode(Url::to(['login-by-openid', 'type' =&gt; $this-&gt;type], true));
        $url = '';
        switch ($this-&gt;type) {
            case 'qq':
                $url = "https://graph.qq.com/oauth2.0/token?grant_type=authorization_code&amp;code={$this-&gt;code}&amp;client_id={$this-&gt;app_id}&amp;client_secret={$this-&gt;app_secret}&amp;redirect_uri={$redirect_uri}";
                //返回示例...
                //access_token=15C0CE01C0311240F9091A7DB6828E62&amp;expires_in=7776000&amp;refresh_token=7BFCE2E5B773D4F5531561A10E1C2B2D
                break;
            case 'weixin':
                $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$this-&gt;app_id}&amp;secret={$this-&gt;app_secret}&amp;code={$this-&gt;code}&amp;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-&gt;app_id}&amp;client_secret={$this-&gt;app_secret}&amp;grant_type=authorization_code&amp;redirect_uri={$redirect_uri}&amp;code={$this-&gt;code}";//新浪微博
                $post_data = [];
                return $this-&gt;post($url, $post_data);//撒币制杖
                //返回示例
                /*{
                    "access_token": "SlAV32hkKG",
                    "remind_in": 3600,
                    "expires_in": 3600,
                    "uid":"12341234"
                }*/
                break;

            default:

                break;
        }
        if ($true) {
            $res_access_token = $this-&gt;get_contents($url);
            if ($this-&gt;type == 'qq' &amp;&amp; strpos($res_access_token, "access_token") !== false) {
                $token_result = ['access_token' =&gt; explode('=', explode('&amp;', $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-&gt;access_token = $access_token;
            return $access_token;
        } else {
            return $this-&gt;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-&gt;getAccessToken(false);
        if ($this-&gt;type == 'qq' &amp;&amp; strpos($res_access_token, "access_token") !== false) {
            $access_token = ['access_token' =&gt; explode('=', explode('&amp;', $res_access_token)[0])[1]];
        } else {
            $access_token = json_decode($res_access_token ?: '{}', true);
        }
        $openid = '';
        if (isset($access_token['access_token'])) {
            $this-&gt;access_token = $access_token['access_token'];
            switch ($this-&gt;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-&gt;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-&gt;get_contents($url);
                    $openid = isset($result['uid'])?$result['uid']:'';*/
                    break;

                default:

                    break;
            }
        }
        return $openid;
    }
}
登录后复制

使用方法如下:

//第三方登录界面处理
public function actionLoginByOpenid(){
    Yii::$app-&gt;response-&gt;format= Response::FORMAT_HTML;
    $params = Yii::$app-&gt;request-&gt;get();
    $oauth = new OauthLogin($params);
    if(empty($params['code'])){
        $url = $oauth-&gt;getOauthUrl();
        return $this-&gt;redirect($url);
    }else{
        //微信代理跳转处理
        if(isset($params['redirect']) &amp;&amp; $params['redirect'] != $oauth-&gt;server){
            $proxy = $oauth-&gt;proxy;
            $server = $params['redirect'];
            return $this-&gt;redirect(str_replace($proxy, $server, Url::current(['redirect'=&gt;null], 'http')));
        }
        $openid = $oauth-&gt;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&amp;state=4a78***&amp;code=1CA8DF***
4.服务器根据code参数,验证state,获取access_token,然后获取unionid(uid),处理结果。

相关推荐:

网站添加第三方登陆PHP版

php QQ第三方登陆SDK程序代码_PHP教程

新浪微博第三方登陆


智能AI问答
PHP中文网智能助手能迅速回答你的编程问题,提供实时的代码和解决方案,帮助你解决各种难题。不仅如此,它还能提供编程资源和学习指导,帮助你快速提升编程技能。无论你是初学者还是专业人士,AI智能助手都能成为你的可靠助手,助力你在编程领域取得更大的成就。
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
最新问题
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2024 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号