一:介紹
第三方登錄有QQ、微信、微博、支付寶等等,如果現(xiàn)在自己的項(xiàng)目中實(shí)現(xiàn)這些登錄,即可以使用友盟的sdk,也可以一個一個接入,各有各的有點(diǎn),這里不做贅述。
今天和大家分享的是,在項(xiàng)目中實(shí)現(xiàn)微信登錄,雖然微信官網(wǎng)給出了接入文檔,但是我在接入的過程中,遇到一些問題,在此做出總結(jié)以便大家參考。主要講微信snsapi_base靜默授權(quán)與snsapi_userinfo網(wǎng)頁授權(quán)的實(shí)現(xiàn)。
二:準(zhǔn)備工作
移動應(yīng)用微信登錄是基于OAuth2.0標(biāo)準(zhǔn)協(xié)議構(gòu)建的微信OAuth2.0授權(quán)登錄系統(tǒng)。
在進(jìn)行微信OAuth2.0授權(quán)登錄接入之前,需要完成一下工作才可以開始介接入:
- 在微信開放平臺注冊開發(fā)者帳號;
- 擁有一個已審核通過的移動應(yīng)用;
- 并獲得相應(yīng)的AppID和AppSecret;
- 申請微信登錄且通過審核。
三:授權(quán)流程
微信OAuth2.0授權(quán)登錄目前支持authorization_code模式,適用于擁有server端的應(yīng)用授權(quán)。該模式整體流程為:
- 第三方發(fā)起微信授權(quán)登錄請求,微信用戶允許授權(quán)第三方應(yīng)用后,微信會拉起應(yīng)用或重定向到第三方網(wǎng)站,并且?guī)鲜跈?quán)臨時票據(jù)code參數(shù);
- 通過code參數(shù)加上AppID和AppSecret等,通過API換取access_token;
- 通過access_token進(jìn)行接口調(diào)用,獲取用戶基本數(shù)據(jù)資源或幫助用戶實(shí)現(xiàn)基本操作。
獲取access_token時序圖:

四:靜默授權(quán)與網(wǎng)頁授權(quán)的實(shí)現(xiàn)
1. 靜默授權(quán)與網(wǎng)頁授權(quán)的區(qū)別
網(wǎng)頁授權(quán):
req.scope = @"snsapi_userinfo";
靜默授權(quán):
req.scope = @"snsapi_base";
snsapi_base與snsapi_userinfo屬于微信網(wǎng)頁授權(quán)獲取用戶信息的兩種作用域:
snsapi_base只能獲取access_token和openID
snsapi_userinfo可以獲取更詳細(xì)的用戶資料,比如頭像、昵稱、性別等
2. 獲取CODE
再登錄按鈕的點(diǎn)擊事件中寫入一下代碼:
//構(gòu)造SendAuthReq結(jié)構(gòu)體
SendAuthReq* req =[[[SendAuthReq alloc]init]autorelease];
req.scope = @"snsapi_userinfo";
req.state = @"123";
//第三方向微信終端發(fā)送一個SendAuthReq消息結(jié)構(gòu)
[WXApi sendReq:req];
在AppDelegate的didFinishLaunchingWithOptions方法中注冊:
[WXApi registerApp:@"wx1234567890"];
"wx1234567890"為appid,請更換為自己項(xiàng)目的appid
拉起微信打開授權(quán)登錄頁如下圖:

點(diǎn)擊確認(rèn)登陸,授權(quán)后回調(diào) WXApiDelegate
-(void)onResp:(BaseReq *)resp
{
/*
ErrCode ERR_OK = 0(用戶同意)
ERR_AUTH_DENIED = -4(用戶拒絕授權(quán))
ERR_USER_CANCEL = -2(用戶取消)
code 用戶換取access_token的code,僅在ErrCode為0時有效
state 第三方程序發(fā)送時用來標(biāo)識其請求的唯一性的標(biāo)志,由第三方程序調(diào)用sendReq時傳入,由微信終端回傳,state字符串長度不能超過1K
lang 微信客戶端當(dāng)前語言
country 微信用戶當(dāng)前國家信息
*/
if ([resp isKindOfClass:[SendAuthResp class]]) //判斷是否為授權(quán)請求,否則與微信支付等功能發(fā)生沖突
{
SendAuthResp *aresp = (SendAuthResp *)resp;
if (aresp.errCode== 0)
{
NSLog(@"code %@",aresp.code);
[[NSNotificationCenter defaultCenter] postNotificationName:@"wechatDidLoginNotification" object:self userInfo:@{@"code":aresp.code}];
}
}
}
使用通知,將aresp.code傳遞到登錄頁面
3. 通過code獲取access_token
在登錄頁面通過通知,獲取到code之后,請求以下鏈接獲取access_token:
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
參數(shù)說明:
- appid:應(yīng)用唯一標(biāo)識,在微信開放平臺提交應(yīng)用審核通過后獲得
- secret:應(yīng)用密鑰AppSecret,在微信開放平臺提交應(yīng)用審核通過后獲得
- code:填寫第一步獲取的code參數(shù)
- grant_type:填authorization_code
網(wǎng)絡(luò)請求返回的參數(shù)格式如下:
{
"access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE",
"unionid":"o6_bmasdasdsad6_2sgVt7hMZOPfL"
}
參數(shù)說明:
- access_token:接口調(diào)用憑證
- expires_in:access_token接口調(diào)用憑證超時時間,單位(秒)
- refresh_token:用戶刷新access_token
- openid:授權(quán)用戶唯一標(biāo)識
- scope:用戶授權(quán)的作用域,使用逗號(,)分隔
- unionid:當(dāng)且僅當(dāng)該移動應(yīng)用已獲得該用戶的userinfo授權(quán)時,才會出現(xiàn)該字段
4. 注意:
- 建議將Appsecret、用戶數(shù)據(jù)(如access_token)放在App云端服務(wù)器,由云端中轉(zhuǎn)接口調(diào)用請求:
Appsecret 是應(yīng)用接口使用密鑰,泄漏后將可能導(dǎo)致應(yīng)用數(shù)據(jù)泄漏、應(yīng)用的用戶數(shù)據(jù)泄漏等高風(fēng)險后果;存儲在客戶端,極有可能被惡意竊取(如反編譯獲取Appsecret);
access_token 為用戶授權(quán)第三方應(yīng)用發(fā)起接口調(diào)用的憑證(相當(dāng)于用戶登錄態(tài)),存儲在客戶端,可能出現(xiàn)惡意獲取access_token 后導(dǎo)致的用戶數(shù)據(jù)泄漏、用戶微信相關(guān)接口功能被惡意發(fā)起等行為;
refresh_token 為用戶授權(quán)第三方應(yīng)用的長效憑證,僅用于刷新access_token,但泄漏后相當(dāng)于access_token 泄漏,風(fēng)險同上。
- 要注意網(wǎng)絡(luò)授權(quán)網(wǎng)頁授權(quán)access_token 與 普通access_token的區(qū)別:
- 網(wǎng)頁授權(quán)的access_token在每次獲取openID時一起更新,在接口調(diào)用頻次限制中為“無上限”;
- 普通access_token一般限制為2000次/日,需要自己保存起來并定時更新。
到這里同時獲得access_token和openid,靜默授權(quán)與網(wǎng)頁授權(quán)操作都是一樣的。根據(jù)官網(wǎng)文檔,網(wǎng)頁授權(quán)還可以進(jìn)一步操作,獲取用戶更多詳細(xì)信息。
5. 獲取用戶個人信息(UnionID機(jī)制)
此接口用于獲取用戶個人信息,開發(fā)者可通過OpenID來獲取用戶基本信息,接口如下:
https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID
參數(shù)說明:
- access_token:調(diào)用憑證
- openid:普通用戶的標(biāo)識,對當(dāng)前開發(fā)者帳號唯一
正確的Json返回結(jié)果:
{
"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"
}
6. 靜默授權(quán)獲取到用戶詳細(xì)資料
在第3步通過snsapi_base,同時獲得access_token和openid,
把這里的access_token和openid用于下面接口中:
https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
參數(shù)說明:
- access_token:調(diào)用憑證
- openid:普通用戶的標(biāo)識,對當(dāng)前開發(fā)者帳號唯一
- lang:國家地區(qū)語言版本,zh_CN 簡體,zh_TW 繁體,en 英語,默認(rèn)為zh-CN
Json返回結(jié)果和snsapi_userinfo下獲取的用戶詳情一樣。
但是這個方法的前提是同一個公眾號內(nèi),用戶關(guān)注了,如果是其他公眾號,還是需要用戶點(diǎn)擊授權(quán)的。
希望可以幫助大家
如果哪里有什么不對或者不足的地方,還望讀者多多提意見或建議
如需轉(zhuǎn)載請聯(lián)系我,經(jīng)過授權(quán)方可轉(zhuǎn)載,謝謝
關(guān)注【網(wǎng)羅開發(fā)】公眾號,領(lǐng)資源