微信网页授权登录(公众号)
第一步
先去微信公众平台申请公众号,网址:https://mp.weixin.qq.com/,然后有了公众号申请测试号,拿到appID和appsecret
第二步
申请url和域名
(1) 测试号二维码添加自己的微信号(后期使用微信web开发者工具)可以用自己微信测试,注意 往下拉 :网页服务 --> 网页帐号 --> 网页授权获取用户基本信息 --> 修改 这边也需要把域名填写,和上面的域名一致。
因为微信的授权接口必须是域名不能ip,所有这边没有域名的小伙伴可以使用NATAPP
公网配置前的准备:
在我们本地测试的时候,需要将我们的本地地址映射到公网,我们使用一个免费且非常方便的工具:natapp。下面的地址是natapp的官网和natapp的使用教程:
natapp官网 :https://natapp.cn/
NATAPP 1分钟快速新手图文教程 :https://natapp.cn/article/natapp_newbie
免费隧道配置
先注册,注册成功后登录。
注意上图:本地端口必须是要填8080的(这个购买后也是可以再修改的),因为微信公众平台接口的调用仅支持80。开发之间建议阅读微信公众平台技术文档。
隧道购买成功后,在我的隧道中就可以看到已拥有的隧道:
客户端下载
我们访问到natapp的客户端下载,下载natapp客户端:
下载后,解压,会有一个natapp.exe的文件。
运行natapp
在运行natapp之前需要先配置,详细教程参考:使用本地配置文件config.ini。config.ini内容:
注意:config.ini配置文件需要与natapp.exe在同一个目录下。
在这两个文件的目录下,打开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,不然是找不到公网映射的
(2) 申请url,有了域名以后自己写个api直接返回就可以成功了
1 @ApiOperation(value = "微信申请URL") 2 @GetMapping("") 3 public void getUrl(HttpServletRequest request, HttpServletResponse response) throws IOException { 4 log.info("WeiXinController getUrl start"); 5 6 Enumeration pNames = request.getParameterNames(); 7 String logName = null; 8 while (pNames.hasMoreElements()) { 9 String name = (String) pNames.nextElement(); 10 String value = request.getParameter(name); 11 logName = "name =" + name + " value =" + value; 12 } 13 log.info("logName: " + logName); 14 15 // 微信加密签名 16 String signature = request.getParameter("signature"); 17 // 时间戳 18 String timestamp = request.getParameter("timestamp"); 19 // 随机数 20 String nonce = request.getParameter("nonce"); 21 // 随机字符串 22 String echostr = request.getParameter("echostr"); 23 PrintWriter out = response.getWriter(); 24 out.print(echostr); 25 out.close(); 26 String info = "signature = " + signature + ", timestamp = " + timestamp + ", nonce = " + nonce + ", echostr = "+ echostr; 27 log.info(info); 28 29 log.info("WeiXinController getUrl end"); 30 }
第三步
后台接口测试
第一个servlet:
@Slf4j @WebServlet(name = "weChatLoginServlet", urlPatterns = "/wechat/login") public class WeiXinLoginServlet extends HttpServlet { public WeiXinLoginServlet() { super(); } /** * 微信公众号唯一标识(在微信小程序管理后台获取) */ @Value("${wechat.appId}") private String appId; /** * 回调地址 */ @Value("${wechat.backUrl}") private String backUrl; /** * 第一步:引导用户进入授权页面同意授权,获取code */ @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { log.debug("WeiXinLoginServlet doGet start"); // 授权页面地址 String url = "https://open.weixin.qq.com/connect/oauth2/authorize?" + "appid=" + appId + "&redirect_uri=" + urlEncodeUTF8(backUrl) + "&response_type=code" + "&scope=snsapi_base" + "&state=STATE#wechat_redirect"; // 重定向到授权页面 response.sendRedirect(url); log.debug("WeiXinLoginServlet doGet end"); } /** * 用 urlEncode 对链接进行处理 * * @author * @date 2019-03-19 */ private String urlEncodeUTF8(String source) { log.debug("WeiXinLoginServlet urlEncodeUTF8 start, source = [{}]", source); String result = source; try { result = java.net.URLEncoder.encode(source,"utf-8"); } catch (UnsupportedEncodingException e) { log.info("WeiXinController urlEncodeUTF8 BaseException: " + e.getMessage()); } log.debug("WeiXinLoginServlet urlEncodeUTF8 end"); return result; } }
第二个servlet:
@Slf4j @WebServlet(name = "weChatCallbackServlet", urlPatterns = "/wechat/callback") public class WeiXinCallBackServlet extends HttpServlet { public WeiXinCallBackServlet() { super(); } /** * 微信公众号唯一标识(在微信小程序管理后台获取) */ @Value("${wechat.appId}") private String appId; /** * 回调地址 */ @Value("${wechat.secret}") private String secret; /** * 第二步:通过code换取网页授权openid */ @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { log.debug("WeiXinCallBackServlet callback start"); // 从request里面获取code参数(当微信服务器访问回调地址的时候,会把code参数传递过来) String code = request.getParameter("code"); // 获取code后,请求以下链接获取access_token String url = "https://api.weixin.qq.com/sns/oauth2/access_token?" + "appid=" + appId + "&secret=" + secret + "&code=" + code + "&grant_type=authorization_code"; // 通过网络请求方法来请求上面这个接口 JSONObject jsonObject = doGetJson(url); // 从返回的JSON数据中取出access_token和openid,拉取用户信息时用 // String token = jsonObject.getString("access_token"); String openid = jsonObject.getString("openid"); // 第四步:拉取用户信息(需scope为 snsapi_userinfo) // String infoUrl ="https://api.weixin.qq.com/sns/userinfo?" // + "access_token=" + token // + "&openid=" + openid // + "&lang=zh_CN"; // 通过网络请求方法来请求上面这个接口 // JSONObject userInfo = doGetJson(infoUrl); request.setAttribute("openid", openid); // request.getRequestDispatcher("/login?channel=1&source=1&openid=" + openid).forward(request, response); log.debug("WeiXinCallBackServlet callback end"); } /** * 工具类 * @param url String * @return JSONObject */ private JSONObject doGetJson(String url) throws IOException { log.debug("WeiXinCallBackServlet doGetJson start, url = [{}]", url); JSONObject jsonObject = null; // 首先初始化HttpClient对象 HttpClient client = HttpClientBuilder.create().build(); // 通过get方式进行提交 HttpGet httpGet = new HttpGet(url); // 通过HTTPclient的execute方法进行发送请求 HttpResponse response = client.execute(httpGet); // 从response里面拿自己想要的结果 HttpEntity entity = response.getEntity(); if(entity != null){ String result = EntityUtils.toString(entity,"UTF-8"); jsonObject = JSONObject.parseObject(result); } // 把链接释放掉 httpGet.releaseConnection(); log.debug("WeiXinCallBackServlet doGetJson end"); return jsonObject; }
访问第一个servlet以后会得到一个跳转地址,然后直接在微信web开发者工具上使用就可以测试获取openId了