如果用户在微信客户端中访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,进而实现业务逻辑。

1. 关于OAuth2.0的说明

官方网站:http://oauth.net/   http://oauth.net/2/

权威定义:OAuth is An open protocol to allow secure authorization in a simple and standard method from web, mobile and desktop applications.

OAuth是一个开放协议,允许用户让第三方应用以安全且标准的方式获取该用户在某一网站、移动或桌面应用上存储的私密的资源(如用户个人信息、照片、视频、联系人列表),而无需将用户名和密码提供给第三方应用。

OAuth 2.0是OAuth协议的下一版本,但不向后兼容OAuth 1.0。 OAuth 2.0关注客户端开发者的简易性,同时为Web应用,桌面应用和手机,和起居室设备提供专门的认证流程。

OAuth允许用户提供一个令牌,而不是用户名和密码来访问他们存放在特定服务提供者的数据。每一个令牌授权一个特定的网站(例如,视频编辑网站)在特定的时段(例如,接下来的2小时内)内访问特定的资源(例如仅仅是某一相册中的视频)。这样,OAuth允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要分享他们的访问许可或他们数据的所有内容。

新浪微博API目前也使用OAuth 2.0。

2. 微信公众平台OAuth2.0授权

大体流程如下图:

2.1 用户请求

用户首先请求第三方网页

2.2 第三方服务器处理

第三方服务器获取用户请求后会进行判断,是否需要获取code(正常请求肯定是需要code的,这里我们可以参考一下官方JsApiPay的mode,来看获取openid的大体流程)

  1 <?php
  2 require_once "../lib/WxPay.Api.php";
  3 /**
  4  *
  5  * JSAPI支付实现类
  6  * 该类实现了从微信公众平台获取code、通过code获取openid和access_token、
  7  * 生成jsapi支付js接口所需的参数、生成获取共享收货地址所需的参数
  8  *
  9  * 该类是微信支付提供的样例程序,商户可根据自己的需求修改,或者使用lib中的api自行开发
 10  *
 11  * @author widy
 12  *
 13  */
 14 class JsApiPay
 15 {
 16     /**
 17      *
 18      * 网页授权接口微信服务器返回的数据,返回样例如下
 19      * {
 20      *  "access_token":"ACCESS_TOKEN",
 21      *  "expires_in":7200,
 22      *  "refresh_token":"REFRESH_TOKEN",
 23      *  "openid":"OPENID",
 24      *  "scope":"SCOPE",
 25      *  "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
 26      * }
 27      * 其中access_token可用于获取共享收货地址
 28      * openid是微信支付jsapi支付接口必须的参数
 29      * @var array
 30      */
 31     public $data = null;
 32
 33     /**
 34      *
 35      * 通过跳转获取用户的openid,跳转流程如下:
 36      * 1、设置自己需要调回的url及其其他参数,跳转到微信服务器https://open.weixin.qq.com/connect/oauth2/authorize
 37      * 2、微信服务处理完成之后会跳转回用户redirect_uri地址,此时会带上一些参数,如:code
 38      *
 39      * @return 用户的openid
 40      */
 41     public function GetOpenid()
 42     {
 43         //通过code获得openid
 44         if (!isset($_GET['code'])){
 45             //触发微信返回code码
 46             $baseUrl = urlencode('http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].$_SERVER['QUERY_STRING']);
 47             $url = $this->__CreateOauthUrlForCode($baseUrl);
 48             Header("Location: $url");
 49             exit();
 50         } else {
 51             //获取code码,以获取openid
 52             $code = $_GET['code'];
 53             $openid = $this->getOpenidFromMp($code);
 54             return $openid;
 55         }
 56     }
 57
 58     /**
 59      *
 60      * 获取jsapi支付的参数
 61      * @param array $UnifiedOrderResult 统一支付接口返回的数据
 62      * @throws WxPayException
 63      *
 64      * @return json数据,可直接填入js函数作为参数
 65      */
 66     public function GetJsApiParameters($UnifiedOrderResult)
 67     {
 68         if(!array_key_exists("appid", $UnifiedOrderResult)
 69         || !array_key_exists("prepay_id", $UnifiedOrderResult)
 70         || $UnifiedOrderResult['prepay_id'] == "")
 71         {
 72             throw new WxPayException("参数错误");
 73         }
 74         $jsapi = new WxPayJsApiPay();
 75         $jsapi->SetAppid($UnifiedOrderResult["appid"]);
 76         $timeStamp = time();
 77         $jsapi->SetTimeStamp("$timeStamp");
 78         $jsapi->SetNonceStr(WxPayApi::getNonceStr());
 79         $jsapi->SetPackage("prepay_id=" . $UnifiedOrderResult['prepay_id']);
 80         $jsapi->SetSignType("MD5");
 81         $jsapi->SetPaySign($jsapi->MakeSign());
 82         $parameters = json_encode($jsapi->GetValues());
 83         return $parameters;
 84     }
 85
 86     /**
 87      *
 88      * 通过code从工作平台获取openid机器access_token
 89      * @param string $code 微信跳转回来带上的code
 90      *
 91      * @return openid
 92      */
 93     public function GetOpenidFromMp($code)
 94     {
 95         $url = $this->__CreateOauthUrlForOpenid($code);
 96         //初始化curl
 97         $ch = curl_init();
 98         //设置超时
 99         curl_setopt($ch, CURLOPT_TIMEOUT, $this->curl_timeout);
100         curl_setopt($ch, CURLOPT_URL, $url);
101         curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,FALSE);
102         curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,FALSE);
103         curl_setopt($ch, CURLOPT_HEADER, FALSE);
104         curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
105         if(WxPayConfig::CURL_PROXY_HOST != "0.0.0.0"
106             && WxPayConfig::CURL_PROXY_PORT != 0){
107             curl_setopt($ch,CURLOPT_PROXY, WxPayConfig::CURL_PROXY_HOST);
108             curl_setopt($ch,CURLOPT_PROXYPORT, WxPayConfig::CURL_PROXY_PORT);
109         }
110         //运行curl,结果以jason形式返回
111         $res = curl_exec($ch);
112         curl_close($ch);
113         //取出openid
114         $data = json_decode($res,true);
115         $this->data = $data;
116         $openid = $data['openid'];
117         return $openid;
118     }
119
120     /**
121      *
122      * 拼接签名字符串
123      * @param array $urlObj
124      *
125      * @return 返回已经拼接好的字符串
126      */
127     private function ToUrlParams($urlObj)
128     {
129         $buff = "";
130         foreach ($urlObj as $k => $v)
131         {
132             if($k != "sign"){
133                 $buff .= $k . "=" . $v . "&";
134             }
135         }
136
137         $buff = trim($buff, "&");
138         return $buff;
139     }
140
141     /**
142      *
143      * 获取地址js参数
144      *
145      * @return 获取共享收货地址js函数需要的参数,json格式可以直接做参数使用
146      */
147     public function GetEditAddressParameters()
148     {
149         $getData = $this->data;
150         $data = array();
151         $data["appid"] = WxPayConfig::APPID;
152         $data["url"] = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
153         $time = time();
154         $data["timestamp"] = "$time";
155         $data["noncestr"] = "1234568";
156         $data["accesstoken"] = $getData["access_token"];
157         ksort($data);
158         $params = $this->ToUrlParams($data);
159         $addrSign = sha1($params);
160
161         $afterData = array(
162             "addrSign" => $addrSign,
163             "signType" => "sha1",
164             "scope" => "jsapi_address",
165             "appId" => WxPayConfig::APPID,
166             "timeStamp" => $data["timestamp"],
167             "nonceStr" => $data["noncestr"]
168         );
169         $parameters = json_encode($afterData);
170         return $parameters;
171     }
172
173     /**
174      *
175      * 构造获取code的url连接
176      * @param string $redirectUrl 微信服务器回跳的url,需要url编码
177      *
178      * @return 返回构造好的url
179      */
180     private function __CreateOauthUrlForCode($redirectUrl)
181     {
182         $urlObj["appid"] = WxPayConfig::APPID;
183         $urlObj["redirect_uri"] = "$redirectUrl";
184         $urlObj["response_type"] = "code";
185         $urlObj["scope"] = "snsapi_base";
186         $urlObj["state"] = "STATE"."#wechat_redirect";
187         $bizString = $this->ToUrlParams($urlObj);
188         return "https://open.weixin.qq.com/connect/oauth2/authorize?".$bizString;
189     }
190
191     /**
192      *
193      * 构造获取open和access_toke的url地址
194      * @param string $code,微信跳转带回的code
195      *
196      * @return 请求的url
197      */
198     private function __CreateOauthUrlForOpenid($code)
199     {
200         $urlObj["appid"] = WxPayConfig::APPID;
201         $urlObj["secret"] = WxPayConfig::APPSECRET;
202         $urlObj["code"] = $code;
203         $urlObj["grant_type"] = "authorization_code";
204         $bizString = $this->ToUrlParams($urlObj);
205         return "https://api.weixin.qq.com/sns/oauth2/access_token?".$bizString;
206     }
207 }

2.3 授权

如果需要获取code,第三方服务器会跳转到授权页面

在确保微信公众账号拥有授权作用域(scope参数)的权限的前提下(服务号获得高级接口后,默认拥有scope参数中的snsapi_base和snsapi_userinfo),引导关注者打开如下页面

请求方法如下:

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect 若提示“该链接无法访问”,请检查参数是否填写错误,是否拥有scope参数对应的授权作用域权限。

参数说明:

参数  必须 说明
appid 公众号的唯一标识
redirect_uri 授权后重定向的回调链接地址
response_type 返回类型,请填写code
scope 应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息)
state 重定向后会带上state参数,开发者可以填写任意参数值
#wechat_redirect 直接在微信打开链接,可以不填此参数。做页面302重定向时候,必须带此参数

下图为scope等于snsapi_userinfo时的授权页面:

2.4 用户同意授权

用户同意授权将信息发送到微信公众平台,微信公众平台会内部进行授权验证

用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE。

code说明 : code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。

2.5 获取网页授权

验证通过返回给第三方服务器code

通过code换取网页授权access_token

首先请注意,这里通过code换取的是一个特殊的网页授权access_token,与基础支持中的access_token(该access_token用于调用其他接口)不同。公众号可通过下述接口来获取网页授权access_token。如果网页授权的作用域为snsapi_base,则本步骤中获取到网页授权access_token的同时,也获取到了openid,snsapi_base式的网页授权流程即到此为止。

请求方法如下:

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

返回说明:

正确时返回的JSON数据包如下:

{ "access_token":"ACCESS_TOKEN",    "expires_in":7200,    "refresh_token":"REFRESH_TOKEN",    "openid":"OPENID",    "scope":"SCOPE" }

参数说明:

 参数 描述
access_token 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
expires_in access_token接口调用凭证超时时间,单位(秒)
refresh_token 用户刷新access_token
openid 用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID
scope 用户授权的作用域,使用逗号(,)分隔

错误时微信会返回JSON数据包如下(示例为Code无效错误):

{"errcode":40029,"errmsg":"invalid code"}

2.6 判断access_token过期

如果access_token过期了需要重新刷取access_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参数

2.7 拉取用户信息

官方文档有说明,需要scope为snsapi_userinfo

请求方法如下:

http:GET(请使用https协议) https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

参数说明:

参数 描述
access_token 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
openid 用户的唯一标识

返回说明

正确时返回的JSON数据包如下:

{    "openid":" OPENID",  " nickname": NICKNAME,   "sex":"1",   "province":"PROVINCE"   "city":"CITY",   "country":"COUNTRY",    "headimgurl":    "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",  "privilege":[ "PRIVILEGE1" "PRIVILEGE2"     ],    "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL" }

参数说明:

 参数 描述
openid 用户的唯一标识
nickname 用户昵称
sex 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
province 用户个人资料填写的省份
city 普通用户个人资料填写的城市
country 国家,如中国为CN
headimgurl 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空
privilege 用户特权信息,json 数组,如微信沃卡用户为(chinaunicom)

错误时微信会返回JSON数据包如下(示例为openid无效):

{"errcode":40003,"errmsg":" invalid openid "}

其他一些细节性的问题请参考官方文档:https://mp.weixin.qq.com/wiki

微信开发网页授权获取用户信息相关推荐

  1. 微信开发 网页授权获取用户基本信息

    微信公众平台最近新推出微信认证,认证后可以获得高级接口权限,其中一个是OAuth2.0网页授权,很多朋友在使用这个的时候失败了或者无法理解其内容,希望我出个教程详细讲解一下,于是便有了这篇文章. 一. ...

  2. 连小白都能看懂的微信开发之 微信自定义菜单 + 获取网页授权 + 获取用户信息

    微信自定义菜单+获取网页授权+获取用户信息 今天项目需要一个需求,就是添加一个菜单接口,并且还可以获取用于的信息,从而根据用户的信息去做一些业务的查询.通过百度和自己查看文档大致的解决办法如下: 注意 ...

  3. Spring Boot 微信-网页授权获取用户信息

    微信-验证服务器有效性 微信-网页授权获取用户信息 网页授权获取用户信息步骤 第一步:用户同意授权,获取code 第二步:通过code换取网页授权access_token 第三步:拉取用户信息(需sc ...

  4. 支付宝 网页授权 获取用户信息

    ****** 支付宝 网页授权 获取用户信息(昵称,头像等)****** 最近有个项目 需要获取到支付宝的头像和昵称作为互动数据,作为php新人,对于看文档来说 很是痛苦,网上也没有很多关于支付宝网页 ...

  5. vue h5微信公众号授权获取用户信息

    vue h5微信公众号授权获取用户信息 1.申请测试账号 https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login 2.修改网页授权 ...

  6. 微信小程序授权获取用户信息和手机号码

    微信小程序授权获取用户信息和手机号码 1.微信官方文档 登录:https://developers.weixin.qq.com/miniprogram/dev/framework/open-abili ...

  7. 微信小程序授权 获取用户信息

    微信小程序授权 获取用户信息 小程序昵称突然变成了"微信用户",头像也不显示, <!-- 近期很多小伙伴通过该方法获取头像和昵称,代码也没有做改变,突然就变成了下面这样子 - ...

  8. 微信公众号开发之授权获取用户信息

    微信开发交流群:148540125 系列文章参考地址 极速开发微信公众号 欢迎留言.转发.打赏 项目源码参考地址 点我点我--欢迎Start 前几篇文章已讲完如何导入项目,如何启动配置项目,如何成为开 ...

  9. PHP 微信网页授权获取用户信息

    最近用到过微信用户授权获取用户信息的功能,在这里记录一下. 因为用户授权要用到认证过的服务号才有权限,而线上正在使用公众号,而开发就有些不方便了,这里可以申请一个微信公众测试号. 1.申请一个微信公众 ...

最新文章

  1. 记录一次bug解决过程:eclipse Installed JREs 配置引出的问题
  2. 优秀的产品经理和一般的产品经理之间的区别
  3. mysql json函数_Mysql里的JSON系列操作函数
  4. The current branch is not configured for pull N...
  5. cpu —>内存—>硬盘这种方式是不是更慢?
  6. android 自定义View【2】对话框取色色盘取色的实现
  7. eclipse的下载、安装
  8. linux视频补帧,如何用 60 帧播放 24 帧的视频?
  9. 51ditu Maps API 类参考文档
  10. html 通知页面,12款体验不错的网站提示/通知样式
  11. Arduino与Proteus仿真实例-SHT7x温度湿度传感器驱动仿真
  12. 管理项目干系人时,巧用工具可以事半功倍
  13. 压缩感知算法_CEALeti研发出基于压缩感知的CMOS图像传感器
  14. ARM核心板有哪些不同之处?
  15. Android手电筒开发
  16. jvm-sandbox:基础了解及demo演示
  17. 机器学习日记(13)
  18. python初中必背语法_全初中必背英语语法知识汇总
  19. git tag 标签重命名
  20. 使用VBA在Office中输入特殊字符(1/3)

热门文章

  1. 新款奔驰S400L改装原厂360全景影像系统,不在担心走向问题
  2. 从零开始操作系统------探析保护模式
  3. 基于自适应反向学习的黏菌算法
  4. UG NX 10 草图重新附着
  5. 网易AI入选2018年杭州案例
  6. Docker基础入门详解
  7. 【数学思维】运筹学-线性规划之标准形式与Hidden LP
  8. 2019丘成桐中学科学奖计算机,2019年丘成桐中学科学奖总决赛获奖名单
  9. springboot+Vue整合Luckysheet,实现在线编辑Excel表格
  10. JSP中访问本地图片