当前位置:   article > 正文

Java 实现微信扫码登录方法(提供前端及后端核心代码)_java微信扫码登录

java微信扫码登录

思路

1、Vue前端页面获取一个公众号的二维码,不是普通二维号,是带有场景值的

2、java后端接收前端的请求,生成一个带时效性的二维码链接返回给前端

3、公众号平台配置服务器接口地址

4、接收到关注或扫码请求并相应处理

5、前端轮询状态,如果检查到验证通过进到下一页面

前端页面

vue代码

  1. wxlogin() {
  2. this.$showLoading();
  3. getTempQrCode(this.token).then((res) => {
  4. console.log("res==========",res);
  5. this.$closeLoading();
  6. this.imageUrl = objToStr(res.data.message);
  7. this.loginType='wx'
  8. setTimeout(() => {
  9. this.check();
  10. }, 1000);
  11. })
  12. },

java代码

  1. @RequestMapping(value = "/getTempQrCode", method = RequestMethod.GET)
  2. public Result<?> getTempQrCode(@RequestParam(name = "scene_str", required = true) String sceneStr) {
  3. WeixinHelper.setAppId(appid);
  4. WeixinHelper.setSecret(secret);
  5. String result = WeixinHelper.createTempQrCode(WeixinHelper.getAccessToken(), sceneStr);
  6. return Result.ok(result);
  7. }
  8. public static String createTempQrCode(String access_token, String scene_str) {
  9. String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + access_token;
  10. Map<String, Object> data = new HashMap<>();
  11. data.put("expire_seconds", 604800);
  12. data.put("action_name", "QR_STR_SCENE");
  13. Map<String, Object> action_info = new HashMap<>();
  14. Map<String, Object> scene = new HashMap<>();
  15. scene.put("scene_str", scene_str);
  16. action_info.put("scene", scene);
  17. data.put("action_info", action_info);
  18. String json = HttpUtil.createPost(url)
  19. .header("Content-Type", "application/json")
  20. .body(JSONUtil.toJsonStr(data))
  21. .execute().body();
  22. System.out.println("json = " + json);
  23. String qrcode = (String) JSONUtil.getByPath(JSONUtil.parse(json), "ticket");
  24. return "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=" + qrcode;
  25. }
  26. public static String getAccessToken() {
  27. accessToken = getNewAccessToken();
  28. return accessToken;
  29. }
  30. public static String getNewAccessToken() {
  31. String access_token = "";
  32. String grant_type = "client_credential";//获取access_token填写client_credential
  33. String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=" + grant_type + "&appid=" + appId + "&secret=" + secret;
  34. try {
  35. URL urlGet = new URL(url);
  36. HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
  37. http.setRequestMethod("GET"); // 必须是get方式请求
  38. http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
  39. http.setDoOutput(true);
  40. http.setDoInput(true);
  41. System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒
  42. System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒
  43. http.connect();
  44. InputStream is = http.getInputStream();
  45. int size = is.available();
  46. byte[] jsonBytes = new byte[size];
  47. is.read(jsonBytes);
  48. String message = new String(jsonBytes, "UTF-8");
  49. JSONObject demoJson = JSONObject.parseObject(message);
  50. System.out.println("JSON字符串:" + demoJson);
  51. access_token = demoJson.getString("access_token");
  52. is.close();
  53. } catch (Exception e) {
  54. e.printStackTrace();
  55. }
  56. return access_token;
  57. }

公众号配置

java提供消息接收接口代码,有两个,一个get(公众平台网址验证的时候用),一个post(消息事件触发时用)

  1. /*
  2. * @param signature 微信加密签名,signature结合了开发者填写的 token 参数和请求中的 timestamp 参数、nonce参数。
  3. * @param timestamp 时间戳
  4. * @param nonce 这是个随机数
  5. * @param echostr 随机字符串,验证成功后原样返回
  6. */
  7. @GetMapping("/wx/event")
  8. public void get(@RequestParam(required = false) String signature,
  9. @RequestParam(required = false) String timestamp,
  10. @RequestParam(required = false) String nonce,
  11. @RequestParam(required = false) String echostr,
  12. HttpServletResponse response) throws IOException {
  13. System.out.println("接受事件===" + echostr);
  14. response.setCharacterEncoding("UTF-8");
  15. response.getWriter().write(echostr);
  16. response.getWriter().flush();
  17. response.getWriter().close();
  18. }
  19. //处理微信推送事件
  20. @PostMapping("/wx/event")
  21. public void post(final HttpServletRequest request, HttpServletResponse response) {
  22. System.out.println("接受事件");
  23. try {
  24. // 微信加密签名
  25. final String signature = request.getParameter("signature");
  26. // 时间戳
  27. final String timestamp = request.getParameter("timestamp");
  28. // 随机数
  29. final String nonce = request.getParameter("nonce");
  30. // 随机字符串
  31. final String echostr = request.getParameter("echostr");
  32. //将xml文件转成易处理的map(下方贴出)
  33. final Map<String, String> map = oConvertUtils.parseXml(request);
  34. //开发者微信号
  35. final String toUserName = map.get("ToUserName");
  36. //OpenId
  37. final String fromUserName = map.get("FromUserName");
  38. //消息创建时间 (整型)
  39. final String createTime = map.get("CreateTime");
  40. //消息类型,event
  41. final String msgType = map.get("MsgType");
  42. //事件类型
  43. final String event = map.get("Event");
  44. String scene_str = "";
  45. String msg = "";
  46. if ("event".equals(msgType)) {
  47. if (event.equals("subscribe")) {
  48. final String ticket = map.get("Ticket");
  49. if (ticket != null) {
  50. scene_str = map.get("EventKey").replace("qrscene_", "");
  51. }
  52. msg = getXmlReturnMsg(fromUserName, toUserName, (new Date()).getTime(), "欢迎您使用量子文档");
  53. }
  54. //注:事件类型为SCAN即已关注
  55. else if (event.equals("SCAN")) {
  56. final String ticket = map.get("Ticket");
  57. if (ticket != null) {
  58. scene_str = map.get("EventKey");
  59. }
  60. msg = getXmlReturnMsg(fromUserName, toUserName, (new Date()).getTime(), "您刚刚扫码登录了量子文档");
  61. }
  62. }
  63. System.out.println("event:" + event);
  64. System.out.println("场景值:" + scene_str);
  65. System.out.println("openId:" + fromUserName);
  66. System.out.println("ToUserName:" + toUserName);
  67. // 如果scene_str 不为空代表用户已经扫描并且关注了公众号
  68. if (oConvertUtils.isNotEmpty(scene_str)) {
  69. QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
  70. queryWrapper.eq("open_id", fromUserName);
  71. SysUser sysUser = sysUserService.getOne(queryWrapper, false);
  72. if (sysUser == null) {
  73. sysUser = new SysUser();
  74. sysUser.setOpenId(fromUserName);
  75. sysUser.setUsername(fromUserName);
  76. sysUser.setRealname(null);
  77. String salt = oConvertUtils.randomGen(8);
  78. String passwordEncode = PasswordUtil.encrypt(fromUserName, salt, salt);
  79. sysUser.setSalt(salt);
  80. sysUser.setMemberLevelId("1");
  81. sysUser.setPassword(passwordEncode);
  82. sysUser.setStatus(1);
  83. sysUser.setDelFlag(CommonConstant.DEL_FLAG_0);
  84. sysUserService.save(sysUser);
  85. LzMessage message = new LzMessage();
  86. message.setMsgDate(new Date());
  87. message.setContent("欢迎您使用量子文档");
  88. message.setFileId(null);
  89. message.setIsRead(0);
  90. message.setDelFlag(0);
  91. message.setMsgType(3);
  92. message.setFromUserId("001");
  93. message.setFromUserName("小量子");
  94. message.setToUserId(sysUser.getId());
  95. lzMessageService.save(message);
  96. }
  97. // 将微信公众号用户ID缓存到redis中,标记用户已经扫码完成,执行登录逻辑。
  98. redisUtil.set(scene_str, fromUserName, 60);
  99. }
  100. System.out.println("打印消息体=========");
  101. System.out.println(msg);
  102. System.out.println("=========");
  103. response.setCharacterEncoding("UTF-8");
  104. PrintWriter out = response.getWriter();
  105. out.print(msg);
  106. out.flush();
  107. out.close();
  108. } catch (Exception e) {
  109. e.printStackTrace();
  110. }
  111. }

vue前端轮询

  1. check() {
  2. if (this.loginType!='wx') return false;
  3. checkScanState(this.token).then((res) => {
  4. console.log(res);
  5. console.log("check....");
  6. if (res.data.success == true) {
  7. sessionStorage.setItem('token', res.data.result.token)
  8. sessionStorage.setItem('userId', res.data.result.userInfo.id)
  9. sessionStorage.setItem('userName', res.data.result.userInfo.username)
  10. sessionStorage.setItem('realname', res.data.result.userInfo.realname)
  11. sessionStorage.setItem('sex', res.data.result.userInfo.sex)
  12. sessionStorage.setItem('memberLevelName', res.data.result.memberLevel.name)
  13. sessionStorage.setItem('maxFileCount', res.data.result.memberLevel.maxFileCount)
  14. this.loginType = "";
  15. if (objToStr(res.data.result.userInfo.realname) == "") {
  16. this.$showInputBox({
  17. caption: "输入您的姓名",
  18. inputValue: '',
  19. callback: (data) => {
  20. updateRealname(res.data.result.userInfo.id, data).then((res) => {
  21. sessionStorage.setItem('realname', data)
  22. this.$closeInputBox();
  23. })
  24. }
  25. })
  26. }
  27. this.$router.push({
  28. path: '/person' ,
  29. })
  30. } else {
  31. setTimeout(() => {
  32. this.check();
  33. }, 1000);
  34. }
  35. })
  36. },

后端接受前端查状态的轮询请求

  1. @ApiOperation("检查扫码状态")
  2. @GetMapping("/checkScanState")
  3. public Result<JSONObject> wechatLogin(@RequestParam(name = "scene_str", required = true) String sceneStr) {
  4. Result<JSONObject> result = new Result<JSONObject>();
  5. Object openId = redisUtil.get(sceneStr);
  6. if (openId == null) {
  7. result.error500("未登入");
  8. return result;
  9. }
  10. QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
  11. queryWrapper.eq("open_id", openId);
  12. SysUser sysUser = sysUserService.getOne(queryWrapper, false);
  13. if (sysUser != null) {
  14. String syspassword = sysUser.getPassword();
  15. String username = sysUser.getUsername();
  16. // 生成token
  17. String token = JwtUtil.sign(username, syspassword);
  18. redisUtil.del(CommonConstant.PREFIX_USER_TOKEN + token);
  19. //清空用户登录Shiro权限缓存
  20. redisUtil.del(CommonConstant.PREFIX_USER_SHIRO_CACHE + sysUser.getId());
  21. //清空用户的缓存信息(包括部门信息),例如sys:cache:user::<username>
  22. redisUtil.del(String.format("%s::%s", CacheConstant.SYS_USERS_CACHE, sysUser.getUsername()));
  23. result = sysUserService.checkUserIsEffective(sysUser);
  24. if(!result.isSuccess()) {
  25. return result;
  26. }
  27. //用户信息
  28. userInfo(sysUser, result);
  29. //添加日志
  30. sysBaseAPI.addLog("用户名: " + sysUser.getUsername() + ",登录成功!", CommonConstant.LOG_TYPE_1, null);
  31. }
  32. return result;
  33. }
  34. /**
  35. * 用户信息
  36. *
  37. * @param sysUser
  38. * @param result
  39. * @return
  40. */
  41. private Result<JSONObject> userInfo(SysUser sysUser, Result<JSONObject> result) {
  42. String syspassword = sysUser.getPassword();
  43. String username = sysUser.getUsername();
  44. // 生成token
  45. String token = JwtUtil.sign(username, syspassword);
  46. // 设置token缓存有效时间
  47. redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
  48. redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME*2 / 1000);
  49. // 获取用户部门信息
  50. JSONObject obj = new JSONObject();
  51. List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());
  52. obj.put("departs", departs);
  53. if (departs == null || departs.size() == 0) {
  54. obj.put("multi_depart", 0);
  55. } else if (departs.size() == 1) {
  56. sysUserService.updateUserDepart(username, departs.get(0).getOrgCode());
  57. obj.put("multi_depart", 1);
  58. } else {
  59. obj.put("multi_depart", 2);
  60. }
  61. obj.put("token", token);
  62. obj.put("userInfo", sysUser);
  63. obj.put("sysAllDictItems", sysDictService.queryAllDictItems());
  64. obj.put("memberLevel", lzMemberLevelService.getById(sysUser.getMemberLevelId()));
  65. result.setResult(obj);
  66. result.success("登录成功");
  67. return result;
  68. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/675721
推荐阅读
相关标签
  

闽ICP备14008679号