微信開發_網頁受權獲取用戶的基本信息

若是用戶在微信客戶端中訪問第三方網頁,公衆號能夠經過微信網頁受權機制,來獲取用戶基本信息,進而實現業務邏輯。

關於OAuth2.0的說明

官方網站:http://oauth.net/   http://oauth.net/2/php

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

OAuth是一個開放協議,容許用戶讓第三方應用以安全且標準的方式獲取該用戶在某一網站、移動或桌面應用上存儲的私密的資源(如用戶我的信息、照片、視頻、聯繫人列表),而無需將用戶名和密碼提供給第三方應用。json

OAuth 2.0是OAuth協議的下一版本,但不向後兼容OAuth 1.0。 OAuth 2.0關注客戶端開發者的簡易性,同時爲Web應用,桌面應用和手機,和起居室設備提供專門的認證流程。api

OAuth容許用戶提供一個令牌,而不是用戶名和密碼來訪問他們存放在特定服務提供者的數據。每個令牌受權一個特定的網站(例如,視頻編輯網站)在特定的時段(例如,接下來的2小時內)內訪問特定的資源(例如僅僅是某一相冊中的視頻)。這樣,OAuth容許用戶受權第三方網站訪問他們存儲在另外的服務提供者上的信息,而不須要分享他們的訪問許可或他們數據的全部內容。數組

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

微信公衆平臺OAuth2.0受權

大致流程以下圖:服務器

 

用戶請求

用戶首先請求第三方網頁微信

第三方服務器處理

第三方服務器獲取用戶請求後會進行判斷,是否須要獲取code(正常請求確定是須要code的,這裏咱們能夠參考一下官方JsApiPay的mode,來看獲取openid的大致流程)app

  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      * 一、設置本身須要調回的url及其其餘參數,跳轉到微信服務器https://open.weixin.qq.com/connect/oauth2/authorize
 37      * 二、微信服務處理完成以後會跳轉回用戶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 }
展開代碼

受權

若是須要獲取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時的受權頁面:

用戶贊成受權

用戶贊成受權將信息發送到微信公衆平臺,微信公衆平臺會內部進行受權驗證

用戶贊成受權,頁面將跳轉至 redirect_uri/?code=CODE&state=STATE。

code說明 : code做爲換取access_token的票據,每次用戶受權帶上的code將不同,code只能使用一次,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"}

判斷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參數

拉取用戶信息

官方文檔有說明,須要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/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ

4eMsv84eavHiaiceqxibJxCfHe/46",  

"privilege":[ "PRIVILEGE1" "PRIVILEGE2"     ],    

 "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL" 

}

參數說明:

 參數 描述
openid 用戶的惟一標識
nickname 用戶暱稱
sex 用戶的性別,值爲1時是男性,值爲2時是女性,值爲0時是未知
province 用戶我的資料填寫的省份
city 普通用戶我的資料填寫的城市
country 國家,如中國爲CN
headimgurl 用戶頭像,最後一個數值表明正方形頭像大小(有0、4六、6四、9六、132數值可選,0表明640*640正方形頭像),用戶沒有頭像時該項爲空
privilege 用戶特權信息,json 數組,如微信沃卡用戶爲(chinaunicom)

 錯誤時微信會返回JSON數據包以下(示例爲openid無效):

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

其餘一些細節性的問題請參考官方文檔:https://mp.weixin.qq.com/wiki

相關文章
相關標籤/搜索