微信網(wǎng)頁授權(quán)
所謂的微信網(wǎng)頁授權(quán)說白了就是 用戶微信客戶端內(nèi)訪問第三方網(wǎng)頁汛聚,公眾號可以根據(jù)網(wǎng)頁授權(quán)這個機制來獲取用戶的基本信息棍潘,然后進行相應(yīng)的邏輯處理。
官方文檔 : https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842
準(zhǔn)備工作:
1 微信為我們提供了相應(yīng)的測試賬號
可以參考文檔 第二章 “微信開發(fā)之環(huán)境搭建”
或者直接看官方文檔 https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login
2 填寫自己的服務(wù)器url 用于接收微信返回事件xml數(shù)據(jù)。
3 添加自己的 網(wǎng)頁授權(quán)回調(diào)域名
? 關(guān)于網(wǎng)頁授權(quán)回調(diào)域名的說明
1、在微信公眾號請求用戶網(wǎng)頁授權(quán)之前堤器,開發(fā)者需要先到公眾平臺官網(wǎng)中的“ 開發(fā) - 接口權(quán)限 - 網(wǎng)頁服務(wù) - 網(wǎng)頁帳號 - 網(wǎng)頁授權(quán)獲取用戶基本信息”的配置選項中,修改授權(quán)回調(diào)域名末贾。請注意闸溃,這里填寫的是域名(是一個字符串),而不是URL拱撵,因此請勿加 http:// 等協(xié)議頭辉川;
2、授權(quán)回調(diào)域名配置規(guī)范為全域名拴测,比如需要網(wǎng)頁授權(quán)的域名為:www.qq.com乓旗,配置以后此域名下面的頁面http://www.qq.com/music.html 、 http://www.qq.com/login.html 都可以進行OAuth2.0鑒權(quán)集索。但http://pay.qq.com 屿愚、 http://music.qq.com 、 http://qq.com無法進行OAuth2.0鑒權(quán)
3抄谐、如果公眾號登錄授權(quán)給了第三方開發(fā)者來進行管理渺鹦,則不必做任何設(shè)置,由第三方代替公眾號實現(xiàn)網(wǎng)頁授權(quán)即可
配置回調(diào)域名 :
點擊修改 填寫自己的回調(diào)域名蛹含,開頭不需要以 http:// 或者 https:// 開頭
需要注意此處的access_token區(qū)別
關(guān)于網(wǎng)頁授權(quán)access_token和普通access_token的區(qū)別
1毅厚、微信網(wǎng)頁授權(quán)是通過OAuth2.0機制實現(xiàn)的,在用戶授權(quán)給公眾號后浦箱,公眾號可以獲取到一個網(wǎng)頁授權(quán)特有的接口調(diào)用憑證(網(wǎng)頁授權(quán)access_token)吸耿,通過網(wǎng)頁授權(quán)access_token可以進行授權(quán)后接口調(diào)用祠锣,如獲取用戶基本信息;
2咽安、其他微信接口伴网,需要通過基礎(chǔ)支持中的“獲取access_token”接口來獲取到的普通access_token調(diào)用。
關(guān)于網(wǎng)頁授權(quán)的兩種scope的區(qū)別說明
1妆棒、以snsapi_base為scope發(fā)起的網(wǎng)頁授權(quán)澡腾,是用來獲取進入頁面的用戶的openid的,并且是靜默授權(quán)并自動跳轉(zhuǎn)到回調(diào)頁的糕珊。用戶感知的就是直接進入了回調(diào)頁(往往是業(yè)務(wù)頁面)
2动分、以snsapi_userinfo為scope發(fā)起的網(wǎng)頁授權(quán),是用來獲取用戶的基本信息的红选。但這種授權(quán)需要用戶手動同意澜公,并且由于用戶同意過,所以無須關(guān)注喇肋,就可在授權(quán)后獲取該用戶的基本信息坟乾。
3、用戶管理類接口中的“獲取用戶基本信息接口”蝶防,是在用戶和公眾號產(chǎn)生消息交互或關(guān)注后事件推送后甚侣,才能根據(jù)用戶OpenID來獲取用戶基本信息。這個接口慧脱,包括其他微信接口渺绒,都是需要該用戶(即openid)關(guān)注了公眾號后,才能調(diào)用成功的菱鸥。
關(guān)于以上1,2 兩種scope機制對比
網(wǎng)頁授權(quán)方式 | 是否提示授權(quán) | 獲取信息 |
---|---|---|
snsapi_base | 否 | 只能獲取openid |
snsapi_userinfo | 是 | 可獲取到更詳細(xì)的信息包括openid躏鱼,昵稱氮采,地址等等 |
snsapi_userinfo 會顯示下面授權(quán)頁面,snsapi_base是不會顯示的染苛!
第三條說明即是 :
? 用戶和公眾號產(chǎn)生消息交互或關(guān)注后事件推送后(xml數(shù)據(jù))鹊漠,可以根據(jù)xml數(shù)據(jù)中的用戶openid調(diào)用 “獲取用戶基本信息接口”獲取用戶詳細(xì)信息,但這個前提是用戶必須先關(guān)注公眾號茶行!
關(guān)于特殊場景下的靜默授權(quán)
1躯概、上面已經(jīng)提到,對于以snsapi_base為scope的網(wǎng)頁授權(quán)畔师,就靜默授權(quán)的娶靡,用戶無感知;
2看锉、對于已關(guān)注公眾號的用戶姿锭,如果用戶從公眾號的會話或者自定義菜單進入本公眾號的網(wǎng)頁授權(quán)頁塔鳍,即使是scope為snsapi_userinfo,也是靜默授權(quán)呻此,用戶無感知轮纫。
步驟主要分為四步:
第一步:用戶同意授權(quán),獲取code
在確保微信公眾賬號擁有授權(quán)作用域(scope參數(shù))的權(quán)限的前提下(服務(wù)號獲得高級接口后焚鲜,默認(rèn)擁有scope參數(shù)中的snsapi_base和snsapi_userinfo)掌唾,引導(dǎo)關(guān)注者打開如下頁面:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect 若提示“該鏈接無法訪問”,請檢查參數(shù)是否填寫錯誤,是否擁有scope參數(shù)對應(yīng)的授權(quán)作用域權(quán)限序目。
尤其注意:由于授權(quán)操作安全等級較高薪前,所以在發(fā)起授權(quán)請求時,微信會對授權(quán)鏈接做正則強匹配校驗情连,如果鏈接的參數(shù)順序不對,授權(quán)頁面將無法正常訪問
參考鏈接(請在微信客戶端中打開此鏈接體驗):
scope為snsapi_base
scope為snsapi_userinfo
參數(shù)說明
參數(shù) | 是否必須 | 說明 |
---|---|---|
appid | 是 | 公眾號的唯一標(biāo)識 |
redirect_uri | 是 | 授權(quán)后重定向的回調(diào)鏈接地址览效, 請使用 urlEncode 對鏈接進行處理 |
response_type | 是 | 返回類型却舀,請?zhí)顚慶ode |
scope | 是 | 應(yīng)用授權(quán)作用域,snsapi_base (不彈出授權(quán)頁面锤灿,直接跳轉(zhuǎn)挽拔,只能獲取用戶openid),snsapi_userinfo (彈出授權(quán)頁面但校,可通過openid拿到昵稱螃诅、性別、所在地状囱。并且术裸, 即使在未關(guān)注的情況下,只要用戶授權(quán)亭枷,也能獲取其信息 ) |
state | 否 | 重定向后會帶上state參數(shù)袭艺,開發(fā)者可以填寫a-zA-Z0-9的參數(shù)值,最多128字節(jié) |
#wechat_redirect | 是 | 無論直接打開還是做頁面302重定向時候叨粘,必須帶此參數(shù) |
尤其注意:跳轉(zhuǎn)回調(diào)redirect_uri猾编,應(yīng)當(dāng)使用https鏈接來確保授權(quán)code的安全性。
redirect_uri 的url 需要我們自己來定義升敲。
如點擊url進入 第三方網(wǎng)頁url
//授權(quán)后跳轉(zhuǎn)的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";
//設(shè)置自己的appid 和 授權(quán)機制
url = url.replace("APPID","xxxxxxxxxxxxxxx").replace("SCOPE","snsapi_userinfo");
授權(quán)后跳轉(zhuǎn)的url地址 controller
/**
* 網(wǎng)頁授權(quán)獲取用戶信息 用戶同意授權(quán) , 獲取code
* @param code
* @return 頁面
*/
@GetMapping("getUserInfo")
public String getUserInfo(String code){
logger.info("code = " + code);
//獲取用戶信息
String userAuthorzation = UserService.userAuthorzation(code);
//返回數(shù)據(jù)錯誤
if (userAuthorzation.equals("error")){ return "500";}
return "sucess";
}
第二步:通過code換取網(wǎng)頁授權(quán)access_token
首先請注意答倡,這里通過code換取的是一個特殊的網(wǎng)頁授權(quán)access_token,與基礎(chǔ)支持中的access_token(該access_token用于調(diào)用其他接口)不同。公眾號可通過下述接口來獲取網(wǎng)頁授權(quán)access_token驴党。如果網(wǎng)頁授權(quán)的作用域為snsapi_base瘪撇,則本步驟中獲取到網(wǎng)頁授權(quán)access_token的同時,也獲取到了openid,snsapi_base式的網(wǎng)頁授權(quán)流程即到此為止设江。
尤其注意:由于公眾號的secret和獲取到的access_token安全級別都非常高锦茁,必須只保存在服務(wù)器,不允許傳給客戶端叉存。后續(xù)刷新access_token码俩、通過access_token獲取用戶信息等步驟,也必須從服務(wù)器發(fā)起歼捏。
請求方法
獲取code后稿存,請求以下鏈接獲取access_token:
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
參數(shù)說明
參數(shù) | 是否必須 | 說明 |
---|---|---|
appid | 是 | 公眾號的唯一標(biāo)識 |
secret | 是 | 公眾號的appsecret |
code | 是 | 填寫第一步獲取的code參數(shù) |
grant_type | 是 | 填寫為authorization_code |
返回說明
正確時返回的JSON數(shù)據(jù)包如下:
{
"access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE"
}
參數(shù) | 描述 |
---|---|
access_token | 網(wǎng)頁授權(quán)接口調(diào)用憑證,注意:此access_token與基礎(chǔ)支持的access_token不同 |
expires_in | access_token接口調(diào)用憑證超時時間,單位(秒) |
refresh_token | 用戶刷新access_token |
openid | 用戶唯一標(biāo)識瞳秽,請注意瓣履,在未關(guān)注公眾號時,用戶訪問公眾號的網(wǎng)頁练俐,也會產(chǎn)生一個用戶和公眾號唯一的OpenID |
scope | 用戶授權(quán)的作用域袖迎,使用逗號(,)分隔 |
錯誤時微信會返回JSON數(shù)據(jù)包如下(示例為Code無效錯誤):
{"errcode":40029,"errmsg":"invalid code"}
第三步:刷新access_token(如果需要)
由于access_token擁有較短的有效期,當(dāng)access_token超時后腺晾,可以使用refresh_token進行刷新燕锥,refresh_token有效期為30天,當(dāng)refresh_token失效之后悯蝉,需要用戶重新授權(quán)归形。
請求方法
獲取第二步的refresh_token后,請求以下鏈接獲取access_token:
https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN
參數(shù) | 是否必須 | 說明 |
---|---|---|
appid | 是 | 公眾號的唯一標(biāo)識 |
grant_type | 是 | 填寫為refresh_token |
refresh_token | 是 | 填寫通過access_token獲取到的refresh_token參數(shù) |
返回說明
正確時返回的JSON數(shù)據(jù)包如下:
{
"access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE"
}
參數(shù) | 描述 |
---|---|
access_token | 網(wǎng)頁授權(quán)接口調(diào)用憑證,注意:此access_token與基礎(chǔ)支持的access_token不同 |
expires_in | access_token接口調(diào)用憑證超時時間鼻由,單位(秒) |
refresh_token | 用戶刷新access_token |
openid | 用戶唯一標(biāo)識 |
scope | 用戶授權(quán)的作用域暇榴,使用逗號(,)分隔 |
錯誤時微信會返回JSON數(shù)據(jù)包如下(示例為code無效錯誤):
{"errcode":40029,"errmsg":"invalid code"}
第四步:拉取用戶信息(需scope為 snsapi_userinfo)
” 拉取用戶信息 “ 前提 是 網(wǎng)頁授權(quán)作用域為snsapi_userinfo,則此時開發(fā)者可以通過access_token和openid拉取用戶信息了蕉世。
請求方法
http:GET(請使用https協(xié)議) https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
參數(shù)說明
參數(shù) | 描述 |
---|---|
access_token | 網(wǎng)頁授權(quán)接口調(diào)用憑證,注意:此access_token與基礎(chǔ)支持的access_token不同 |
openid | 用戶的唯一標(biāo)識 |
lang | 返回國家地區(qū)語言版本蔼紧,zh_CN 簡體,zh_TW 繁體讨彼,en 英語 |
返回數(shù)據(jù)說明
正確時返回的JSON數(shù)據(jù)包如下:
{
"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"
}
參數(shù) | 描述 |
---|---|
openid | 用戶的唯一標(biāo)識 |
nickname | 用戶昵稱 |
sex | 用戶的性別歉井,值為1時是男性,值為2時是女性哈误,值為0時是未知 |
province | 用戶個人資料填寫的省份 |
city | 普通用戶個人資料填寫的城市 |
country | 國家,如中國為CN |
headimgurl | 用戶頭像躏嚎,最后一個數(shù)值代表正方形頭像大忻圩浴(有0、46卢佣、64重荠、96、132數(shù)值可選虚茶,0代表640*640正方形頭像)戈鲁,用戶沒有頭像時該項為空仇参。若用戶更換頭像,原有頭像URL將失效婆殿。 |
privilege | 用戶特權(quán)信息诈乒,json 數(shù)組,如微信沃卡用戶為(chinaunicom) |
unionid | 只有在用戶將公眾號綁定到微信開放平臺帳號后婆芦,才會出現(xiàn)該字段怕磨。 |
錯誤時微信會返回JSON數(shù)據(jù)包如下(示例為openid無效):
{"errcode":40003,"errmsg":" invalid openid "}
通過code 獲取 網(wǎng)頁access_token 和 用戶信息 代碼實現(xiàn)
/**
* 網(wǎng)頁授權(quán)獲取用戶信息 用戶同意授權(quán) , 獲取code
* @param args
*/
public static String userAuthorzation(String code){
//2 通過code換取網(wǎng)頁授權(quán)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);//發(fā)送請求
logger.info("通過code換取網(wǎng)頁授權(quán)access_token 的 result = " + result);
/**
* 正確時返回的JSON數(shù)據(jù)包如下:
* { "access_token":"ACCESS_TOKEN",
* "expires_in":7200,
* "refresh_token":"REFRESH_TOKEN",
* "openid":"OPENID",
* "scope":"SCOPE" }
* 錯誤時微信會返回JSON數(shù)據(jù)包如下(示例為Code無效錯誤):
* {"errcode":40029,"errmsg":"invalid code"}
*/
JSONObject jsonObject = JSONObject.parseObject(result);
String access_token = jsonObject.getString("access_token");
String openid = jsonObject.getString("openid");
//返回的數(shù)據(jù)是后出錯
if(jsonObject!=null && jsonObject.toJSONString().contains("errcode")){
logger.info("通過code換取網(wǎng)頁授權(quán)access_token 返回數(shù)據(jù)時出錯!");
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";
}