Java微信公眾號開發 - 獲取用戶信息

本文旨在提供一個Java開發微信公眾號服務器的一個入門級別教程,由于本人水平有限,文中若出現錯誤歡迎同學們指正!作者郵箱luo.xuelin@nclantuo.com。本文歡迎轉載,但請注明出處來自SteinsGate博客!
俗話說的好,什么教程都比不上官方開發者文檔。所以,微信開發者開發文檔在此:開發者文檔

目錄

<a name="part1">一、網頁授權獲取用戶信息</a>

1、網頁授權的說明

網頁授權 即用戶在微信客戶端訪問第三方網頁時,可以通過網頁授權機制,來獲取用戶的基本信息,從而實現業務邏輯。例如登陸、注冊等。
openid 即用戶相對于一個公眾號來說的唯一標識,可以理解成在此公眾號內的用戶ID

配置回調域名
在微信公眾號使用網頁授權之前,開發者需要到公眾平臺的 開發 > 接口權限 菜單中的網頁授權獲取用戶基本信息欄配置授權回調域名,且只需要填寫域名,不需要加http://等協議頭。
回調域名必須為全域名。比如配置的域名為www.baidu.com,配置以后此域名下的頁面http://www.baidu.com/code.html、http://www.baidu.com/test/login.html都可以進行網頁授權。但http://tieba.baidu.com之類的無法進行網頁授權。

網頁授權兩種scope的區別
snsapi_base 為scope發起的網頁授權,是用來獲取進入頁面用戶的openid的,并且是靜默授權并自動跳轉到回調頁面。用戶并不會感知到授權過程直接進入了第三方的頁面。
snsapi_userinfo 為scope發起的網頁授權,是用來獲取用戶的基本信息的。但這種授權需要用戶手動確認,并且由于用戶確認過,所以開發者也可以獲取到未關注用戶的基本信息。

特殊場景下的靜默授權
上面已提到,對于已snsapi_base為scope的網頁授權,就靜默授權,用戶不會感知到。
對于已關注公眾號的用戶,如果是從公眾號的會話或者是菜單進入的網頁授權頁面,即使scope是snsapi_userinfo,也是靜默授權。

網頁授權access_token與普通access_token的區別
網頁授權是通過Oauth2.0機制實現的,在用戶授權給公眾號后,公眾號可以獲取到一個網頁授權特有的接口調用憑據(網頁授權access_token),通過網頁授權access_token可以進行授權后接口調用,如獲取用戶基本信息。
其他的微信接口,需要通過 獲取access_token 接口來獲取普通的access_token

2、網頁授權的流程

網頁授權的流程
網頁授權的流程大致可以分為以下五步:

  • 生成網頁授權URL
  • 引導用戶進入授權頁面并同意授權,獲取code
  • 通過code換去網頁授權access_token
  • 如果需要,開發者可以刷新網頁授權access_token,避免過期
  • 通過網頁授權access_token和openid獲取用戶基本信息

2.1、生成網頁授權URL
接口地址

https://open.weixin.qq.com/connect/oauth2/authorize?
參數 是否必須 說明
appid 公眾號的唯一標識
redirect_uri 授權后重定向的回調鏈接地址,請使用urlencode對鏈接進行處理
response_type 返回類型,填code
scope snsapi_userinfo、snsapi_base
state 重定向后會帶上state參數,開發者可以填寫a-zA-Z0-9的參數值,最多128字節
wechat_redirect 無論直接打開還是做頁面302重定向時候,必須帶此參數

一個完整的網頁授權URL如下:

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxd91aa2e2fab6&redirect_uri=http%3A%2F%2Fwww.baidu.com&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect

當用戶點進入URL時就會進入授權界面,如下:

2.2、用戶同意授權后
如果用戶同意授權,頁面就會跳轉到redirect_uri

code:code作為換取access_token的票據,每次用戶授權帶上的code是不一樣的,code只能用一次,且5分鐘未使用自動過期。

跳轉到重定向地址后,開發者可以直接在請求參數中獲取到code。

2.3、code換取access_token

此處獲取到的access_token與其他接口需要使用到的access_token是不同的。如果網頁授權使用的scope是snsapi_base,則在此處獲取到access_token的同時,也獲取到了openid,snsapi_base的流程也到此結束。

請求地址

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

返回說明
請求正確時的返回數據

{ 
 "access_token":"ACCESS_TOKEN",    
 "expires_in":7200,    
 "refresh_token":"REFRESH_TOKEN",    
 "openid":"OPENID",    
 "scope":"SCOPE" 
}
參數 說明
access_token 網頁授權接口調用憑證
expires_in access_token接口調用憑證超時時間,單位(秒)
refresh_token 用戶刷新access_token需要用到的token
openid 用戶唯一標識
scope 用戶授權的作用域

示例代碼

String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
Map<String, String> params = new HashMap<String, String>();
params.put("APPID", appid);
params.put("SECRET", appsecret);
params.put("CODE", code);

JSONObject json = HttpUtil.get(StringFormat.format(url, params));
if(json != null){
    boolean isErr = json.containsKey("errcode");
    if(isErr){//請求失敗
        String errCode = json.getString("errcode");
        String errMsg = json.getString("errmsg");
    }else{
        String accessToken = json.getString("access_token");
        int expires = json.getInt("expires_in");
        String refreshToken = json.getString("refresh_token");
        String openid = json.getString("openid");
        String scope = json.getString("scope");
    }
}

2.4、驗證access_token是否有效
請求地址

https://api.weixin.qq.com/sns/auth?access_token=ACCESS_TOKEN&openid=OPENID 

參數說明

參數 是否必須 說明
access_token 網頁授權接口調用憑證
openid 用戶的唯一標識

返回說明
請求正確時的返回數據

{ "errcode":0,"errmsg":"ok"}

示例代碼

String url = "https://api.weixin.qq.com/sns/auth?access_token=ACCESS_TOKEN&openid=OPENID";
Map<String, String> params = new HashMap<String, String>();
params.put("ACCESS_TOKEN", access_token);
params.put("OPENID", openid);

JSONObject json = HttpUtil.get(StringFormat.format(url, params));
if(json != null){
    String errCode = json.getString("errcode");
    String errMsg = json.getString("errmsg");
}

2.5、刷新access_token(若有必要)

由于access_token有效期比較短,當access_token失效后,可以使用refresh_token進行刷新,refresh_token的有效期為30天。refresh_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 填寫獲取到的refresh_token參數

返回說明
請求正確時的返回數據

{ 
 "access_token":"ACCESS_TOKEN",  
 "expires_in":7200,   
 "refresh_token":"REFRESH_TOKEN",   
 "openid":"OPENID",   
 "scope":"SCOPE" 
}
參數 說明
access_token 網頁授權接口調用憑證
expires_in access_token接口調用憑證超時時間,單位(秒)
refresh_token 用戶刷新access_token需要用到的token
openid 用戶唯一標識
scope 用戶授權的作用域

示例代碼

String url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN";
Map<String, String> params = new HashMap<String, String>();
params.put("APPID", appid);
params.put("REFRESH_TOKEN", refresh_token);

JSONObject json = HttpUtil.get(StringFormat.format(url, params));
if(json != null){
    boolean isErr = json.containsKey("errcode");
    if(isErr){//請求失敗
        String errCode = json.getString("errcode");
        String errMsg = json.getString("errmsg");
    }else{
        String accessToken = json.getString("access_token");
        int expires = json.getInt("expires_in");
        String refreshToken = json.getString("refresh_token");
        String openid = json.getString("openid");
        String scope = json.getString("scope");
    }
}

2.6、獲取用戶信息(當scope為snsapi_userinfo)
請求地址

https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN 

參數說明

參數 是否必須 說明
access_token 網頁授權接口調用憑證
openid 用戶的唯一標識
lang 返回國家地區語言版本,zh_CN 簡體,zh_TW 繁體,en 英語

返回說明
請求正確時的返回數據

{
 "openid":"OPENID",  
 "nickname":"NICKNAME",   
 "sex":"1",   
 "province":"PROVINCE"   
 "city":"CITY",   
 "country":"COUNTRY",    
 "headimgurl":"http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ
4eMsv84eavHiaiceqxibJxCfHe/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正方形頭像),用戶沒有頭像時該項為空。若用戶更換頭像,原有頭像URL將失效。
privilege 用戶特權信息,json 數組,如微信沃卡用戶為(chinaunicom)
unionid 只有在用戶將公眾號綁定到微信開放平臺帳號后,才會出現該字段。

示例代碼

CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet("https://api.weixin.qq.com/sns/userinfo?access_token="+ access_token +"&openid="+ openid +"&lang="+ lang +"");
CloseableHttpResponse response = httpclient.execute(httpget);
JSONObject json = null;
try {
    int statusCode = response.getStatusLine().getStatusCode();
    if (statusCode == HttpStatus.SC_OK) {
        HttpEntity entity = response.getEntity();
        InputStream inStream = entity.getContent(); // 獲取請求參數數據
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outStream.write(buffer, 0, len);
        }
        
        outStream.close();
        inStream.close();
        String j = new String(outStream.toByteArray(), "utf-8");
        json = JSONObject.fromObject(j);
        System.out.println(result);
    }
} finally {
    response.close();
}
if(json != null){        
    
    boolean isErr = json.containsKey("errcode");
    if(isErr){//請求失敗
        System.out.println(json);
    }else{
        System.out.println(json);
    }
}

<a name="part2">二、根據openid獲取用戶信息</a>

使用此接口的前提是已有用戶的openid作為參數。
需要注意的是,此處用到的access_token與網頁授權中用到的access_token是完全不同的。此處access_token的獲取方式參見Java微信公眾號開發 - 開始接入

接口地址

https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN 

參數說明

參數 是否必須 說明
access_token 微信接口全局調用憑證
openid 用戶的唯一標識
lang 返回國家地區語言版本,zh_CN 簡體,zh_TW 繁體,en 英語

返回說明

請求正確時的返回數據

{
   "subscribe": 1, 
   "openid": "o6_bmjrPTlm6_2sgVt7hMZOPfL2M", 
   "nickname": "Band", 
   "sex": 1, 
   "language": "zh_CN", 
   "city": "廣州", 
   "province": "廣東", 
   "country": "中國", 
   "headimgurl":  "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4
eMsv84eavHiaiceqxibJxCfHe/0",
  "subscribe_time": 1382694957,
  "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"
  "remark": "",
  "groupid": 0,
  "tagid_list":[128,2]
}
參數 說明
subscribe 用戶是否訂閱該公眾號標識,值為0時,代表此用戶沒有關注該公眾號,拉取不到其余信息。
openid 用戶的標識,對當前公眾號唯一
nickname 用戶的昵稱
sex 用戶的性別,值為1時是男性,值為2時是女性,值為0時是未知
city 用戶所在城市
country 用戶所在國家
province 用戶所在省份
language 用戶的語言,簡體中文為zh_CN
headimgurl 用戶頭像,最后一個數值代表正方形頭像大?。ㄓ?、46、64、96、132數值可選,0代表640*640正方形頭像),用戶沒有頭像時該項為空。若用戶更換頭像,原有頭像URL將失效。
subscribe_time 用戶關注時間,為時間戳。如果用戶曾多次關注,則取最后關注時間
unionid 只有在用戶將公眾號綁定到微信開放平臺帳號后,才會出現該字段。
remark 公眾號運營者對粉絲的備注,公眾號運營者可在微信公眾平臺用戶管理界面對粉絲添加備注
groupid 用戶所在的分組ID(兼容舊的用戶分組接口)
tagid_list 用戶被打上的標簽ID列表

示例代碼

String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=";
url = url + access + "&openid=" + openId + "&lang=" + lang;
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet(url);
CloseableHttpResponse response = httpclient.execute(httpget);
JSONObject json = null;
try {
    int statusCode = response.getStatusLine().getStatusCode();
    if (statusCode == HttpStatus.SC_OK) {
        HttpEntity entity = response.getEntity();
        InputStream inStream = entity.getContent(); // 獲取請求參數數據
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outStream.write(buffer, 0, len);
        }
        
        outStream.close();
        inStream.close();
        String j = new String(outStream.toByteArray(), "utf-8");
        json = JSONObject.fromObject(j);
    }
} finally {
    response.close();
}
if(json != null){
    boolean isErr = json.containsKey("errcode");
    if(isErr){//請求失敗
        System.out.println(json);
    }else{
        System.out.println(json);
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容