微信OAuth授权获取用户OpenId-JAVA(个人经验)
最新博文在这里:https://my.oschina.net/xshuai/blog/293458
带评论昵称 才同意加QQ
鉴于老是有人问我。就更新一下了。
更新时间 2016年10月18日
修改了测试号权限不足导致授权获取信息抛异常的问题。
服务器暂时有问题。想查看效果。在周一到周五10:00-17:00查看即可。
可以扫描关注查看效果。这个是测试号。服务器有限。不要恶意攻击
http://mp.weixin.qq.com/wiki这个是官网的接口文档
微信授权获取用户openid-JAVA
开发微信测试需要用到的代码和jar包都在里面 包括核心代码
源码在这里。https://zb.oschina.net/market/opus/1444646_161 维护服务器。一份5元。自愿购买
链接: https://zb.oschina.net/market/opus/1444646_161
注意:授权把回调域名配置了。(只需要域名就行 例如:www.baidu.com)
没有配置回调域名有问题就别问我了。
拉取用户信息(需scope为 snsapi_userinfo)
本作者是用菜单的方式引导用户进入点击获取信息的。不会创建菜单的自己去看官网API。或者搜索教程。先把官网文档稍微看下。知道自己需要配置的域名。等一些参数。点个赞都不给。就什么问题也问。还有。我工作不是专门做微信这方面的。我也需要忙我自己的工作内容。
如果网页授权作用域为snsapi_userinfo,则此时开发者可以通过access_token和openid拉取用户信息了。
前提设置一个菜单调用授权接口的URL获取code
修改相应的参数后的链接(只是一个例子) 创建一个view类型的菜单。url如下:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx2d39c6c31ed5f199&redirect_uri=http://zxshuai.imwork.net/weixin/oauth.do &response_type=code&scope=snsapi_userinfo&state=123#wechat_redirect
截图示意(最后一张上传于2016年10月18日)
第一步:用户同意授权,获取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取得openId
*
* @param appid 公众号的唯一标识
* @param secret 公众号的appsecret密钥
* @param code code为换取access_token的票据
* @return
*/public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//参数
String code = request.getParameter("code");
if(null != code && !"".equals(code)){
log.info("==============[OAuthServlet]获取网页授权code不为空,code="+code);
//根据code换取openId
OAuthInfo oa = WeixinUtil.getOAuthOpenId(Constants.appId,Constants.appSecret,code);
UserInfo info = WeixinUtil.getUserInfo(oa.getAccessToken(), oa.getOpenId());
if(!"".equals(oa) && null != oa){
request.setAttribute("openid", oa.getOpenId());
request.setAttribute("nickname", info.getNickname());
request.getRequestDispatcher("/index.jsp").forward(request, response);
}else{
log.info("==============[OAuthServlet]获取网页授权openId失败!");
}
}else{
log.info("==============[OAuthServlet]获取网页授权code失败!");
}
}
替换相应的APPID APPSECRET SCOPE
第二步:通过code换取网页授权access_token 这里的access_token与基础获取的access_token不同
获取code后,请求以下链接获取access_token:
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
具体做法与上面基本一致。更换相对应的值。需要注意的是code可以写一个Servlet获取。String code = request.getParameter("code");get/post都可以。
这样子就会返回一下json格式数据
{
"access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE"
}
具体代码如下。获取的code换取的access_token
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code;
public static OAuthInfo getOAuthOpenId(String appid, String secret, String code ) {
OAuthInfo oAuthInfo = null;
String o_auth_openid_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code;";
String requestUrl = o_auth_openid_url.replace("APPID", appid).replace("SECRET", secret).replace("CODE", code);
JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
//oAuthInfo是作者自己把那几个属性参数写在一个类里面了。
// 如果请求成功
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;
}
根据上面代码获取的access_token openid 然后再请求获取userinfo的接口。就能得到微信用户的所有信息了。
具体返回如下。获取用户信息代码不再写。
请求获取用户信息的接口地址
{"sex":1,
"nickname":"小帅",
"privilege":[],
"province":"北京",
"openid":"o2VKNju8JqCeGVoEWJ1S8Ue_up8E",
"language":"zh_CN",
"headimgurl":"http://wx.qlogo.cn/mmopen/ribqo6CmxxhyfrokJWjVAedZzl590B4HAbribNVS3CQvplHp8KgmH1kIfqpM4Ek5uTr0lFW8yMDjfZrWLtvjjKLXu1H5icSfRBl/0",
"country":"中国",
"city":"海淀"}
这就获取到用户的openid。应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息)我自己用的作用域为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
替换链接里面的大写字母的信息为你自己公众号的。state可以不改。
写一个Servlet专门接收传递过来的code。进行相应的操作。
获取用户基本信息接口
接口调用请求说明
http请求方式: GET
https://api.weixin.qq.com/cgi-bin/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
最新更新。2016年9月9日 鉴于好多人只能获取到openid但拿不到用户信息。那就更新一下。
通过openid是可以直接再去获取到用户信息的。前提也是用户关注了公众号
{
"subscribe": 1,
"openid": "osdhfjkdsfh78sdjkljljkkj",
"nickname": "小帅帅丶",
"sex": 1,
"language": "zh_CN",
"city": "北京",
"province": "北京",
"country": "中国",
"headimgurl": "http://wx.qlogo.cn/mmopen/Kkv3HV30gbEZmoo1rTrP4UjRRqzsibUjT9JClPJy3gzo0NkEqzQ9yTSJzErnsRqoLIct5NdLJgcDMicTEBiaibzLn34JLwficVvl6/0",
"subscribe_time": 1389684286
}
参数说明
参数 |
说明 |
---|---|
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"}
具体代码 获取到openid代码在上面。都不愿意资助一下。就不要加QQ咨询所有的问题。
/**
* 网页授权获取用户信息
* @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"));
//等一系列的信息
} catch (JSONException e) {
userInfo = null;
// 获取token失败
log.error("网页授权获取openId失败 errcode:{} errmsg:{}", jsonObject
.getInt("errcode"), jsonObject.getString("errmsg"));
}
}
return userInfo;
}
}
1.OAuthServlet 对code进行access——token的验证
2.一个Servlet的方法调用接口地址。得到相应code。
3.OAuthInfo 返回数据相应的参数的PO类。set/get方法
4.WeiXinUtil添加一个方法 publicOAuth getOAuthInfo(String appid, String secret, String code)得到json格式。并使用JSONObject读取出自己想要的数据。
https://open.weixin.qq.com/ 这个是授权登陆自己网站的和我的这个是有区别的。
http://www.oschina.net/code/snippet_1444646_47662 HTTPREQUEST方法、
个人博客 http://my.oschina.net/xshuai/blog
- TensorFlow强化学习入门(4)——深度Q网络(DQN)及其扩展
- 3.请求安全-- 如何验证请求的唯一性
- 2.请求安全-- MD5的必要性以及实际应用场景
- 1.请求安全-- 一个简单的 单设备登录 单点登录
- phalapi-进阶篇3(自动加载和拦截器)
- phalapi-进阶篇2(DI依赖注入和单例模式)
- 基于PhalApi的DB集群拓展 V0.1bate
- phalapi-进阶篇1(Api,Domain,和Model)
- 你不知道的Javascript:有趣的setTimeout
- phalapi-入门篇5(数据库操作和Model层)
- HTML5.2新特性解读
- phalapi-入门篇6(小技巧和浅谈API适用范围以及入门篇总结)
- phalapi-入门篇2(把它玩起来)
- phalapi-入门篇3(请求和返回)
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 【从0到1学算法】快速排序
- 每天一道前端面试题:左边宽度固定,右边⾃适应
- 几个IDEA高级调试技巧,完全是bug杀手啊
- Spring Security 实战干货:从零手写一个验证码登录
- LaTex学习笔记
- 聊聊dubbo-go的metricsFilter
- 配置.gitignore
- 同样的GitHub包你就下载失败
- Linux编译C++
- 聊聊dubbo-go的tracingFilter
- JDBC - 第一天
- JavaSE - 排序算法
- JavaSE - 多态的本质
- Result Maps collection does not contain value for XXX 错误
- 当端口被占用如何kill占用端口的进程