微信公眾號獲取OpenId(使用者授權)(無需關注公眾號)以及獲取使用者基本資訊
上一個部落格也寫了微信公眾號獲取OpenId,但是現在這個和上一個有什麼區別呢。
其實呢,是差不多的,只是這個是通過使用者授權。
但是,又會有人問了,明明可以未授權獲取到使用者的openId,那我為什麼要讓使用者進行授權呢,我偷偷的獲取不就好了嗎?
好像很有道理,但是呢,那微信又幹嘛多一個介面呢?
其實,授權和未授權的區別就是:未授權的獲取方式是需要使用者關注你的公眾號的,但是,授權的情況下,只要使用者點選確定,使用者是不需要去關注你的公眾號的,你就可以獲取到使用者的openId以及使用者的基本資訊!!!
下面我講一下流程:其實呢,流程是和上一個部落格差不多的(請注意加紅部分)(最後我會附上我的Utils)
1.在公眾號後臺設定回撥的域名(大多情況下是你的專案)
開發-介面許可權-網頁賬號-使用者授權獲取使用者基礎資訊中修改
2.在頁面上訪問下面的網址
https://open.weixin.qq.com/connect/oauth2/authorize?appid=*******&redirect_uri=你回撥的地址&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect
上面的會返回到你回撥的地址?code=xxxxxxxxx
也就是說它會返回到你回撥的地址並且帶上code引數,一般情況下,回撥的地址設定為後端的action即可,然後就可以獲取到code了,當你獲取到code,已經成功了一大半。
3.根據code獲取到網頁授權access_token(此token不是基礎服務裡的access_token,請記得區分),返回值內就含有openId
4.然後根據openId以及access_token你就可以獲取使用者基本資訊了
下面我附上我的程式碼,已經封裝好了,你只需修改appId以及secret即可,還有記得匯入JSONObject的包哦,MyX509TrustManager就不貼了。
Utils:
WeChatAccessToken:package com.survey.common.wechat; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.ConnectException; import java.net.URL; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import com.survey.toysrus.model.WeChatAccessToken; import com.survey.toysrus.model.WechatUserinfo; import net.sf.json.JSONObject; import com.survey.toysrus.model.WechatAccessTokenCheck; public class weChatUtils { // 微信公眾號的appId以及secret private static String appId = ""; private static String secret = ""; // 獲取網頁授權access_token的Url,和基礎服務access_token不同,記得區分 private static String getAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code"; // 重新整理網頁授權access_token的Url,和基礎服務access_token不同,記得區分 private static String getRefreshAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN"; // 檢驗授權憑證access_token是否有效,和基礎服務access_token不同,記得區分 private static String checkAccessTokenUrl = "https://api.weixin.qq.com/sns/auth?access_token=ACCESS_TOKEN&openid=OPENID"; // 獲取使用者資訊的Url private static String getWXUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN"; /** * 根據code獲取到網頁授權access_token * * @author Shen * @param code * 微信回撥後帶有的引數code值 */ public static WeChatAccessToken getAccessToken(String code) { String url = weChatUtils.getAccessTokenUrl.replace("APPID", weChatUtils.appId).replace("SECRET", secret) .replace("CODE", code); JSONObject jsonObj=JSONObject.fromObject(httpRequest(url, "POST", null)); return (WeChatAccessToken) JSONObject.toBean(jsonObj,WeChatAccessToken.class); } /** * 根據在獲取accessToken時返回的refreshToken重新整理accessToken * * @author Shen * @param refreshToken */ public static WeChatAccessToken getRefreshAccessToken(String refreshToken) { String url = weChatUtils.getRefreshAccessTokenUrl.replace("APPID", weChatUtils.appId).replace("REFRESH_TOKEN", refreshToken); JSONObject jsonObj=JSONObject.fromObject(httpRequest(url, "POST", null)); return (WeChatAccessToken) JSONObject.toBean(jsonObj,WeChatAccessToken.class); } /** * 獲取微信使用者資訊 * * @author Shen * @param openId * 微信標識openId * @param accessToken * 微信網頁授權accessToken */ public static WechatUserinfo getWXUserInfoUrl(String openId, String accessToken) { String url = weChatUtils.getWXUserInfoUrl.replace("OPENID", openId).replace("ACCESS_TOKEN", accessToken); JSONObject jsonObj=JSONObject.fromObject(httpRequest(url, "POST", null)); return (WechatUserinfo) JSONObject.toBean(jsonObj,WechatUserinfo.class); } /** * 檢驗授權憑證accessToken是否有效 * * @author Shen * @param openId * @param accessToken */ public WechatAccessTokenCheck checkAccessToken(String openId, String accessToken) { String url = weChatUtils.checkAccessTokenUrl.replace("OPENID", openId).replace("ACCESS_TOKEN", accessToken); JSONObject jsonObj=JSONObject.fromObject(httpRequest(url, "POST", null)); return (WechatAccessTokenCheck) JSONObject.toBean(jsonObj,WechatAccessTokenCheck.class); } /** * get或者post請求 * * @author Shen * @param requestUrl * @param requestMethod * GET or POST 需要大寫* * @param outputStr * @return */ public static String httpRequest(String requestUrl, String requestMethod, String outputStr) { StringBuffer buffer = new StringBuffer(); try { // 建立SSLContext物件,並使用我們指定的信任管理器初始化 TrustManager[] tm = { new MyX509TrustManager() }; SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE"); sslContext.init(null, tm, new java.security.SecureRandom()); // 從上述SSLContext物件中得到SSLSocketFactory物件 SSLSocketFactory ssf = sslContext.getSocketFactory(); URL url = new URL(requestUrl); HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection(); httpUrlConn.setSSLSocketFactory(ssf); httpUrlConn.setDoOutput(true); httpUrlConn.setDoInput(true); httpUrlConn.setUseCaches(false); // 設定請求方式(GET/POST) httpUrlConn.setRequestMethod(requestMethod); if ("GET".equalsIgnoreCase(requestMethod)) httpUrlConn.connect(); // 當有資料需要提交時 if (null != outputStr) { OutputStream outputStream = httpUrlConn.getOutputStream(); // 注意編碼格式,防止中文亂碼 outputStream.write(outputStr.getBytes("UTF-8")); outputStream.close(); } // 將返回的輸入流轉換成字串 InputStream inputStream = httpUrlConn.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8"); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String str = null; while ((str = bufferedReader.readLine()) != null) { buffer.append(str); } bufferedReader.close(); inputStreamReader.close(); // 釋放資源 inputStream.close(); inputStream = null; httpUrlConn.disconnect(); } catch (ConnectException ce) { System.out.println("Weixin server connection timed out." + ce.getMessage()); } catch (Exception e) { System.out.println("https request error:{}" + e.getMessage()); } return buffer.toString(); } }
package com.survey.toysrus.model;
/**
* 此AccessToken不是基礎模組的AccessToken,是一個特殊的網頁授權access_token,請記得區分
*
* @author Shen date : 2018-01-22
*/
public class WeChatAccessToken {
/**
* 直接引用了微信的返回值,不使用駝峰等命名 access_token
* 網頁授權介面呼叫憑證,注意:此access_token與基礎支援的access_token不同 expires_in
* access_token介面呼叫憑證超時時間,單位(秒) refresh_token 使用者重新整理access_token openid
* 使用者唯一標識,請注意,在未關注公眾號時,使用者訪問公眾號的網頁,也會產生一個使用者和公眾號唯一的OpenID scope
* 使用者授權的作用域,使用逗號(,)分隔
*/
private String access_token;
private int expires_in;
private String refresh_token;
private String openid;
private String scope;
// 額外的資訊
private int errcode;
private String errmsg;
public int getErrcode() {
return errcode;
}
public void setErrcode(int errcode) {
this.errcode = errcode;
}
public String getErrmsg() {
return errmsg;
}
public void setErrmsg(String errmsg) {
this.errmsg = errmsg;
}
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public int getExpires_in() {
return expires_in;
}
public void setExpires_in(int expires_in) {
this.expires_in = expires_in;
}
public String getRefresh_token() {
return refresh_token;
}
public void setRefresh_token(String refresh_token) {
this.refresh_token = refresh_token;
}
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
}