php微信开放平台--第三方网页微信扫码登陆(OAuth2.0)

第1、OAuth2.0

  OAuth(开放受权)是一个开放标准,容许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。
  容许用户提供一个令牌,而不是用户名和密码来访问他们存放在特定服务提供者的数据。每个令牌受权一个特定的网站(例如,视频编辑网站)在特定的时段(例如,接下来的2小时内)内访问特定的资源(例如仅仅是某一相册中的视频)。这样,OAuth容许用户受权第三方网站访问他们存储在另外的服务提供者上的信息,而不须要分享他们的访问许可或他们数据的全部内容。
第2、目标
  咱们这里主要模拟使用OAuth2.0,用户经过扫描咱们网页应用的二维码并进行受权登陆来获取用户的基本信息的过程。详细的接口相关信息能够在微信开放平台上查看:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&lang=zh_CN
第3、前期准备(获取微信开发者权限)
  咱们这里主要讲的是网站(Web)应用,网站应用微信登陆是基于OAuth2.0协议标准构建的微信OAuth2.0受权登陆系统(即上面的协议)。在微信客户端受权登陆(获取用户信息)的能够查看:http://www.cnblogs.com/0201zcr/p/5131602.html

  在进行微信OAuth2.在进行微信OAuth2.0受权登陆接入以前,在微信开放平台注册开发者账号,并拥有一个已审核经过的网站应用,并得到相应的AppID和AppSecret,申请微信登陆且经过审核后,可开始接入流程。
php

 

3.一、注册开发者帐号
能够在https://open.weixin.qq.com/ 这里申请开发的帐号。因为是腾讯的网页,这里能够直接经过 QQ号进行登陆。
3.二、提交网站应用审核
在已经登陆的界面中选择“管理中心”——》网站应用——》建立网站应用

填写事后,还有有一个页面须要填写,提交一份纸质版申请书扫描件(会提供模板,咱们下载再来填写后,需盖章,签名),配置回调域名(扫码登陆后会跳转的页面)等。
  以后提交审核便可,等微信审核经过,咱们便可得到咱们须要的网页应用的appid和AppSecret,并配置后回调的域名了(这三样是咱们开发所必须的)。

css

四、受权流程说明html

微信OAuth2.0受权登陆让微信用户使用微信身份安全登陆第三方应用或网站,在微信用户受权登陆已接入微信OAuth2.0的第三方应用后,第三方能够获取到用户的接口调用凭证(access_token),经过access_token能够进行微信开放平台受权关系接口调用,从而可实现获取微信用户基本开放信息和帮助用户实现基础开放功能等。
微信OAuth2.0受权登陆目前支持authorization_code模式,适用于拥有server端的应用受权。该模式总体流程为:
1. 第三方发起微信受权登陆请求,微信用户容许受权第三方应用后,微信会拉起应用或重定向到第三方网站,而且带上受权临时票据code参数;
2. 经过code参数加上AppID和AppSecret等,经过API换取access_token;
3. 经过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操做。

json

获取access_token时序图:api

五、获取网页的二维码浏览器

当咱们经过微信的认证,获取到了appid和AppSecret,并配置了回调的域名。咱们就已经能够获取属于咱们网页的二维码了,获取的方式很简单,只需打开一个微信的连接,加上咱们的appid和回调域名便可在网页上面打开二维码,用户用微信客户端扫码并受权登陆以后即会跳转到咱们配置的回调域名下。
注意:
一、这里填写的是域名(是一个字符串),而不是URL,所以请勿加http://等协议头;
安全

二、受权回调域名配置规范为全域名,好比须要网页受权的域名为:www.qq.com,配置之后此域名下面的页面http://www.qq.com/music.html 、 http://www.qq.com/login.html 均可以进行OAuth2.0鉴权。但http://pay.qq.com 、 http://music.qq.com 、 http://qq.com没法进行OAuth2.0鉴权

服务器

5.一、请求url说明微信

第三方使用网站应用受权登陆前请注意已获取相应网页受权做用域(scope=snsapi_login),则能够经过在PC端打开如下连接:微信开发

https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

 


 返回说明
   用户容许受权后,将会重定向到redirect_uri的网址上,而且带上code和state参数
redirect_uri?code=CODE&state=STATE若用户禁止受权,则重定向后不会带上code参数,仅会带上state参数
redirect_uri?state=STATE
生成二维码代码

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>微信扫码登陆</title>
</head>
<body>
<div id="login_container"></div>
</body>
  <script src="http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>
<input type="hidden" value="{$url}" id="url">
{include file="public/css"}
{include file="public/js"}
<script>
    var url=$("#url").val();
    var obj = new WxLogin({

        id:"login_container",    //div的id

        appid: "wx84654355186541351",

        scope: "snsapi_login",

        redirect_uri: "http"+url,        //回调地址

        state: "",         //参数,可带可不带

        style: "",         //样式  提供"black"、"white"可选,默认为黑色文字描述

        href: ""                 //自定义样式连接,第三方可根据实际需求覆盖默认样式。
    });</script>
</html>

 

注意WxLogin方法在这个文件里:

<script src="http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>
 !function(a,b,c){
        function d(a){
            var c="default";
            a.self_redirect===!0?c="true":a.self_redirect===!1&&(c="false");
            var d=b.createElement("iframe"),
                    e="https://open.weixin.qq.com/connect/qrconnect?appid="+a.appid+"&scope="+a.scope+"&redirect_uri="+a.redirect_uri+"&state="+a.state+"&login_type=jssdk&self_redirect="+c;
                     e+=a.style?"&style="+a.style:"",
                    e+=a.href?"&href="+a.href:"",
                    d.src=e,
                    d.frameBorder="0",
                    d.allowTransparency="true",
                    d.scrolling="no",
                    d.width="300px",
                    d.height="400px";
            var f=b.getElementById(a.id);
            f.innerHTML="",
                    f.appendChild(d)
        }a.WxLogin=d}(window,document);

5.二、事例1:

一号店的微信二维码连接以下:

https://open.weixin.qq.com/connect/qrconnect?appid=wxbdc5610cc59c1631&redirect_uri=https%3A%2F%2Fpassport.yhd.com%2Fwechat%2Fcallback.do&response_type=code&scope=snsapi_login&state=3d6be0a4035d839573b04816624a415e#wechat_redirect

 将其复制到浏览器中打开便可得到一号店的二维码,二维码页面以下:

经过使用微信客户端的扫一扫功能,扫描该二维码,即会跳转到上面填写redirect_uri所在的地址上。假如用户赞成受权,这里就得到了微信返回的code参数了。

六、获取用户信息

假如前面已经得到code。咱们能够经过code参数去获取用户openid和access_token,进而得到用户的信息。

6.一、经过code参数获取access_token

https://api.weixin.qq.com/sns/oauth2/access_token?
appid=APPID
&secret=SECRET
&code=CODE
&grant_type=authorization_code

 

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

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

6.二、经过access_token获取用户的基本信息
获取的前提条件

access_token有效且为超时;

微信用户已受权给第三方应用帐号相应接口做用域(scope)【在二维码生成链接那里填写

使用snsapi_base做用域的受权是扫码以后无需用户点击受权,扫码后直接跳转,用户感受不到受权了,但这种受权方式能获取的数据量有限,这里咱们要获取用户的基本信息,咱们须要使用snsapi_userinfo受权。使用snsapi_userinfo受权,扫码后出现相似于下面的受权界面

此接口用于获取用户我的信息。开发者可经过OpenID来获取用户基本信息。特别须要注意的是,若是开发者拥有多个移动应用、网站应用和公众账号,可经过获取用户基本信息中的unionid来区分用户的惟一性,由于只要是同一个微信开放平台账号下的移动应用、网站应用和公众账号,用户的unionid是惟一的。换句话说,同一用户,对同一个微信开放平台下的不一样应用,unionid是相同的。请注意,在用户修改微信头像后,旧的微信头像URL将会失效,所以开发者应该本身在获取用户信息后,将头像图片保存下来,避免微信头像URL失效后的异常状况。https://api.weixin.qq.com/sns/userinfo?

access_token=ACCESS_TOKEN

&openid=OPENID

正确的Json返回结果:

{
"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"

}

七、总结

最近着手开发了微信网页扫码登陆和公众号受权登陆,二者的开发很相似。
    二者均可以经过微信客户端扫码受权的方式,让第三方页面得到微信用户的一些基本信息(昵称、性别、所在地、在微信惟一标示等……)。他们都是经过提供一个连接让用户受权的方式。但网页版须要在页面打开二维码以后受权,而公众号则须要用户先关注了咱们的公众号,而后点开公众号里面的连接,确认受权便可。
    网页扫码登陆须要将受权的连接(二维码连接)在网页中打开、而公众号受权登陆的连接必需要微信客户端中打开。
    不管网页扫码登陆仍是在公众号中受权登陆,都是经过受权的方式得到一个code参数,以后经过code参数获取access_token和openid和经过access_token和openid去获取用户的基本信息的请求连接是同样的。


八、在php使用该功能能够封装一个公共的类class_weixin_adv,在这里主要用到的是curl扩展,代码以下:

 1 <?php  2 /**  3  * 微信SDK  4  * pan041ymail@gmail.com  5 */  6 class class_weixin_adv  7 {  8 var $appid = "";  9 var $appsecret = ""; 10 //构造函数,获取Access Token 11 public function __construct($appid = NULL, $appsecret = NULL) 12  { 13 if($appid){ 14 $this->appid = $appid; 15  } 16 if($appsecret){ 17 $this->appsecret = $appsecret; 18  } 19 $this->lasttime = 1395049256; 20 $this->access_token = "nRZvVpDU7LxcSi7GnG2LrUcmKbAECzRf0NyDBwKlng4nMPf88d34pkzdNcvhqm4clidLGAS18cN1RTSK60p49zIZY4aO13sF-eqsCs0xjlbad-lKVskk8T7gALQ5dIrgXbQQ_TAesSasjJ210vIqTQ"; 21 if (time() > ($this->lasttime + 7200)){ 22 $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$this->appid."&secret=".$this->appsecret; 23 $res = $this->https_request($url); 24 $result = json_decode($res, true); 25 $this->access_token = $result["access_token"]; 26 $this->lasttime = time(); 27  } 28  } 29 //获取用户基本信息 30 public function get_user_info($openid) 31  { 32 $url = "https://api.weixin.qq.com/sns/userinfo?access_token={$this->access_token}&openid={$openid}&lang=zh_CN"; 33 $res = $this->https_request($url); 34 return json_decode($res, true); 35  } 36 //https请求 37 public function https_request($url, $data = null) 38  { 39 $curl = curl_init(); 40 curl_setopt($curl, CURLOPT_URL, $url); 41 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); 42 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); 43 if (!empty($data)){ 44 curl_setopt($curl, CURLOPT_POST, 1); 45 curl_setopt($curl, CURLOPT_POSTFIELDS, $data); 46  } 47 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 48 $output = curl_exec($curl); 49 curl_close($curl); 50 return $output; 51  } 52 }

在咱们须要用的方法里引入这个类,在这里本人使用该类的get_user_info的方法他会报错缘由多是在使用该方法时,又重新走了一遍该类的构造方法因此在获取用户的我的信息时没有用他类里面的方法,代码以下:

 1 function oauth2(){  2 include('./class_weixin_adv.php');  3 $appid="";  4 $secret="";  5 $weixin=new class_weixin_adv($appid, $secret);  6 if (isset($_GET['code'])){  7 $url="https://api.weixin.qq.com/sns/oauth2/access_token?appid={$appid}&secret={$secret}&code={$_GET['code']}&grant_type=authorization_code";  8 $res = $weixin->https_request($url);  9 $res=(json_decode($res, true)); 10 11 // $row=$weixin->get_user_info($res['openid']); 12 13 $url = "https://api.weixin.qq.com/sns/userinfo?access_token={$res['access_token']}&openid={$res['openid']}&lang=zh_CN"; 14 $res =https_request($url); 15 $res=json_decode($res, true); 16 if ($res['openid']) { 17 //用户的我的信息获取成功,咱们能够进行下一步操做,$res是用户的我的信息 18 return $res; 19 }else{ 20 return ('受权出错,请从新受权!'); 21  } 22 }else{ 23 return "NO CODE"; 24  } 25 } 26 //https请求 27 function https_request($url, $data = null) 28 { 29 $curl = curl_init(); 30 curl_setopt($curl, CURLOPT_URL, $url); 31 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); 32 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); 33 if (!empty($data)){ 34 curl_setopt($curl, CURLOPT_POST, 1); 35 curl_setopt($curl, CURLOPT_POSTFIELDS, $data); 36  } 37 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 38 $output = curl_exec($curl); 39 curl_close($curl); 40 return $output; 41 }

 

 

9、以上程序若是在本地测试须要将本地的服务器映射到外网上不然微信的服务器不能成功回调到你的服务器上,因此这个时候咱们须要下载ngrok,下载地址 :https://ngrok.com/

下载成功以后我就能够解压,以下

一、咱们在doc命令中找到ngrok.exe的文件夹

二、在执行ngrok http 80 的命令就会出现

,我在测试的时候,这个地址连接不稳,有时候连不上,(建议将电脑的防火墙关闭)。

相关文章
相关标签/搜索