個人小程序。微信掃一掃查看哦。謝謝支持
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 請先留言說明您!否則不加!