1. 程式人生 > >微信公眾號獲取OpenId(使用者授權)(無需關注公眾號)以及獲取使用者基本資訊

微信公眾號獲取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:

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();
	}

}
WeChatAccessToken:
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;
	}

}