Java面向微信接口开发--授权网页获取用户信息
背景:最近公司业务与微信公众号有关,面向微信接口开发
原文地址: https://blog.csdn.net/rongxiang111/article/details/78765514
1.开发语言使用Java
2.使用微信接口测试账号进行本地测试
3.使用natapp(原ngrok)将本地地址映射到外网地址实现微信公众号的本地调试
申请微信公众平台接口测试账号
打开上面的链接地址后,直接用自己的微信扫一下就可以直接登录了。
登录成功后,如下显示:
公网配置前的准备
在我们本地测试的时候,需要将我们的本地地址映射到公网,我们使用一个免费且非常方便的工具:natapp。下面的地址是natapp的官网和natapp的使用教程:
natapp官网
NATAPP 1分钟快速新手图文教程
大家可以根据上面的教程来一步步做,我下面还会重新介绍一遍(因为在我跟着官网的教程做的时候后来因为自己的原因遇到了一些小问题)。
免费隧道配置
先注册,注册成功后登录。
注意上图:本地端口必须是要填8080的(这个购买后也是可以再修改的),因为微信公众平台接口的调用仅支持80。开发之间建议阅读微信公众平台技术文档。
隧道购买成功后,在我的隧道中就可以看到已拥有的隧道:
客户端下载
我们访问到natapp的客户端下载,下载natapp客户端:
下载后,解压,会有一个natapp.exe的文件。
运行natapp
在运行natapp之前需要先配置,详细教程参考:使用本地配置文件config.ini。config.ini内容:
在这两个文件的目录下,打开cmd命令窗口,输入:
natapp -authtoken=你的authtoken
回车,运行成功后是如下界面:
- Tunnel Status Online 代表链接成功
- Version 当前客户端版本,如果有新版本,会有提示
- Forwarding 当前穿透 网址 或者端口
- Web Interface 是本地Web管理界面,可在隧道配置打- 开或关闭,仅用于web开发测试
- Total Connections 总连接数
- Avg Conn Time 0.00ms 这里不代表,不代表,不代表 延时,需要注意!
这两个都是可以访问的,区别就是使用natapp是将本地映射到公网上了,别人也可以访问,但是别人就不能访问你的127.0.0.1:8080
。
注意:用
http://xxx.natappfree.cc
访问的时候运行natapp的cmd窗口要开着,也就是得运行着natapp,不然是找不到公网映射的。
这样我们的微信本地开发调试环境就配好了。
前提:需要申请认证的微信公众号;获取对应的APPID和APPSECRET;并且还需要获取到用户信息权限(点击“修改“添加服务器的域名地址),前期工作安装测试账号为例给大家展示下:
1)、公众测试账号获取
访问上面的连接,选择“接口测试号申请”获得直接打开http://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index通过微信客户端扫码登录即可登录。
登录完即可获取到一个测试公众账号的信息。主要有appId和appsecret两个参数,这将唯一标示一个公众号,并且需要将他们作为参数获取用户的信息。
2)、关注公众号
用户只有关注了这个公众号了,才能通过打开有公众号信息的链接去授权第三方登录,并获取用户信息的操作。故我们还需要用我们的微信关注微信号,操作如下:
还是刚刚那个登录成功后跳转的页面,我们可以看到,该页面有一个二维码,我们可以通过扫描该二维码进行关注,关注成功在右边的“用户列表”会多一个用户的信息。如下图所示:
3)配置回调函数
我们在微信客户端访问第三方网页(即我们自己的网页)的时候,我们可以通过微信网页授权机制,我们不仅要有前面获取到的appid和appsecret还需要有当用户授权之后,回调的域名设置,即用户授权后,页面会跳转到哪里。具体的配置如下:
还是在刚刚的页面,有一个“网页授权获取用户基本信息”,点击后面的修改
填写回调的域名:
如果你的网址没有被列入过黑名单,就会在顶部出现
然后,域名配置就成功了!可以进行开发了。
一。授权开发的流程(详情的东西请以官网为准,在此就不多说了):具体而言,网页授权流程分为四步:
1、引导用户进入授权页面同意授权,获取code
2、通过code换取网页授权access_token(与基础支持中的access_token不同)
3、如果需要,开发者可以刷新网页授权access_token,避免过期
4、通过网页授权access_token和openid获取用户基本信息(支持UnionID机制)
二.按照如上流程我就不多说废话直接粘代码供大家参考,请大家多多指教(代码里的所有APPID,APPSECRET都是使用的官网提供测试账号)
1.设计一个公用网络请求工具类:
WXAuthUtil.java
import java.io.IOException; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; public class WXAuthUtil { public static final String APPID = "************"; public static final String APPSECRET = "*************"; public static JSONObject doGetJson(String url) throws ClientProtocolException, IOException { JSONObject jsonObject = null; DefaultHttpClient client = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(url); HttpResponse response = client.execute(httpGet); HttpEntity entity = response.getEntity(); if (entity != null) { // 把返回的结果转换为JSON对象 String result = EntityUtils.toString(entity, "UTF-8"); jsonObject = JSON.parseObject(result); } return jsonObject; } }
2.微信登录的实现类(里面包含引导action和确认登录后的回调函数):
WXLoginController.java
import java.io.IOException; import java.net.URLEncoder; import java.text.ParseException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import com.alibaba.fastjson.JSONObject; import test.util.WXAuthUtil; @Controller @RequestMapping("/wx") public class WXLoginController { private static final Logger logger = Logger.getLogger(WXLoginController.class); @Autowired private HttpServletRequest request; @Autowired private HttpServletResponse response; /** * 公众号微信登录授权 * * @param request * @param response * @return * @throws ParseException * @parameter */ @RequestMapping(value = "/wxLogin", method = RequestMethod.GET) public String wxLogin() throws ParseException { // 这个url的域名必须要进行再公众号中进行注册验证,这个地址是成功后的回调地址 String backUrl = "http://vs6ck3.natappfree.cc/wx/callBack"; // 第一步:用户同意授权,获取code String getCodeUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + WXAuthUtil.APPID + "&redirect_uri=" + URLEncoder.encode(backUrl) + "&response_type=code" + "&scope=snsapi_userinfo" + "&state=STATE#wechat_redirect"; logger.info("获取code, getCodeUrl=" + getCodeUrl); // response.sendRedirect(url); return "redirect:" + getCodeUrl;// 必须重定向,否则不能成功 } /** * 公众号微信登录授权回调函数 * * @param modelMap * @param req * @param resp * @return * @throws ServletException * @throws IOException * @parameter */ @RequestMapping(value = "/callBack", method = RequestMethod.GET) @ResponseBody public String callBack() throws ServletException, IOException { String code = request.getParameter("code"); // 第二步:通过code换取网页授权access_token String getTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + WXAuthUtil.APPID + "&secret=" + WXAuthUtil.APPSECRET + "&code=" + code + "&grant_type=authorization_code"; logger.info("获取token,getTokenUrl=" + getTokenUrl); JSONObject getTokenJson = WXAuthUtil.doGetJson(getTokenUrl); /* * { "access_token":"ACCESS_TOKEN", "expires_in":7200, * "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE" } */ logger.info("获取token,getTokenJson=" + getTokenJson.toJSONString()); String openid = getTokenJson.getString("openid"); String access_token = getTokenJson.getString("access_token"); String refresh_token = getTokenJson.getString("refresh_token"); // 第五步验证access_token是否失效;展示都不需要 String vlidTokenUrl = "https://api.weixin.qq.com/sns/auth?access_token=" + access_token + "&openid=" + openid; logger.info("验证token,vlidTokenUrl=" + vlidTokenUrl); JSONObject validTokenJson = WXAuthUtil.doGetJson(vlidTokenUrl); logger.info("验证token,validTokenJson=" + validTokenJson.toJSONString()); if (!"0".equals(validTokenJson.getString("errcode"))) { // 第三步:刷新access_token(如果需要)-----暂时没有使用,参考文档https://mp.weixin.qq.com/wiki, String refreshTokenUrl = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=" + openid + "&grant_type=refresh_token&refresh_token=" + refresh_token; logger.info("刷新token,refreshTokenUrl=" + refreshTokenUrl); JSONObject refreshTokenJson = WXAuthUtil.doGetJson(refreshTokenUrl); /* * { "access_token":"ACCESS_TOKEN", "expires_in":7200, * "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE" } */ logger.info("刷新token,refreshTokenJson=" + refreshTokenJson.toJSONString()); access_token = refreshTokenJson.getString("access_token"); } // 第四步:拉取用户信息(需scope为 snsapi_userinfo) String getUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=" + access_token + "&openid=" + openid + "&lang=zh_CN"; logger.info("获取用户信息,getUserInfoUrl=" + getUserInfoUrl.toString()); JSONObject getUserInfoJson = WXAuthUtil.doGetJson(getUserInfoUrl); /* * { "openid":" OPENID", " nickname": NICKNAME, "sex":"1", "province":"PROVINCE" * "city":"CITY", "country":"COUNTRY", "headimgurl": * "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46", * "privilege":[ "PRIVILEGE1" "PRIVILEGE2" ], "unionid": * "o6_bmasdasdsad6_2sgVt7hMZOPfL" } */ logger.info("获取用户信息,getUserInfoJson=" + getUserInfoJson.toString()); /* * end 获取微信用户基本信息 */ // 获取到用户信息后就可以进行重定向,走自己的业务逻辑了。。。。。。 // 接来的逻辑就是你系统逻辑了,请自由发挥 return getUserInfoJson.toString(); } }
祖先原文地址:https://blog.csdn.net/weixin_43031215/article/details/83345388