您的位置:首页 > 移动开发 > 微信开发

微信OAuth授权获取用户OpenId-JAVA(个人经验)

2014-07-21 16:51 856 查看



个人小程序。微信扫一扫查看哦。谢谢支持

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[/code] 
{
"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 [b] 请先留言说明您!否则不加![/b]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  OpenID OAuth