所謂的微信網頁受權說白了就是 用戶微信客戶端內訪問第三方網頁,公衆號能夠根據網頁受權這個機制來獲取用戶的基本信息,而後進行相應的邏輯處理。php
官方文檔 : https://mp.weixin.qq.com/wiki...html
準備工做:java
1 微信爲咱們提供了相應的測試帳號 web
能夠參考文檔 第二章 「微信開發之環境搭建」 json
或者直接看官方文檔 https://mp.weixin.qq.com/debu...api
2 填寫本身的服務器url 用於接收微信返回事件xml數據。數組
3 添加本身的 網頁受權回調域名安全
關於網頁受權回調域名的說明服務器
一、在微信公衆號請求用戶網頁受權以前,開發者須要先到公衆平臺官網中的「 開發 - 接口權限 - 網頁服務 - 網頁賬號 - 網頁受權獲取用戶基本信息」的配置選項中,修改受權回調域名。請注意,這裏填寫的是域名(是一個字符串),而不是URL,所以請勿加 http:// 等協議頭;二、受權回調域名配置規範爲全域名,好比須要網頁受權的域名爲:www.qq.com,配置之後此域名下面的頁面http://www.qq.com/music.html>... 均可以進行OAuth2.0鑑權。但http://pay.qq.com 、 http://music.qq.com 、 http://qq.com沒法進行OAuth2.0鑑權微信
三、若是公衆號登陸受權給了第三方開發者來進行管理,則沒必要作任何設置,由第三方代替公衆號實現網頁受權便可
配置回調域名 :
點擊修改 填寫本身的回調域名,開頭不須要以 http:// 或者 https:// 開頭
須要注意此處的access_token區別
關於網頁受權access_token和普通access_token的區別
一、微信網頁受權是經過OAuth2.0機制實現的,在用戶受權給公衆號後,公衆號能夠獲取到一個網頁受權特有的接口調用憑證(網頁受權access_token),經過網頁受權access_token能夠進行受權後接口調用,如獲取用戶基本信息;二、其餘微信接口,須要經過基礎支持中的「獲取access_token」接口來獲取到的普通access_token調用。
關於網頁受權的兩種scope的區別說明
一、以snsapi_base爲scope發起的網頁受權,是用來獲取進入頁面的用戶的openid的,而且是靜默受權並自動跳轉到回調頁的。用戶感知的就是直接進入了回調頁(每每是業務頁面)二、以snsapi_userinfo爲scope發起的網頁受權,是用來獲取用戶的基本信息的。但這種受權須要用戶手動贊成,而且因爲用戶贊成過,因此無須關注,就可在受權後獲取該用戶的基本信息。
三、用戶管理類接口中的「獲取用戶基本信息接口」,是在用戶和公衆號產生消息交互或關注後事件推送後,才能根據用戶OpenID來獲取用戶基本信息。這個接口,包括其餘微信接口,都是須要該用戶(即openid)關注了公衆號後,才能調用成功的。
關於以上1,2 兩種scope機制對比
網頁受權方式 | 是否提示受權 | 獲取信息 |
---|---|---|
snsapi_base | 否 | 只能獲取openid |
snsapi_userinfo | 是 | 可獲取到更詳細的信息包括openid,暱稱,地址等等 |
snsapi_userinfo 會顯示下面受權頁面,snsapi_base是不會顯示的!
第三條說明便是 :
用戶和公衆號產生消息交互或關注後事件推送後(xml數據),能夠根據xml數據中的用戶openid調用 「獲取用戶基本信息接口」獲取用戶詳細信息,但這個前提是用戶必須先關注公衆號!
關於特殊場景下的靜默受權
一、上面已經提到,對於以snsapi_base爲scope的網頁受權,就靜默受權的,用戶無感知;
二、對於已關注公衆號的用戶,若是用戶從公衆號的會話或者自定義菜單進入本公衆號的網頁受權頁,即便是scope爲snsapi_userinfo,也是靜默受權,用戶無感知。
在確保微信公衆帳號擁有受權做用域(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參數對應的受權做用域權限。
尤爲注意:因爲受權操做安全等級較高,因此在發起受權請求時,微信會對受權連接作正則強匹配校驗,若是連接的參數順序不對,受權頁面將沒法正常訪問
參考連接(請在微信客戶端中打開此連接體驗):
scope爲snsapi_base
https://open.weixin.qq.com/co...
scope爲snsapi_userinfo
https://open.weixin.qq.com/co...
參數說明
參數 | 是否必須 | 說明 |
---|---|---|
appid | 是 | 公衆號的惟一標識 |
redirect_uri | 是 | 受權後重定向的回調連接地址, 請使用 urlEncode 對連接進行處理 |
response_type | 是 | 返回類型,請填寫code |
scope | 是 | 應用受權做用域,snsapi_base (不彈出受權頁面,直接跳轉,只能獲取用戶openid),snsapi_userinfo (彈出受權頁面,可經過openid拿到暱稱、性別、所在地。而且, 即便在未關注的狀況下,只要用戶受權,也能獲取其信息 ) |
state | 否 | 重定向後會帶上state參數,開發者能夠填寫a-zA-Z0-9的參數值,最多128字節 |
#wechat_redirect | 是 | 不管直接打開仍是作頁面302重定向時候,必須帶此參數 |
尤爲注意:跳轉回調redirect_uri,應當使用https連接來確保受權code的安全性。
redirect_uri 的url 須要咱們本身來定義。
如點擊url進入 第三方網頁url
//受權後跳轉的url地址 String redirect_uri ="http://www.udeam.com" + "/getUserInfo"; String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri="+ redirect_uri +"&response_type=code&scope=SCOPE&state=STATE#wechat_redirect"; //設置本身的appid 和 受權機制 url = url.replace("APPID","xxxxxxxxxxxxxxx").replace("SCOPE","snsapi_userinfo");
受權後跳轉的url地址 controller
/** * 網頁受權獲取用戶信息 用戶贊成受權 , 獲取code * @param code * @return 頁面 */ @GetMapping("getUserInfo") public String getUserInfo(String code){ logger.info("code = " + code); //獲取用戶信息 String userAuthorzation = UserService.userAuthorzation(code); //返回數據錯誤 if (userAuthorzation.equals("error")){ return "500";} return "sucess"; }
首先請注意,這裏經過code換取的是一個特殊的網頁受權access_token,與基礎支持中的access_token(該access_token用於調用其餘接口)不一樣。公衆號可經過下述接口來獲取網頁受權access_token。若是網頁受權的做用域爲snsapi_base,則本步驟中獲取到網頁受權access_token的同時,也獲取到了openid,snsapi_base式的網頁受權流程即到此爲止。
尤爲注意:因爲公衆號的secret和獲取到的access_token安全級別都很是高,必須只保存在服務器,不容許傳給客戶端。後續刷新access_token、經過access_token獲取用戶信息等步驟,也必須從服務器發起。
請求方法
獲取code後,請求如下連接獲取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超時後,可使用refresh_token進行刷新,refresh_token有效期爲30天,當refresh_token失效以後,須要用戶從新受權。
請求方法
獲取第二步的refresh_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參數 |
返回說明
正確時返回的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 | 用戶惟一標識 |
scope | 用戶受權的做用域,使用逗號(,)分隔 |
錯誤時微信會返回JSON數據包以下(示例爲code無效錯誤):
{"errcode":40029,"errmsg":"invalid code"}
」 拉取用戶信息 「 前提 是 網頁受權做用域爲snsapi_userinfo,則此時開發者能夠經過access_token和openid拉取用戶信息了。
請求方法
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 | 用戶的惟一標識 |
lang | 返回國家地區語言版本,zh_CN 簡體,zh_TW 繁體,en 英語 |
返回數聽說明
正確時返回的JSON數據包以下:
{ "openid":" OPENID", " nickname": NICKNAME, "sex":"1", "province":"PROVINCE" "city":"CITY", "country":"COUNTRY", "headimgurl": "http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/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正方形頭像),用戶沒有頭像時該項爲空。若用戶更換頭像,原有頭像URL將失效。 |
privilege | 用戶特權信息,json 數組,如微信沃卡用戶爲(chinaunicom) |
unionid | 只有在用戶將公衆號綁定到微信開放平臺賬號後,纔會出現該字段。 |
錯誤時微信會返回JSON數據包以下(示例爲openid無效):
{"errcode":40003,"errmsg":" invalid openid "}
經過code 獲取 網頁access_token 和 用戶信息 代碼實現
/** * 網頁受權獲取用戶信息 用戶贊成受權 , 獲取code * @param args */ public static String userAuthorzation(String code){ //2 經過code換取網頁受權access_token String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code"; url=url.replace("APPID","xxxxxx").replace("SECRET","xxxxxxxxx").replace("CODE",code); String result = HttpUtil.sendHttpByGet(url);//發送請求 logger.info("經過code換取網頁受權access_token 的 result = " + result); /** * 正確時返回的JSON數據包以下: * { "access_token":"ACCESS_TOKEN", * "expires_in":7200, * "refresh_token":"REFRESH_TOKEN", * "openid":"OPENID", * "scope":"SCOPE" } * 錯誤時微信會返回JSON數據包以下(示例爲Code無效錯誤): * {"errcode":40029,"errmsg":"invalid code"} */ JSONObject jsonObject = JSONObject.parseObject(result); String access_token = jsonObject.getString("access_token"); String openid = jsonObject.getString("openid"); //返回的數據是後出錯 if(jsonObject!=null && jsonObject.toJSONString().contains("errcode")){ logger.info("經過code換取網頁受權access_token 返回數據時出錯!"); return "error"; } //第三步:刷新access_token(若是須要) //第四步:拉取用戶信息(需scope爲 snsapi_userinfo) String userMsg = getUserMsg(openid); jsonObject = JSONObject.parseObject(userMsg); if(jsonObject!=null && jsonObject.toJSONString().contains("access_token")) { logger.info("拉取用戶信息 ! " + jsonObject.toJSONString()); return jsonObject.toJSONString(); } logger.info("拉取用戶信息失敗! " + result); return "error"; }