1. 程式人生 > >php微信開放平臺--第三方網頁微信掃碼登入(OAuth2.0)

php微信開放平臺--第三方網頁微信掃碼登入(OAuth2.0)

第一、OAuth2.0

  OAuth(開放授權)是一個開放標準,允許使用者讓第三方應用訪問該使用者在某一網站上儲存的私密的資源(如照片,視訊,聯絡人列表),而無需將使用者名稱和密碼提供給第三方應用。
  允許使用者提供一個令牌,而不是使用者名稱和密碼來訪問他們存放在特定服務提供者的資料。每一個令牌授權一個特定的網站(例如,視訊編輯網站)在特定的時段(例如,接下來的2小時內)內訪問特定的資源(例如僅僅是某一相簿中的視訊)。這樣,OAuth允許使用者授權第三方網站訪問他們儲存在另外的服務提供者上的資訊,而不需要分享他們的訪問許可或他們資料的所有內容。
第二、目標
  我們這裡主要模擬使用OAuth2.0,使用者通過掃描我們網頁應用的二維碼並進行授權登入來獲取使用者的基本資訊的過程。詳細的介面相關資訊可以在微信開放平臺上檢視:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&lang=zh_CN
第三、前期準備(獲取微信開發者許可權)
  我們這裡主要講的是網站(Web)應用,網站應用微信登入是基於OAuth2.0協議標準構建的微信OAuth2.0授權登入系統(即上面的協議)。在微信客戶端授權登入(獲取使用者資訊)的可以檢視:http://www.cnblogs.com/0201zcr/p/5131602.html

  在進行微信OAuth2.在進行微信OAuth2.0授權登入接入之前,在微信開放平臺註冊開發者帳號,並擁有一個已稽核通過的網站應用,並獲得相應的AppID和AppSecret,申請微信登入且通過稽核後,可開始接入流程。

 

3.1、註冊開發者賬號 可以在https://open.weixin.qq.com/ 這裡申請開發的賬號。由於是騰訊的網頁,這裡可以直接通過 QQ號進行登入。 3.2、提交網站應用稽核 在已經登入的介面中選擇“管理中心”——》網站應用——》建立網站應用

填寫過後,還有有一個頁面需要填寫,提交一份紙質版申請書掃描件(會提供模板,我們下載再來填寫後,需蓋章,簽名),配置回撥域名(掃碼登入後會跳轉的頁面)等。
  之後提交稽核即可,等微信稽核通過,我們即可獲得我們需要的網頁應用的appid和AppSecret,並配置後回撥的域名了(這三樣是我們開發所必須的)。

4、授權流程說明

微信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進行介面呼叫,獲取使用者基本資料資源或幫助使用者實現基本操作。

獲取access_token時序圖:

5、獲取網頁的二維碼

當我們通過微信的認證,獲取到了appid和AppSecret,並配置了回撥的域名。我們就已經可以獲取屬於我們網頁的二維碼了,獲取的方式很簡單,只需開啟一個微信的連結,加上我們的appid和回撥域名即可在網頁上面開啟二維碼,使用者用微信客戶端掃碼並授權登入之後即會跳轉到我們配置的回撥域名下。
注意:
1、這裡填寫的是域名(是一個字串),而不是URL,因此請勿加http://等協議頭;

2、授權回撥域名配置規範為全域名,比如需要網頁授權的域名為: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.1、請求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

5.2、事例:

一號店的微信二維碼連結如下:

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引數了。

6、獲取使用者資訊

假如前面已經獲得code。我們可以通過code引數去獲取使用者openid和access_token,進而獲得使用者的資訊。

6.1、通過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.2、通過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"

}

7、總結

最近著手開發了微信網頁掃碼登入和公眾號授權登入,兩者的開發很類似。
    兩者都可以通過微信客戶端掃碼授權的方式,讓第三方頁面獲得微信使用者的一些基本資訊(暱稱、性別、所在地、在微信唯一標示等……)。他們都是通過提供一個連結讓使用者授權的方式。但網頁版需要在頁面開啟二維碼之後授權,而公眾號則需要使用者先關注了我們的公眾號,然後點開公眾號裡面的連結,確認授權即可。
    網頁掃碼登入需要將授權的連結(二維碼連結)在網頁中開啟、而公眾號授權登入的連結必須要微信客戶端中開啟。
    無論網頁掃碼登入還是在公眾號中授權登入,都是通過授權的方式獲得一個code引數,之後通過code引數獲取access_token和openid和通過access_token和openid去獲取使用者的基本資訊的請求連結是一樣的。


8、在php使用該功能可以封裝一個公共的類class_weixin_adv,在這裡主要用到的是curl擴充套件,程式碼如下:

 1 <?php
 2 /**
 3  * 微信SDK  4  * [email protected]  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/

下載成功之後我就可以解壓,如下

1、我們在doc命令中找到ngrok.exe的資料夾

2、在執行ngrok http 80 的命令就會出現

,我在測試的時候,這個地址連結不穩,有時候連不上,(建議將電腦的防火牆關閉)。