场景:用户扫描微信公众号的二维码,关注后自动登录网站,若已关注则直接登录。

逻辑:
1.系统生成带参数(此参数自定义为唯一值)的临时二维码(微信公众平台有提供该接口,可查看一下开发文档);
2.用户使用微信扫描该二维码,关注后微信服务器会将数据(自定义参数、openid…)返回到我们的服务器;
3.我们服务器将接收到的openid再次向微信服务器发起请求,获取该用户的信息(昵称、头像、地域、unionid(若绑定了微信开放平台,则有此参数));
4.我们将返回的用户信息存储到数据库,用作于登录。

准备工作:登录微信公众平台,在基本配置下,查看appid和设置appsecret、回调URL、token,小编这里使用的是测试账号,因为正式的要审核(收费300个大洋),如下图:


小编是使用springMVC+mybatis开发的,为了方便展示,小编将代码都写在同一个controller下了,你们自己可以做下拆分,代码如下:

package com.lrfun.web.controller;import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import javax.servlet.http.HttpServletRequest;import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;import com.google.gson.Gson;@Controller
public class WechatController {//Lrfun测试公众号private static final String app_id = "xxx";private static final String app_secret = "xxx";private static final Gson gson = new Gson();/**** httpClient-Get请求* @param url 请求地址* @return* @throws Exception*/public static Map<String, Object> httpClientGet(String url) throws Exception {HttpClient client = new HttpClient();client.getParams().setContentCharset("UTF-8");GetMethod httpGet = new GetMethod(url);try {client.executeMethod(httpGet);String response = httpGet.getResponseBodyAsString();Map<String, Object> map = gson.fromJson(response, Map.class);return map;} catch (Exception e) {throw e;} finally {httpGet.releaseConnection();}}/**** httpClient-Post请求* @param url 请求地址* @param params post参数* @return* @throws Exception*/public static Map<String, Object> httpClientPost(String url, String params) throws Exception {HttpClient client = new HttpClient();client.getParams().setContentCharset("UTF-8");PostMethod httpPost = new PostMethod(url);try {RequestEntity requestEntity = new ByteArrayRequestEntity(params.getBytes("utf-8"));httpPost.setRequestEntity(requestEntity);client.executeMethod(httpPost);String response = httpPost.getResponseBodyAsString();Map<String, Object> map = gson.fromJson(response, Map.class);return map;} catch (Exception e) {throw new RuntimeException(e);} finally {httpPost.releaseConnection();}}// 获取access_tockenprivate String getAccessToken() throws Exception{String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + app_id + "&secret=" + app_secret;Map<String, Object> accessTokenMap = WechatController.httpClientGet(url);System.out.println(accessTokenMap);return accessTokenMap.get("access_token").toString();}// 通过openid获取用户信息private Map<String, Object> getUserInfoByOpenid(String openid) throws Exception {String access_tocken = getAccessToken();String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + access_tocken + "&openid=" + openid;Map<String, Object> map = httpClientGet(url);return map;}// 生成带参数的二维码,扫描关注微信公众号,自动登录网站@RequestMapping(value = "/wechat/mpLogin.html")public ModelAndView wechatMpLogin(ModelMap modelMap) throws Exception {String access_token = getAccessToken();String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + access_token;String scene_str = "lrfun.com." + new Date().getTime();String params = "{\"expire_seconds\":600, \"action_name\":\"QR_STR_SCENE\", \"action_info\":{\"scene\":{\"scene_str\":\"" + scene_str + "\"}}}";Map<String, Object> resultMap = httpClientPost(url, params);if (resultMap.get("ticket") != null) {String qrcodeUrl = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=" + resultMap.get("ticket");modelMap.put("qrcodeUrl", qrcodeUrl);}modelMap.put("scene_str", scene_str);return new ModelAndView("/test/wechatMpLogin.vm", modelMap);}// 检测登录@RequestMapping("/wechat/checkLogin.html")public @ResponseBody Map<String, Object> wechatMpCheckLogin(String scene_str){// 根据scene_str查询数据库,获取对应记录// SELECT * FROM wechat_user_info WHERE event_key='scene_str';Map<String, Object> returnMap = new HashMap<String, Object>();if (true) {returnMap.put("result", "true");} else {returnMap.put("result", "false");}return returnMap;}// 回调函数@RequestMapping(value = "/wechat/callback.html")public void callback(HttpServletRequest httpServletRequest) throws Exception {Map<String, String> callbackMap = xmlToMap(httpServletRequest); //获取回调信息//下面是返回的xml//<xml><ToUserName><![CDATA[gh_f6b4da984c87]]></ToUserName> //微信公众号的微信号//<FromUserName><![CDATA[oJxRO1Y2NgWJ9gMDyE3LwAYUNdAs]]></FromUserName> //openid用于获取用户信息,做登录使用//<CreateTime>1531130986</CreateTime> //回调时间//<MsgType><![CDATA[event]]></MsgType>//<Event><![CDATA[SCAN]]></Event>//<EventKey><![CDATA[lrfun.com.UxJkWC1531967386903]]></EventKey> //上面自定义的参数(scene_str)//<Ticket><![CDATA[gQF57zwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyY2ljbjB3RGtkZWwxbExLY3hyMVMAAgTvM0NbAwSAOgkA]]></Ticket> //换取二维码的ticket//</xml>if (callbackMap != null && callbackMap.get("FromUserName").toString() != null) {// 通过openid获取用户信息Map<String, Object> wechatUserInfoMap = getUserInfoByOpenid(callbackMap.get("FromUserName"));// 将数据写入到数据库中,前面自定义的参数(scene_str)也需记录到数据库中,后面用于检测匹配登录// INSERT INTO wechat_user_info......(数据库操作)}}// xml转为mapprivate Map<String, String> xmlToMap(HttpServletRequest httpServletRequest) {Map<String, String> map = new HashMap<String, String>();try {InputStream inputStream = httpServletRequest.getInputStream();SAXReader reader = new SAXReader(); // 读取输入流org.dom4j.Document document = reader.read(inputStream);Element root = document.getRootElement(); // 得到xml根元素List<Element> elementList = root.elements(); // 得到根元素的所有子节点// 遍历所有子节点for (Element e : elementList)map.put(e.getName(), e.getText());// 释放资源inputStream.close();inputStream = null;return map;} catch (Exception e) {e.getMessage();}return null;}
}

静态文件wechatMpLogin.vm:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>微信扫码,关注登录</title>
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
<style>a{outline:0}h1,h2,h3,h4,h5,h6,p{margin:0;font-weight:400}a img,fieldset{border:0}body{font-family:"Microsoft Yahei";color:#fff;background:0 0}.impowerBox{display:inline-block;vertical-align:middle;line-height:1.6;position:relative;width:100%;z-index:1;text-align:center}.impowerBox .title{text-align:center;font-size:20px}.impowerBox .qrcode{width:280px;height:280px;margin-top:15px;border:1px solid #E2E2E2}.impowerBox .info{width:280px;margin:0 auto}.impowerBox .status{padding:7px 14px;text-align:left}.impowerBox .status.normal{margin-top:15px;background-color:#232323;border-radius:100px;-moz-border-radius:100px;-webkit-border-radius:100px;box-shadow:inset 0 5px 10px -5px #191919,0 1px 0 0 #444;-moz-box-shadow:inset 0 5px 10px -5px #191919,0 1px 0 0 #444;-webkit-box-shadow:inset 0 5px 10px -5px #191919,0 1px 0 0 #444}.impowerBox .status.status_browser{text-align:center}.impowerBox .status p{font-size:13px}</style>
<script type="text/javascript" src="http://www.lrfun.com/statics/fun2/js/jquery.min.js"></script>
</head>
<body style="background-color: rgb(51, 51, 51); padding: 50px;">
<div class="main impowerBox"><div class="loginPanel normalPanel"><div class="title">微信登录</div><div class="waiting panelContent"><div class="wrp_code"><img class="qrcode lightBorder" src="$!{qrcodeUrl}"/></div><div class="info"><div class="status status_browser js_status normal" id="wx_default_tip"><p>请使用微信扫描二维码登录</p><p>“lrfun.com”</p></div></div></div></div>
</div>
<script type="text/javascript">$(document).ready(function () {setInterval("wechatCheckLogin()", 2000);});function wechatCheckLogin(){$.post("/wechat/checkLogin.html", {scene_str:"$!{scene_str}"}, function(data){if(data.result == "true"){alert("成功,登录跳转!");} else {alert("失败!");}}, "JSON");}
</script>
</body>
</html>

看了下评论,可能小编有些地方写得不是很清楚,画了一幅图解释一下整个流程(可能画得跟表达得不是很好,大家多多见谅)

更多文章可查看小编的个人博客网站:www.lrfun.com

Java 扫描微信公众号二维码,关注并自动登录网站相关推荐

  1. java获取微信公众号二维码

    引入依赖: <dependency><groupId>com.github.binarywang</groupId><artifactId>weixin ...

  2. 如何给CSDN博客添加微信公众号二维码或自定义栏目

    1. 前言 在浏览CSDN博客的过程中,我们可以发现有些博主的主页有微信公众号二维码等一些个人栏目信息.这可以让其他浏览博客的游客和作者进行有效的沟通,同时也可以在博客里对自己的微信公众号作宣传.我这 ...

  3. thinkphp5+php微信公众号二维码扫码关注推广二维码事件实现

    thinkphp5微信公众号二维码扫码关注推广二维码事件实现, 给出实现的全部方法: 获取二维码,让微信公众号跳转到以下代码的code方法即可,用户点击二维码后,通过二维码获取关注用户信息及二维码推广 ...

  4. 微信公众号二维码怎么生成?好用的生成方法介绍

    微信公众号二维码怎么生成?从事新媒体行业的小伙伴们应该都对微信公众号不陌生吧,公众号是一个企业对外宣传的重要方式之一.通常情况下我们都会将公众号的二维码放置在文章的文末.以便于读者扫码关注公众号.那么 ...

  5. 查看获取别人的微信公众号二维码

    亲测可用,若有疑问请私信 方法一:通过微信号获取公众号/订阅号二维码 这个方法需要知道公众号/订阅号的微信号,具体操作步骤如下: 2.打开浏览器(电脑或手机浏览器均可),访问以下链接地址: https ...

  6. 分享编程技术的微信公众号二维码

    微信公众号二维码 大家好,以下是我的微信公众号二维码,平时会在公众号里分享和总结一些技术心得,欢迎骚扰交流.

  7. 获取任意微信公众号二维码方法

    [获取任意微信公众号二维码方法] 复制下面链接在浏览器里打开,iOS微信打开会报错. https://open.weixin.qq.com/qr/code?username=PlayerYK 将以上链 ...

  8. 在next主题添加微信公众号二维码

    在侧边栏添加微信公众号二维码 首先,当然是准备一张微信公众号二维码.有两种添加方式,添加到侧边栏或者添加到推文的结尾处.我的next主题是7.x版本的,使用的主题是Gemini,设置的侧栏显示方式是一 ...

  9. 如何给CSDN博客添加个人微信公众号二维码或自定义栏目

    公众号查看文章更清晰 在使用CSDN的过程中,可以看到有些博主的主页有个人微信二维码,微信公众号二维码等一些个人栏目信息.这对作者而言,可以让其他浏览博客的游客和作者进行更有效的沟通,也可以在这里对自 ...

最新文章

  1. R语言使用pROC包绘制ROC曲线实战:roc函数计算AUC值、plot.roc函数绘制ROC曲线、添加置信区间、为回归模型中的每个因子绘制ROC曲线并在同一个图中显示出来
  2. GIF动画 汇总帖子+实例
  3. 用一句sql语句更新两个表并可更新对应的字段的值
  4. A Faster Volatile
  5. IIS_FastCGI+php5.3+wincache+memcached+ZendLoader
  6. Flying框架思路与感想
  7. DropBox 超实用的免费文件网络同步、备份、分享工具
  8. Android项目源码(八个)
  9. 数据分析----数据清洗和准备
  10. soap python_Zeep: Python SOAP 客户端
  11. 修复Word打开文档默认显示两页的问题
  12. 【抽象代数】环、子环、理想、商环、环的同态
  13. EC20模块内置协议栈的开发笔记
  14. 市场调研—2021-2027全球与中国硬质托盘包装市场现状及未来发展趋势
  15. python爬虫防屏蔽_python爬虫程序如何预防被限制
  16. 软考高级系统架构设计师:特定领域软件架构
  17. 动漫推荐之境界的彼方
  18. 阿里云·数加,阿里下一代数据集成实践
  19. suse 15破解root密码
  20. java程序员从笨鸟到菜鸟_Java程序员从笨鸟到菜鸟之(十四)Html基础积累总结(上)...

热门文章

  1. C语言从入门到入土(三)
  2. 【天光学术】语言学论文:英语认知语言学和心理语言学的融通互补探析(节选)
  3. GitHub 标星 2.3k+,比个手势,AI 自动识别 Emoji!
  4. 跟计算机相关的商标类别,一体电脑商标注册属于第几类?
  5. java正则匹配下划线_正则表达式(匹配英文、中文、数字、下划线)
  6. 线程间共享 部分变量 Spring框架下向异步线程传递HttpServletRequest参数
  7. vue2+element ui 导入和导出后端传过来的文件
  8. python布尔系列_python-布尔运算
  9. Js 实现颜色值转换_Js 实现十六进制颜色值和RGB颜色值转换整理
  10. 顶级OCR神器:福昕扫描王使用全攻略|装机必备