微信公众号开发-静默授权实现消息推送(微服务方式)
一:引用pom
<dependency> <groupId>com.github.binarywang</groupId> <artifactId>weixin-java-mp</artifactId> <version>${weixin-java-mp.version}</version> </dependency>
二:获取code
注意:redirect_uri 回调地址。请求完成后,微信在回调该地址的时候会带上code,然后根据code去拿openId。亲测不需要编码!!!
要在微信客户端打开接口地址,推荐工具https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455784140 微信官方web开发工具。
传入appId就行了,state是回调的时候带的参数
@ApiOperation(value = "获取code,并回调获取openId", notes = "获取code,并回调获取openId") @GetMapping(value = "/routerForOpenId") public void redirectToMyPage(HttpServletRequest request, HttpServletResponse response, String phone) { StringBuffer sb = new StringBuffer(); StringBuffer encodeUrl = new StringBuffer(300); //公众号中配置的回调域名(网页授权回调域名) // String doname = // request.getScheme() + "://" + request.getServerName() + (-1 == request.getLocalPort() ? "" // : ":" + request.getLocalPort()); String doname = "http://xuexing.ngrok.xiaomiqiu.cn"; String root = "/WeChat"; String appId = "wxb6fac4047e049312"; sb.append("https://open.weixin.qq.com/connect/oauth2/authorize?appid="); sb.append(appId); String url = ""; try { //对重定向url进行编码,官方文档要求 encodeUrl.append(doname).append(root).append("/openId.html"); // url = URLEncoder.encode(encodeUrl.toString(), "utf-8"); sb.append("&redirect_uri=").append(encodeUrl.toString()); //网页授权的静默授权snsapi_base sb.append("&response_type=code&scope=snsapi_base&state=").append(phone); sb.append("#wechat_redirect"); response.sendRedirect(sb.toString()); } catch (UnsupportedEncodingException e) { log.error("重定向url编码失败:>>" + e.getMessage()); e.printStackTrace(); } catch (Exception e) { log.error("response重定向失败:>>" + e.getMessage()); e.printStackTrace(); } }
三:回调地址方法
调用回调地址之前需要一些准备工作:
1,回调地址需要做一个内网穿透,推荐工具Ngrok,花生壳。。本人使用的是Ngrok
1)在Ngrok官网下载好客户端 http://www.ngrok.cc/download.html
2)在官网注册账号并开通隧道 http://www.ngrok.cc 按官网教程开通,有免费隧道,完全可以满足本地开发使用。
3)运行Sunny-Ngrok启动工具.bat 在命令行中输入 clientId (就是在官网注册的邮箱)和 隧道Id(看清,是Id 不是名字)
4)成功后界面,恭喜你内网穿透已经做好,可以在外网环境访问你的服务接口了。
2,配置微信授权域名
1)微信公众平台 https://mp.weixin.qq.com/
2)在保存的时候,会验证是否在你域名的根目录下保存了这个文件。事实上他验证的本质就是通过 [域名+/txt文件名] 是否能访问到txt文件中的字符码,所以我们在微服务中写一个接口将文件中字符返回出来,保存的时候就能校验通过了。
注意:[域名+/txt文件名]和[域名+/openId.html]一定要都可以访问同,微信才能通过 redirect_uri 回调
@ApiOperation(value = "回调获取openId", notes = "回调获取openId") @GetMapping(value = "/openId.html") //发送请求,根据code获取openId public String getOpenId(HttpServletRequest request, HttpServletResponse response, String code, String state) { String content = ""; String openId = ""; String unionId = ""; //封装获取openId的微信API StringBuffer url = new StringBuffer(); url.append("https://api.weixin.qq.com/sns/oauth2/access_token?appid=") .append("wxb6fac4047e049312") .append("&secret=") .append("726b163b73fe82a282903084805b663a") .append("&code=") .append(code) .append("&grant_type=authorization_code"); ObjectMapper objectMapper = new ObjectMapper(); try { HttpGet httpGet = new HttpGet(url.toString());//这里发送get请求 HttpClient httpClient = HttpClientBuilder.create().build(); HttpResponse httpResponse = httpClient.execute(httpGet); // 判断网络连接状态码是否正常(0--200都数正常) if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { content = EntityUtils.toString(httpResponse.getEntity(), "utf-8"); } Map map = objectMapper.readValue(content, Map.class); openId = String.valueOf(map.get("openid")); unionId = String.valueOf(map.get("unionid")); log.info("获取的openID:" + openId); /* * 将openId保存到session中,当其他业务获取openId时, * 可先从session中获取openId. */ request.getSession().setAttribute("openId", openId); } catch (JsonParseException e) { log.error("json解析失败:", e); } catch (JsonMappingException e) { log.error("map转换成json失败:", e); } catch (Exception e) { log.error("http获取openId请求失败:", e); } return openId; }
在这里我们就能够拿到当前微信用户的openid 并在消息推送的时候进行用户 判断,来针对性的推送