Java微信公众获取用户信息踩的坑记录一下
1、测试号
地址:https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index
记得修改为自己的域名:例子 example.test.com
接下来就是干货,上Java代码
@RequestMapping(value = "/wxLogin", method = RequestMethod.GET) public String wxLogin() throws ParseException { // 这个url的域名必须要进行再公众号中进行注册验证,这个地址是成功后的回调地址 String backUrl = "http://xxx.xxx.xxx/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;// 必须重定向,否则不能成功 }
@GetMapping(value = "/callBack") public String callBack(Model model) 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 获取微信用户基本信息 */ // 获取到用户信息后就可以进行重定向,走自己的业务逻辑了。。。。。。 // 缓存 + 1 redisService.incr(ArtKey.isNum,"" + "1"); // 取缓存 String numStr = redisService.get(ArtKey.isNum, "" + "1", String.class); model.addAttribute("name",getUserInfoJson.get("nickname")); model.addAttribute("count",numStr); // 回调到页面 return "index"; } }
public static final String APPID = "XXX"; // public static final String APPID = "XXX"; public static final String APPSECRET = "XXX"; // public static final String APPSECRET = "XXX"; // 与接口配置信息中的Token要一致 private static String token = "XXX"; 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; }
到这儿呢,第一个测试就能跑通了。
接下来,跑第二个测试
URL:(验证微信数字签名的接口)
Token:自己设置
@Slf4j @RestController @RequestMapping("/wechat") public class WechatController { /** * 微信公众号签名认证接口 * @Title: test * @Description: TODO * @param: @param signature * @param: @param timestamp * @param: @param nonce * @param: @param echostr * @param: @return * @return: String * @throws */ @RequestMapping("/wxToken") public String test(String signature,String timestamp,String nonce,String echostr) { // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败 if (signature != null && WXAuthUtil.checkSignature(signature, timestamp, nonce)) { return echostr; } return null; } }
/** * 验证签名 * * @param signature * @param timestamp * @param nonce * @return */ public static boolean checkSignature(String signature, String timestamp, String nonce) { String[] arr = new String[] { token, timestamp, nonce }; // 将token、timestamp、nonce三个参数进行字典序排序 // Arrays.sort(arr); sort(arr); StringBuilder content = new StringBuilder(); for (int i = 0; i < arr.length; i++) { content.append(arr[i]); } MessageDigest md = null; String tmpStr = null; try { md = MessageDigest.getInstance("SHA-1"); // 将三个参数字符串拼接成一个字符串进行sha1加密 byte[] digest = md.digest(content.toString().getBytes()); tmpStr = byteToStr(digest); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } content = null; // 将sha1加密后的字符串可与signature对比,标识该请求来源于微信 return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false; } /** * 将字节数组转换为十六进制字符串 * * @param byteArray * @return */ private static String byteToStr(byte[] byteArray) { String strDigest = ""; for (int i = 0; i < byteArray.length; i++) { strDigest += byteToHexStr(byteArray[i]); } return strDigest; } /** * 将字节转换为十六进制字符串 * * @param mByte * @return */ private static String byteToHexStr(byte mByte) { char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; char[] tempArr = new char[2]; tempArr[0] = Digit[(mByte >>> 4) & 0X0F]; tempArr[1] = Digit[mByte & 0X0F]; String s = new String(tempArr); return s; } public static void sort(String a[]) { for (int i = 0; i < a.length - 1; i++) { for (int j = i + 1; j < a.length; j++) { if (a[j].compareTo(a[i]) < 0) { String temp = a[i]; a[i] = a[j]; a[j] = temp; } } } }
第二个测试跑通了
,接下来就是公众号上的配置了。
参考:
https://www.zhongjianghua.com/att1tude/10205-2020-04.html
https://blog.csdn.net/qq_36654629/article/details/91877299
https://www.kanzhun.com/jiaocheng/534258.html
版权声明:本文为zy1104560031原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。