zoukankan      html  css  js  c++  java
  • PHP实现微信开放平台扫码登录源码(微信第三方登陆)

    PHP实现微信开放平台扫码登录源码(微信第三方登陆)

    第一步:请求CODE
    登录方倍工作室微信登录网站应用
    http://weixin.fangbei.org/login.php

    打开后,应用会生成state参数,跳转到以下链接:(登录前请注意已获取相应网页授权作用域(scope=snsapi_login))
    https://open.weixin.qq.com/connect/qrconnect?appid=wxed782be999f86e0e&redirect_uri=http%3A%2F%2Fweixin.fangbei.org%2Flogin.php&response_type=code&scope=snsapi_login&state=123#wechat_redirect

    若提示“该链接无法访问”,请检查参数是否填写错误,如redirect_uri的域名与审核时填写的授权域名不一致或scope不为snsapi_login。
    参数说明
    参数                                                     appid                                                     redirect_uri                                               response_type                                                                  scope
    是否必须                                                 是                                                              是                                                                 是                                                                                是
    说明                                               应用唯一标识                                        重定向地址,需要进行UrlEncode                          填code                                                                 应用授权作用域,拥有多个作用域用逗号(,)分隔,网页应用目前仅填写snsapi_login即可

    参数                                                       state
    是否必须                                                  否
    说明                          用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验




    返回说明
    此时,PC网站上显示如下二维码

    用户允许授权后,将会重定向到redirect_uri的网址上,并且带上code和state参数
    http://weixin.fangbei.org/login.php?code=0317a2c31ccd5eadf1a7a8fffd4a7dbf&state=123

    为了满足网站更定制化的需求,我们还提供了第二种获取code的方式,支持网站将微信登录二维码内嵌到自己页面中,用户使用微信扫码授权后通过js将code返回给网站。
    JS微信登录主要用途:网站希望用户在网站内就能完成登录,无需跳转到微信域下登录后再返回,提升微信登录的流畅性与成功率。 网站内嵌二维码微信登录JS实现办法:
    步骤1:在页面中先引入如下JS文件(支持https):
    <script src="http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>

    步骤2:在需要使用微信登录的地方实例以下JS对象:
    <script> var obj = new WxLogin({
    id: "login_container",
    appid: "wxed782be999f86e0e",
    scope: "snsapi_login",
    redirect_uri: encodeURIComponent("http://" + window.location.host + "/login.php"), state: Math.ceil(Math.random()*1000),
    style: "black",
    href: ""});
    </script>

    参数说明

    参数                       id                                                                                 appid                                                                                                           scope
    是否必须                是                                                                                    是                                                                                                                是
    说明             第三方页面显示二维码的容器id            应用唯一标识,在微信开放平台提交应用审核通过后获得                            应用授权作用域,拥有多个作用域用逗号(,)分隔,网页应用目前仅填写snsapi_login即可

    参数                 redirect_uri                                                                          state
    是否必须                是                                                                                    否
    说明           重定向地址,需要进行UrlEncode           用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验

    参数                   style                                                                                                                                                 href
    是否必须             否                                                                                                                                                      否
    说明       提供"black"、"white"可选,默认为黑色文字描述。详见文档底部FAQ                                自定义样式链接,第三方可根据实际需求覆盖默认样式。详见文档底部FAQ

    完整代码如下
    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="content-type" content="text/html;charset=utf-8">
    </head>
    <body>
    <span id="login_container"></span>
    <script src="http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>
    <script> var obj = new WxLogin({
    id: "login_container",
    appid: "wxed782be999f86e0e",
    scope: "snsapi_login",
    redirect_uri: encodeURIComponent("http://" + window.location.host + "/login.php"), state: Math.ceil(Math.random()*1000),
    style: "black",
    href: ""});
    </script>
    </body>
    </html>

    页面显示效果如下

    第二步:通过code获取access_token
    通过code获取access_token
    https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

    参数说明

    参数:                    appid
    是否必须:               是
    说明:       应用唯一标识,在微信开放平台提交应用审核通过后获得

    参数:                   secret
    是否必须:               是
    说明:        应用密钥AppSecret,在微信开放平台提交应用审核通过后获得

    参数:                    code
    是否必须:               是
    说明:       填写第一步获取的code参数

    参数:                 grant_type
    是否必须:              是
    说明:       填authorization_code

    返回说明
    正确的返回:
    { "access_token": "OezXcEiiBSKSxW0eoylIeFy2HFC4Bxv9JvC0Sgj4Px4_8TX1ci3jF_QP_6sWjvx2rCAUjXEP1_9edZdJLf3MIwii2N8cnTooDfx7nYpFRmOSZyq4gb2FNdWJr__KUqPtcfVUvg6XBTucZZ4zH6v8VQ",
    "expires_in": 7200,
    "refresh_token": "OezXcEiiBSKSxW0eoylIeFy2HFC4Bxv9JvC0Sgj4Px4_8TX1ci3jF_QP_6sWjvx2lW60INlf6AK1q21rW7mJyc5yG3GZ9p1psANOKTi2EZUQXA6CnwSXxDQlJ3421tEOvCWIrJhkA8oTqjsLKYG-yg",
    "openid": "oJekJs2faTQ47FGjDOEIyOPMN97s",
    "scope": "snsapi_login",
    "unionid": "o4wcnw02YjFUYglZxV0LwcBkVF6Y"}

    参数说明

    参数:access_token
    说明:接口调用凭证

    参数:expires_in
    说明:access_token接口调用凭证超时时间,单位(秒)

    参数:refresh_token
    说明:用户刷新access_token

    参数:openid
    说明:授权用户唯一标识

    参数:scope
    说明:用户授权的作用域,使用逗号(,)分隔

    参数:unionid
    说明:当且仅当该网站应用已获得该用户的userinfo授权时,才会出现该字段。

    错误返回样例:
    {"errcode":40029,"errmsg":"invalid code"}

    刷新access_token有效期
    access_token是调用授权关系接口的调用凭证,由于access_token有效期(目前为2个小时)较短,当access_token超时后,可以使用refresh_token进行刷新,access_token刷新结果有两种:

    1. 若access_token已超时,那么进行refresh_token会获取一个新的access_token,新的超时时间;
    2. 若access_token未超时,那么进行refresh_token不会改变access_token,但超时时间会刷新,相当于续期access_token。

    refresh_token拥有较长的有效期(30天),当refresh_token失效的后,需要用户重新授权。
    请求方法
    获取第一步的code后,请求以下链接进行refresh_token:
    https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN

    参数说明

    参数:appid
    是否必须:是
    说明:应用唯一标识

    参数:grant_type
    是否必须:是
    说明:填refresh_token

    参数:refresh_token
    是否必须:是
    说明:填写通过access_token获取到的refresh_token参数

    返回说明
    正确的返回:
    { "access_token":"ACCESS_TOKEN",
    "expires_in":7200,
    "refresh_token":"REFRESH_TOKEN",
    "openid":"OPENID",
    "scope":"SCOPE" }



    参数:access_token
    说明:接口调用凭证

    参数:expires_in
    说明:access_token接口调用凭证超时时间,单位(秒)

    参数:refresh_token
    说明:用户刷新access_token

    参数:openid
    说明:授权用户唯一标识

    参数:scope
    说明:用户授权的作用域,使用逗号(,)分隔

    错误返回样例:
    {"errcode":40030,"errmsg":"invalid refresh_token"}

    注意:
    1、Appsecret 是应用接口使用密钥,泄漏后将可能导致应用数据泄漏、应用的用户数据泄漏等高风险后果;存储在客户端,极有可能被恶意窃取(如反编译获取Appsecret);
    2、access_token 为用户授权第三方应用发起接口调用的凭证(相当于用户登录态),存储在客户端,可能出现恶意获取access_token 后导致的用户数据泄漏、用户微信相关接口功能被恶意发起等行为;
    3、refresh_token 为用户授权第三方应用的长效凭证,仅用于刷新access_token,但泄漏后相当于access_token 泄漏,风险同上。

    建议将secret、用户数据(如access_token)放在App云端服务器,由云端中转接口调用请求。

    第三步:通过access_token调用接口
    获取access_token后,进行接口调用,有以下前提:

    1. access_token有效且未超时;

    2. 微信用户已授权给第三方应用帐号相应接口作用域(scope)。

    对于接口作用域(scope),能调用的接口有以下:
    授权作用域(scope)
    接口
    接口说明

    snsapi_base
    /sns/oauth2/access_token
    通过code换取access_token、refresh_token和已授权scope

    /sns/oauth2/refresh_token
    刷新或续期access_token使用

    /sns/auth
    检查access_token有效性

    snsapi_userinfo
    /sns/userinfo
    获取用户个人信息

    其中snsapi_base属于基础接口,若应用已拥有其它scope权限,则默认拥有snsapi_base的权限。使用snsapi_base可以让移动端网页授权绕过跳转授权登录页请求用户授权的动作,直接跳转第三方网页带上授权临时票据(code),但会使得用户已授权作用域(scope)仅为snsapi_base,从而导致无法获取到需要用户授权才允许获得的数据和基础功能。

    下面是获取用户个人信息,并dump出来
    array(10) { ["openid"]=> string(28) "oJekJs2faTQ47FGjDOEIyOPMN97s" ["nickname"]=> string(15) "方倍工作室" ["sex"]=> int(1) ["language"]=> string(5) "zh_CN" ["city"]=> string(6) "海淀" ["province"]=> string(6) "北京" ["country"]=> string(6) "中国" ["headimgurl"]=> string(139) "http://wx.qlogo.cn/mmopen/Q3auHgzwzM7zdkiaZFdM5qrwk1iaEESVjfhWVHNg22teOnfKSPpKDE0l2yfQm1hM9AeT8pO1BKElntEBZ7DxibzdteBp3H3yXESwPYUkhibNObs/0" ["privilege"]=> array(0) { } ["unionid"]=> string(28) "o4wcnw02YjFUYglZxV0LwcBkVF6Y"}

    完整代码实现如下

    <?php
    define('APPID', "wxed782be999f86e0e");
    define('APPSECRET', "72edec63779f7aa16a3a33447e2c70fb");

    class class_weixin
    {
    var $appid = APPID;
    var $appsecret = APPSECRET;

    //构造函数,获取Access Token
    public function __construct($appid = NULL, $appsecret = NULL)
    {
        if($appid && $appsecret){
            $this->appid = $appid;
            $this->appsecret = $appsecret;
        }
    }
    
    //生成扫码登录的URL
    public function qrconnect($redirect_url, $scope, $state = NULL)
    {
        $url = "https://open.weixin.qq.com/connect/qrconnect?appid=".$this->appid."&redirect_uri=".urlencode($redirect_url)."&response_type=code&scope=".$scope."&state=".$state."#wechat_redirect";
        return $url;
    }
    
    //生成OAuth2的Access Token
    public function oauth2_access_token($code)
    {
        $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$this->appid."&secret=".$this->appsecret."&code=".$code."&grant_type=authorization_code";
        $res = $this->http_request($url);
        return json_decode($res, true);
    }
    
    //获取用户基本信息(OAuth2 授权的 Access Token 获取 未关注用户,Access Token为临时获取)
    public function oauth2_get_user_info($access_token, $openid)
    {
        $url = "https://api.weixin.qq.com/sns/userinfo?access_token=".$access_token."&openid=".$openid."&lang=zh_CN";
        $res = $this->http_request($url);
        return json_decode($res, true);
    }
    
    
    //HTTP请求(支持HTTP/HTTPS,支持GET/POST)
    protected function http_request($url, $data = null)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        if (!empty($data)){
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
        $output = curl_exec($curl);
        curl_close($curl);
        return $output;
    }
    

    }

    接口调用方法如下

    <?php
    header("Content-type: text/html; charset=utf-8");
    require_once('wxopen.class.php');
    $weixin = new class_weixin();
    if (!isset($_GET["code"])){
    $redirect_url = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
    $jumpurl = $weixin->qrconnect($redirect_url, "snsapi_login", "123");
    header("Location: $jumpurl");
    }else{
    $oauth2_info = $weixin->oauth2_access_token($_GET["code"]);
    $userinfo = $weixin->oauth2_get_user_info($oauth2_info['access_token'], $oauth2_info['openid']);
    var_dump($userinfo);
    }

  • 相关阅读:
    如何确定Kafka的分区数、key和consumer线程数
    Storm程序永久代内存溢出
    JVM堆内存相关的启动参数:年轻代、老年代和永久代的内存分配
    Git添加本地项目出现fatal: unable to get credential storage lock: File exists
    Kafka的通讯协议
    文件上传 数据对比
    jquery 弹出层
    XSS 简单理解之:AntiSamy
    XSS 简单理解
    超人说我最叼蝙蝠侠笑了 超级英雄战力排名
  • 原文地址:https://www.cnblogs.com/smilevv/p/13471207.html
Copyright © 2011-2022 走看看