談?wù)劦谌紸pp接入微信登錄 解讀
接入微信登錄:
1、準(zhǔn)備工作
1.在微信開放平臺(tái)https://open.weixin.qq.com/注冊(cè)成為開發(fā)者。
2.在“管理中心”中創(chuàng)建一個(gè)移動(dòng)應(yīng)用,需“應(yīng)用名稱、簡介、及28*28和108*108的PNG圖片各一張,且大小不超過300k”,點(diǎn)擊下一步,需“應(yīng)用官網(wǎng)地址,應(yīng)用簽名及包名”等信息,然后即可提交審核。
說明:
應(yīng)用簽名:可在微信開發(fā)平臺(tái)的資源中心》》資源下載》》中下載“簽名生成工具”,用戶獲取已經(jīng)安裝到手機(jī)的第三方應(yīng)用的簽名。輸入應(yīng)用包名,即可獲得該應(yīng)用的簽名值。
3.提交審核后,在7個(gè)工作日內(nèi)騰訊將給出審核結(jié)果。(通常較快,幾個(gè)小時(shí)就可反饋結(jié)果)
2、微信登錄接入
微信登錄遵循協(xié)議Aouth2.0中的授權(quán)碼模式,先介紹一下Aouth2.0的流程:

3、微信登錄的官方文檔將微信登錄分為3個(gè)步驟:
第一步.請(qǐng)求code:
{
// send oauth request
Final SendAuth.Req req = new SendAuth.Req();
req.scope = "snsapi_userinfo";
req.state = "wechat_sdk_demo_test";
api.sendReq(req);
}
用這段代碼向微信開放平臺(tái)請(qǐng)求授權(quán)碼code,可拉起微信并打開授權(quán)登錄頁(前提是你安裝了微信應(yīng)用并已登錄,未登錄的會(huì)引導(dǎo)你先登錄)下圖:

需要注意的情況:
1.如果微信授權(quán)頁不顯示,請(qǐng)檢查你的APP簽名是否和你在騰訊開放平臺(tái)的APP簽名一致,不一致可修改騰訊開放平臺(tái)中的APP簽名,修改后重裝微信或清除微信數(shù)據(jù)后重試。
2.在你的包名相應(yīng)目錄下新建一個(gè)wxapi目錄,并在該wxapi目錄下新增一個(gè)WXEntryActivity類,該類繼承自Activity(例如應(yīng)用程序的包名為net.sourceforge,則新的包名為:net.sourceforge.wxapi),此處應(yīng)注意包名不要弄錯(cuò),新增類的名字必須為WXEntryActivity。
返回說明
用戶點(diǎn)擊授權(quán)后,微信客戶端會(huì)被拉起,跳轉(zhuǎn)至授權(quán)界面,用戶在該界面點(diǎn)擊允許或取消,SDK通過SendAuth的Resp返回?cái)?shù)據(jù)給調(diào)用方?;卣{(diào)WXEntryActivity中的onResp(BaseResp resp)方法,如下:
@Override
public void onResp(BaseResp resp) {
int errorCode = resp.errCode;
switch (errorCode) {
case BaseResp.ErrCode.ERR_OK:
//用戶同意
String code = ((SendAuth.Resp) resp).code;
break;
case BaseResp.ErrCode.ERR_AUTH_DENIED:
//用戶拒絕
break;
case BaseResp.ErrCode.ERR_USER_CANCEL:
//用戶取消
break;
default:
break;
}
ToastUtil.showMessageLong(this, resp.errStr);
}
客戶端收到授權(quán)碼后,向自己的服務(wù)器發(fā)起登錄請(qǐng)求,并附帶收到的授權(quán)碼。
服務(wù)端收到登錄請(qǐng)求,向微信開放平臺(tái)請(qǐng)求獲取access_token,微信開放平臺(tái)返回Json字符串:
第二步:通過code獲取access_token:
獲取第一步的code后,請(qǐng)求以下鏈接獲取access_token:
private String getAccessToken(String code) {
String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
URI uri = URI.create(url);
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(uri);
HttpResponse response;
try {
response = client.execute(get);
if (response.getStatusLine().getStatusCode() == 200) {
HttpEntity entity = response.getEntity();
BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"));
StringBuilder sb = new StringBuilder();
for (String temp = reader.readLine(); temp != null; temp = reader.readLine()) {
sb.append(temp);
}
JSONObject object = new JSONObject(sb.toString().trim());
accessToken = object.getString("access_token");
openID = object.getString("openid");
refreshToken = object.getString("refresh_token");
expires_in = object.getLong("expires_in");
return accessToken;
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
參數(shù)說明
參數(shù) 是否必須 說明
appid 是 應(yīng)用唯一標(biāo)識(shí),在微信開放平臺(tái)提交應(yīng)用審核通過后獲得
secret 是 應(yīng)用密鑰AppSecret,在微信開放平臺(tái)提交應(yīng)用審核通過后獲得
code 是 填寫第一步獲取的code參數(shù)
grant_type 是 填authorization_code回說明**
正確的返回:
{
"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)用憑證超時(shí)時(shí)間,單位(秒)
refresh_token 用戶刷新access_token
openid 授權(quán)用戶唯一標(biāo)識(shí)
scope 用戶授權(quán)的作用域,使用逗號(hào)(,)分隔
unionid 只有在用戶將公眾號(hào)綁定到微信開放平臺(tái)帳號(hào)后,才會(huì)出現(xiàn)該字段。
錯(cuò)誤返回樣例:
{"errcode":40029,"errmsg":"invalid code"}
第三步:通過access_token調(diào)用接口
獲取access_token后,進(jìn)行接口調(diào)用,有以下前提:
- access_token有效且未超時(shí);
- 微信用戶已授權(quán)給第三方應(yīng)用帳號(hào)相應(yīng)接口作用域(scope)。
對(duì)于接口作用域(scope),能調(diào)用的接口有以下:
授權(quán)作用域(scope) 接口 接口說明
snsapi_base /sns/oauth2/access_token 通過code換取 access_token、refresh_token和已授權(quán)scope
/sns/oauth2/refresh_token 刷新或續(xù)期access_token使用
/sns/auth 檢查access_token有效性
snsapi_userinfo /sns/userinfo 獲取用戶個(gè)人信息
其中snsapi_base屬于基礎(chǔ)接口,若應(yīng)用已擁有其它scope權(quán)限,則默認(rèn)擁有snsapi_base的權(quán)限。使用snsapi_base可以讓移動(dòng)端網(wǎng)頁授權(quán)繞過跳轉(zhuǎn)授權(quán)登錄頁請(qǐng)求用戶授權(quán)的動(dòng)作,直接跳轉(zhuǎn)第三方網(wǎng)頁帶上授權(quán)臨時(shí)票據(jù)(code),但會(huì)使得用戶已授權(quán)作用域(scope)僅為snsapi_base,從而導(dǎo)致無法獲取到需要用戶授權(quán)才允許獲得的數(shù)據(jù)和基礎(chǔ)功能。
以獲取用戶信息為例:
private void getUserInfo() {
if (isAccessTokenIsInvalid() && System.currentTimeMillis() < expires_in) {
String uri = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openID;
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(URI.create(uri));
try {
HttpResponse response = client.execute(get);
if (response.getStatusLine().getStatusCode() == 200) {
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
StringBuilder builder = new StringBuilder();
for (String temp = reader.readLine(); temp != null; temp = reader.readLine()) {
builder.append(temp);
}
JSONObject object = new JSONObject(builder.toString().trim());
String nikeName = object.getString("nickname");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
微信重復(fù)登錄
假設(shè)用戶已經(jīng)獲得授權(quán),則下次登錄時(shí)只需要驗(yàn)證access_token是否有效,無效則重新獲取授權(quán),有效則無需重新獲得授權(quán)。
1.用戶向自己的服務(wù)器請(qǐng)求登錄,登錄方式為微信登錄,附帶上次登錄返回的的access_token
2.服務(wù)器收到用戶的登錄請(qǐng)求,向微信開放平臺(tái)發(fā)送access_token是否有效的驗(yàn)證請(qǐng)求如下:
private boolean isAccessTokenIsInvalid() {
String url = "https://api.weixin.qq.com/sns/auth?access_token=" + accessToken + "&openid=" + openID;
URI uri = URI.create(url);
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(uri);
HttpResponse response;
try {
response = client.execute(get);
if (response.getStatusLine().getStatusCode() == 200) {
HttpEntity entity = response.getEntity();
BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"));
StringBuilder sb = new StringBuilder();
for (String temp = reader.readLine(); temp != null; temp = reader.readLine()) {
sb.append(temp);
}
JSONObject object = new JSONObject(sb.toString().trim());
int errorCode = object.getInt("errcode");
if (errorCode == 0) {
return true;
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
返回說明
正確的Json返回結(jié)果:
{
"errcode":0,"errmsg":"ok"
}
錯(cuò)誤的Json返回示例:
{
"errcode":40003,"errmsg":"invalid openid"
}
如果access_token有效,服務(wù)端將信息返回給客戶端,客戶端成功登錄。
如果access_token無效,服務(wù)端向微信開放平臺(tái)發(fā)送刷新access_token的請(qǐng)求如下:
access_token是調(diào)用授權(quán)關(guān)系接口的調(diào)用憑證,由于access_token有效期(目前為2個(gè)小時(shí))較短,當(dāng)access_token超時(shí)后,可以使用refresh_token進(jìn)行刷新,access_token刷新結(jié)果有兩種:
1.若access_token已超時(shí),那么進(jìn)行refresh_token會(huì)獲取一個(gè)新的access_token,新的超時(shí)時(shí)間;
2.若access_token未超時(shí),那么進(jìn)行refresh_token不會(huì)改變access_token,但超時(shí)時(shí)間會(huì)刷新,相當(dāng)于續(xù)期access_token。
刷新token
private void refreshAccessToken() {
String uri = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=" + ShareUtil.APP_ID + "&grant_type=refresh_token&refresh_token="
+ refreshToken;
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(URI.create(uri));
try {
HttpResponse response = client.execute(get);
if (response.getStatusLine().getStatusCode() == 200) {
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
StringBuilder builder = new StringBuilder();
for (String temp = reader.readLine(); temp != null; temp = reader.readLine()) {
builder.append(temp);
}
JSONObject object = new JSONObject(builder.toString().trim());
accessToken = object.getString("access_token");
refreshToken = object.getString("refresh_token");
openID = object.getString("openid");
expires_in = object.getLong("expires_in");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
正確的返回:
{
"access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE"
}
參數(shù) 說明
access_token 接口調(diào)用憑證
expires_in access_token接口調(diào)用憑證超時(shí)時(shí)間,單位(秒)
refresh_token 用戶刷新access_token
openid 授權(quán)用戶唯一標(biāo)識(shí)
scope 用戶授權(quán)的作用域,使用逗號(hào)(,)分隔
錯(cuò)誤返回樣例:
{
"errcode":40030,"errmsg":"invalid refresh_token"
}
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JavaScript的9個(gè)陷阱及評(píng)點(diǎn)分析
以下是JavaScript容易犯錯(cuò)的九個(gè)陷阱。雖然不是什么很高深的技術(shù)問題,但注意一下,會(huì)使您的編程輕松些,即所謂make life easier. 筆者對(duì)某些陷阱會(huì)混雜一些評(píng)點(diǎn)。2008-05-05
JavaScript實(shí)現(xiàn)存儲(chǔ)HTML字符串示例
這篇文章主要介紹了JavaScript存儲(chǔ)HTML字符串的具體實(shí)現(xiàn),需要的朋友可以參考下2014-04-04
淺談bootstrap源碼分析之tab(選項(xiàng)卡)
下面小編就為大家?guī)硪黄獪\談bootstrap源碼分析之tab(選項(xiàng)卡)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-06-06
實(shí)現(xiàn)web打印的各種方法介紹及實(shí)現(xiàn)代碼
web的打印方法具我自己懂得知道的有:JQuery插件Jqprint實(shí)現(xiàn);JQery打印插件PrintArea實(shí)現(xiàn)網(wǎng)頁打印;CSS控制網(wǎng)頁打印樣式,本文詳細(xì)介紹實(shí)現(xiàn)步驟,感興趣的朋友可以了解下2013-01-01

