微信OAuth授權獲取用戶OpenId-JAVA(個人經驗) 頂 原 薦

 

個人小程序。微信掃一掃查看哦。謝謝支持

https://open.weixin.qq.com/ 這個是授權登陸自己網站的和我的這個是有區別的。

帶評論暱稱  才同意加QQ

‍鑑於老是有人問我。就更新一下了。

更新時間 2018年08月06日

測試公衆號地址:https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index

可以掃描關注查看效果。這個是測試號。

http://mp.weixin.qq.com/wiki這個是官網的接口文檔

微信授權獲取用戶openid-JAVA

開發微信測試需要用到的代碼和jar包都在裏面  包括核心代碼

源碼一元一份(需要請加QQ:783021975)。語言爲Java(Servlet) 實現功能 自定義菜單、自動回覆、回調配置、OAuth接口實現、JSSDK實現

注意:授權把回調域名配置了。(只需要域名就行 例如:www.baidu.com)

沒有配置回調域名有問題就別問我了。

JSSDK域名配置:

拉取用戶信息(需scope爲 snsapi_userinfo)

本作者是用菜單的方式引導用戶進入點擊獲取信息的。不會創建菜單的自己去看官網API。或者搜索教程。先把官網文檔稍微看下。知道自己需要配置的域名。等一些參數。點個贊都不給。就什麼問題也問。還有。我工作不是專門做微信這方面的。我也需要忙我自己的工作內容。

如果網頁授權作用域爲snsapi_userinfo,則此時開發者可以通過access_token和openid拉取用戶信息了。

前提設置一個菜單調用授權接口的URL獲取code 方式很多。不一定非得是菜單引導。只要是如下地址就行。

修改相應的參數後的鏈接(只是一個例子) 創建一個view類型的菜單。url如下:

 https://open.weixin.qq.com/connect/oauth2/authorize?appid=自己賬戶的appid&redirect_uri=http://替換成自己的域名/wx/servlet&response_type=code&scope=snsapi_userinfo&state=123#wechat_redirect

CommonButton btn11 = new CommonButton();
btn11.setName("授權測試");
btn11.setType("view");
//這裏替換成自己的域名服務器信息 http://xxx.com/wx/servlet  wx爲項目名稱。這個根據自己的實際情況來。servlet爲授權方法路徑 如果需要改動請修改web.xml後再改動這裏
String redirect_uri= "https://www.xsshome.cn/wx/servlet";
String redirect_uriencode= URLEncoder.encode(redirect_uri,"utf-8");
String oauth_url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="+Constants.appId+"&redirect_uri="+redirect_uriencode+"&response_type=code&scope=snsapi_base&state=HEAT#wechat_redirect";
btn11.setUrl(oauth_url);

截圖示意

通過獲取CODE得到OPENID請求獲取用戶基本信息(UnionID機制)接口得到相關信息

第一步:用戶同意授權,獲取code 引導用戶進入授權的URL 修改一些參數

在確保微信公衆賬號擁有授權作用域(scope參數)的權限的前提下(服務號獲得高級接口後,默認帶有scope參數中的snsapi_base和snsapi_userinfo),引導關注者打開如下頁面:本作者用菜單的方式引導用戶點擊進入。

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

我的代碼如下:一個Servlet請求 獲取code + 用戶基本信息

/**
	 * 回調的方法 獲取到code 再根據相關參數獲取用戶信息
	 */
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//接受參數
		String code = request.getParameter("code");
		String scope = request.getParameter("scope");
		AccessTokenFactory accessToken = new AccessTokenFactory();
		log.info("==============[OAuthServlet]獲取網頁授權code="+code+"==============[OAuthServlet]獲取網頁跳轉權限="+scope);
		HttpSession session = request.getSession();
		String openId = session.getAttribute("openid")==null?"":session.getAttribute("openid").toString();
		if(null==openId||openId.equals("")){
			if(null != code && !"".equals(code)){
				log.info("==============[OAuthServlet]獲取網頁授權code不爲空,code="+code);
				//第一步根據code換取openId 這一步拿到openid
				OAuthInfo oa = WeixinUtil.getOAuthOpenId(Constants.appId,Constants.appSecret,code);
               //第二步根據獲取的openid 再用https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET接口獲取token 換取微信用戶基本信息
				UserInfo info = WeixinUtil.getUserInfo(accessToken.getAccessToken().getToken(), oa.getOpenId());
				if(!"".equals(oa) && null != oa){
					 log.info("==============[OAuthServlet]獲取網頁授權openID="+oa.getOpenId());
					 request.setAttribute("openid", oa.getOpenId());
                      //保存到session 防止用戶刷新頁面導致失敗
					 session.setAttribute("openid", oa.getOpenId());
					 if(null!=info){
					 request.setAttribute("nickname", info.getNickname());
					 request.setAttribute("headimgurl", info.getHeadimgurl());
					 }
					 request.getRequestDispatcher("/index.jsp").forward(request, response);
				}else{
					log.info("==============[OAuthServlet]獲取網頁授權openId失敗!");
				}
			}else{
				log.info("==============[OAuthServlet]獲取網頁授權code失敗!");
			}
		}else{
			UserInfo info = WeixinUtil.getUserInfo(accessToken.getAccessToken().getToken(),openId);
			if(null!=info){
				 request.setAttribute("openid", openId);
				 session.setAttribute("openid", openId);
				 request.setAttribute("nickname", info.getNickname());
				 request.setAttribute("headimgurl", info.getHeadimgurl());
			}
			request.getRequestDispatcher("/index.jsp").forward(request, response);
		}
	}

替換相應的APPID APPSECRET SCOPE

第一步:通過code獲取openid

具體代碼如下。code獲取 openid值

/**
	 * 網頁授權,根據code取得openId
	 * @param appid 公衆號的唯一標識
	 * @param secret 公衆號的appsecret密鑰
	 * @param code code爲換取access_token的票據          
	 * @return 
	 */
	public static OAuthInfo getOAuthOpenId(String appid, String secret, String code ) {
		OAuthInfo oAuthInfo = null;
		String requestUrl = o_auth_openid_url.replace("APPID", appid).replace("SECRET", secret).replace("CODE", code);
		System.out.println("==============requestUrl:"+requestUrl+"==============");

		JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
		System.out.println("==============jsonObject:"+jsonObject+"==============");
		
		// 如果請求成功
		if (null != jsonObject) {
			try {
				oAuthInfo = new OAuthInfo();
				oAuthInfo.setAccessToken(jsonObject.getString("access_token"));
				oAuthInfo.setExpiresIn(jsonObject.getInt("expires_in"));
				oAuthInfo.setRefreshToken(jsonObject.getString("refresh_token"));
				oAuthInfo.setOpenId(jsonObject.getString("openid"));
				oAuthInfo.setScope(jsonObject.getString("scope"));
			} catch (JSONException e) {
				oAuthInfo = null;
				// 獲取token失敗
				log.error("網頁授權獲取openId失敗 errcode:{} errmsg:{}", jsonObject
						.getInt("errcode"), jsonObject.getString("errmsg"));
			}
		}
		return oAuthInfo;
	}

這樣子就會返回以下son格式數據

{
    "expiresIn": 7200, 
    "openId": "o2VKNju8JqCeGVoEWJ1S8Ue_up8E", 
    "scope": "snsapi_base", 
    "accessToken": "12_cAJ8dRiI7rkW-_1hqZyaaAO5lYNX9N9Hm_BUesKOL9Mg-F7P4Ie66l6Uypf-vl-DX1SgjP8TYVet_x13kc2IQQHaXAngilSu-0RVq_s6uGQ", 
    "refreshToken": "12_dwEXNtSpeONSWMZrHjhPPCtpyRECSOzB43H8BEJi3JVrTFwcdmSJRLUhjw31rYuXQ181EGpyEciQ-Bf_fEuzkt8r2_dk0BwHTjeTlqZEizY"
}

第二步:通過openid獲取用戶基本信息  這裏的access_token爲基礎接口獲取的access_token

獲取access_token,access_token是公衆號的全局唯一接口調用憑據
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

 

{
    "expiresIn": 7200, 
    "openId": "o2VKNju8JqCeGVoEWJ1S8Ue_up8E", 
    "scope": "snsapi_base", 
    "accessToken": "12_cAJ8dRiI7rkW-_1hqZyaaAO5lYNX9N9Hm_BUesKOL9Mg-F7P4Ie66l6Uypf-vl-DX1SgjP8TYVet_x13kc2IQQHaXAngilSu-0RVq_s6uGQ", 
    "refreshToken": "12_dwEXNtSpeONSWMZrHjhPPCtpyRECSOzB43H8BEJi3JVrTFwcdmSJRLUhjw31rYuXQ181EGpyEciQ-Bf_fEuzkt8r2_dk0BwHTjeTlqZEizY"
}

根據上面代碼獲取的access_token  openid 然後再請求獲取userinfo的接口。就能得到微信用戶的所有信息了。

//獲取用戶信息接口
public static String userinfo_url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";

獲取用戶信息代碼如下。

/**
	 * 根據openid獲取用戶信息
	 * @param access_token 授權得到的access_token
	 * @param openid  授權獲取的openid
	 * @return
	 */
	public static UserInfo getUserInfo(String access_token,String openid ) {
		UserInfo userInfo = null;
		String requestUrl = userinfo_url.replace("ACCESS_TOKEN", access_token).replace("OPENID", openid);
		System.out.println("==============requestUrl:"+requestUrl+"==============");

		JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
		System.out.println("==============jsonObject:"+jsonObject+"==============");
		
		// 如果請求成功
		if (null != jsonObject) {
			try {
				userInfo = new UserInfo();
				userInfo.setNickname(jsonObject.getString("nickname"));
				userInfo.setHeadimgurl(jsonObject.getString("headimgurl"));
			} catch (JSONException e) {
				userInfo = null;
				// 獲取token失敗
				log.error("網頁授權獲取openId失敗 errcode:{} errmsg:{}", jsonObject
						.getInt("errcode"), jsonObject.getString("errmsg"));
			}
		}
		return userInfo;
	}

具體返回如下

{
    "country": "中國", 
    "unionid": "oUmIot2Yo2Mb_8fVW3UVw9AW1w4Y", 
    "qr_scene": 0, 
    "subscribe": 1, 
    "city": "海淀", 
    "openid": "o2VKNju8JqCeGVoEWJ1S8Ue_up8E", 
    "tagid_list": [ ], 
    "sex": 1, 
    "groupid": 0, 
    "language": "zh_CN", 
    "remark": "", 
    "subscribe_time": 1533536600, 
    "province": "北京", 
    "subscribe_scene": "ADD_SCENE_QR_CODE", 
    "nickname": "小帥丶", 
    "headimgurl": "http://thirdwx.qlogo.cn/mmopen/Lj9cibm6LlmjNM8CGSYKuMQiaD4tTPwUjD7zVkkn2u6kFqv4zDwtcfHFntHyxtjjmXeicLDqVqQB42vUukxB5Mia8HgoV94gsN02/132", 
    "qr_scene_str": ""
}

這就獲取到用戶的基本信息,以上結果只適合用戶關注了公衆號信息獲取。

並非https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842網址中的流程。後續補充文檔中流程的獲取步驟

參數說明

參數 說明
subscribe 用戶是否訂閱該公衆號標識,值爲0時,代表此用戶沒有關注該公衆號,拉取不到其餘信息。
openid 用戶的標識,對當前公衆號唯一
nickname 用戶的暱稱
sex 用戶的性別,值爲1時是男性,值爲2時是女性,值爲0時是未知
city 用戶所在城市
country 用戶所在國家
province 用戶所在省份
language 用戶的語言,簡體中文爲zh_CN
headimgurl 用戶頭像,最後一個數值代表正方形頭像大小(有0、46、64、96、132數值可選,0代表640*640正方形頭像),用戶沒有頭像時該項爲空
subscribe_time 用戶關注時間,爲時間戳。如果用戶曾多次關注,則取最後關注時間

錯誤時微信會返回錯誤碼等信息,JSON數據包示例如下(該示例爲AppID無效錯誤):

{"errcode":40013,"errmsg":"invalid appid"}                          

1.OAuthServlet 對code進行access——token的驗證

2.一個Servlet的方法調用接口地址。得到相應code。

3.OAuthInfo 返回數據相應的參數的PO類。set/get方法

4.WeiXinUtil添加一個方法 public OAuth  getOAuthInfo(String appid, String secret, String code)得到json格式。並使用JSONObject讀取出openid數據。

5.根據openid + token 獲取已關注公衆號的用戶的基本信息

官方網頁授權OAuth 獲取CODE 換取OPENID 換取用戶基本信息流程

基本與上面一致。爲了能獲取用戶更多信息。scope建議爲 snsapi_userinfo。代碼如下:

package cn.zxs.weixin.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.sf.json.JSONObject;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import cn.zxs.weixin.util.Constants;
import cn.zxs.weixin.weixin.pojo.OAuthInfo;
import cn.zxs.weixin.weixin.pojo.UserInfo;
import cn.zxs.weixin.weixin.util.WeixinUtil;

public class OAuthServletOff extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private Log logger = LogFactory.getLog(getClass());
	//走POST方式
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
			this.doPost(request, response);
	}
	//OAuth 官方流程
	/**
	 * 1 第一步:用戶同意授權,獲取code
	 * 2 第二步:通過code換取網頁授權access_token
	 * 3 第三步:刷新access_token(如果需要)
	 * 4 第四步:拉取用戶信息(需scope爲 snsapi_userinfo)
	 */
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		HttpSession session = request.getSession();
		//獲取微信返回的code參數
		//第一步:用戶同意授權,獲取code
		String code = request.getParameter("code");
		//獲取session是否有存在的openid
		logger.info("[OAuthServletOff]獲取網頁授權code="+code);
		String openId = session.getAttribute("openid")==null?"":session.getAttribute("openid").toString();
		if(null==openId||openId.equals("")){
		//第二步:通過code換取網頁授權access_token
		OAuthInfo oAuthInfo = WeixinUtil.getOAuthOpenId(Constants.appId,Constants.appSecret,code);
		logger.info("通過code換取網頁授權access_token接口返回的內容"+JSONObject.fromObject(oAuthInfo));
		if(null!=oAuthInfo){
			request.setAttribute("openid", oAuthInfo.getOpenId());
			//如果第一次獲取openid 則放在session裏面 防止刷新頁面導致提示code使用過錯誤
			session.setAttribute("openid", oAuthInfo.getOpenId());
			session.setAttribute("refresh_token", oAuthInfo.getRefreshToken());
			//第四步:拉取用戶信息(需scope爲 snsapi_userinfo) 第三步非必須步驟哦
			UserInfo userInfo = WeixinUtil.getOAuthUserInfo(oAuthInfo.getAccessToken(), oAuthInfo.getOpenId());
			if(null!=userInfo){
				 request.setAttribute("nickname", userInfo.getNickname());
				 request.setAttribute("headimgurl", userInfo.getHeadimgurl());
				 request.getRequestDispatcher("/index.jsp").forward(request, response);
			}else{
				logger.info("[OAuthServlet]獲取用戶信息失敗!");
				 request.getRequestDispatcher("/index.jsp").forward(request, response);
			}
		} else {
			logger.info("[OAuthServlet]獲取網頁授權openId失敗!");
			request.getRequestDispatcher("/index.jsp").forward(request, response);
		}
		}else{
			//第三步:刷新access_token(如果需要)
			String refresh_token = session.getAttribute("refresh_token").toString();
			OAuthInfo oAuthInfo = WeixinUtil.getRefreshTokenInfo(Constants.appId,refresh_token);
			if(null!=oAuthInfo){
				request.setAttribute("openid", oAuthInfo.getOpenId());
				//如果第一次獲取openid 則放在session裏面 防止刷新頁面導致提示code使用過錯誤
				session.setAttribute("openid", oAuthInfo.getOpenId());
				session.setAttribute("refresh_token", oAuthInfo.getRefreshToken());
				//第四步:拉取用戶信息(需scope爲 snsapi_userinfo) 第三步非必須步驟哦
				UserInfo userInfo = WeixinUtil.getOAuthUserInfo(oAuthInfo.getAccessToken(), oAuthInfo.getOpenId());
				if(null!=userInfo){
					 request.setAttribute("nickname", userInfo.getNickname());
					 request.setAttribute("headimgurl", userInfo.getHeadimgurl());
					 request.getRequestDispatcher("/index.jsp").forward(request, response);
				}else{
					logger.info("[OAuthServlet]獲取用戶信息失敗!");
					 request.getRequestDispatcher("/index.jsp").forward(request, response);
				}
			} else {
				logger.info("[OAuthServlet]獲取網頁授權openId失敗!");
				request.getRequestDispatcher("/index.jsp").forward(request, response);
			}
		}
	}
}

新加的2個方法 一個獲取微信用戶信息。一個是刷新操作獲取用戶信息(需要用到(refresh_token)

	//獲取用戶信息接口
	public static String OAUTH_USERINFO = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
	/**
	 * 網頁授權獲取用戶信息
	 * @param access_token 授權得到的access_token
	 * @param openid  授權獲取的openid
	 * @return
	 */
	public static UserInfo getOAuthUserInfo(String access_token,String openid) {
		UserInfo userInfo = null;
		String requestUrl = OAUTH_USERINFO.replace("ACCESS_TOKEN", access_token).replace("OPENID", openid);
		JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
		log.info("官方授權獲取用戶信息接口返回的內容"+jsonObject);
		// 如果請求成功
		if (null != jsonObject) {
			try {
				userInfo = new UserInfo();
				userInfo.setNickname(jsonObject.getString("nickname"));
				userInfo.setHeadimgurl(jsonObject.getString("headimgurl"));
				userInfo.setOpenid(jsonObject.getString("openid"));
			} catch (JSONException e) {
				userInfo = null;
				log.error("網頁授權獲取用戶信息失敗 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
			}
		}
		return userInfo;
	}
	//刷新token
	public static String REFRESH_TOKEN_URL="https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN";
	/**
	 * 刷新獲取的token
	 * @param appid
	 * @param refresh_token
	 * @return
	 */
	public static OAuthInfo getRefreshTokenInfo(String appid,String refresh_token) {
		OAuthInfo oAuthInfo = null;
		String requestUrl = REFRESH_TOKEN_URL.replace("APPID", appid).replace("REFRESH_TOKEN", refresh_token);
		JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
		log.info("getRefreshTokenInfo"+JSONObject.fromObject(jsonObject));
		// 如果請求成功
		if (null != jsonObject) {
			try {
				oAuthInfo = new OAuthInfo();
				oAuthInfo.setAccessToken(jsonObject.getString("access_token"));
				oAuthInfo.setExpiresIn(jsonObject.getInt("expires_in"));
				oAuthInfo.setRefreshToken(jsonObject.getString("refresh_token"));
				oAuthInfo.setOpenId(jsonObject.getString("openid"));
				oAuthInfo.setScope(jsonObject.getString("scope"));
			} catch (JSONException e) {
				oAuthInfo = null;
				log.error("網頁授權獲取openId失敗 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
			}
		}
		return oAuthInfo;
	}

https://open.weixin.qq.com/ 這個是授權登陸自己網站的和我的這個是有區別的。

http://www.oschina.net/code/snippet_1444646_47662 HTTPREQUEST方法、

 

個人微博 http://weibo.com/u/2205636212 

個人博客 http://my.oschina.net/xshuai/blog 

微信/QQ  783021975 請先留言說明您!否則不加!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章