微信开发网页授权获取用户信息
如果用戶在微信客戶端中訪問第三方網頁,公眾號可以通過微信網頁授權機制,來獲取用戶基本信息,進而實現業務邏輯。
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
總結
以上是生活随笔為你收集整理的微信开发网页授权获取用户信息的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何快速插入大量/批量随机数据到数据库(
- 下一篇: python将一张图片粘贴到另外一张图片