Java 扫描微信公众号二维码,关注并自动登录网站
https://blog.csdn.net/qq_42851002/article/details/81327770
场景:用户扫描微信公众号的二维码,关注后自动登录网站,若已关注则直接登录。
逻辑:
1.系统生成带参数(此参数自定义为唯一值)的临时二维码(微信公众平台有提供该接口,可查看一下开发文档);
2.用户使用微信扫描该二维码,关注后微信服务器会将数据(自定义参数、openid…)返回到我们的服务器;
3.我们服务器将接收到的openid再次向微信服务器发起请求,获取该用户的信息(昵称、头像、地域、unionid(若绑定了微信开放平台,则有此参数));
4.我们将返回的用户信息存储到数据库,用作于登录。
准备工作:登录微信公众平台,在基本配置下,查看appid和设置appsecret、回调URL、token,小编这里使用的是测试账号

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_tocken
private 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转为map
private 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>
Java 扫描微信公众号二维码,关注并自动登录网站的更多相关文章
- java 扫描微信公众号二维码,关注并登录逻辑
场景:户扫描微信公众号的二维码,关注后自动登录网站,若已关注则直接登录. 逻辑: 系统生成带参数的临时二维码:参数 scene_str 自定义为唯一值(可以是uuid),临时二维码的生成方式参照官方接 ...
- 官网app下载更换成微信公众号二维码 测试
微信现在很火啊.公司官网原先提供的ios和andriod的app下载链接要求切换成微信公众号二维码.简单的替换,大家都说不需要测试直接上线.还是测了下. 1 验证所有与下载相关的信息都已去除. 包括下 ...
- 在next主题添加微信公众号二维码
在侧边栏添加微信公众号二维码 首先,当然是准备一张微信公众号二维码.有两种添加方式,添加到侧边栏或者添加到推文的结尾处.我的next主题是7.x版本的,使用的主题是Gemini,设置的侧栏显示方式是一 ...
- php微信生成微信公众号二维码扫描进入公众号带参数
https://blog.csdn.net/qq_22823581/article/details/80248555 <?php namespace app\api\model; set_tim ...
- Java 获取微信小程序二维码(可以指定小程序页面 与 动态参数)
一.准备工作 微信公众平台接口调试工具 小程序的唯一标识(appid) 小程序的密钥(secret) 二.获取access_token 打开微信公众平台接口调试工具,在参数列表中输入小程序的appid ...
- Java获取微信小程序二维码
tip:通过该接口,仅能生成已发布的小程序的二维码. tip:可以在开发者工具预览时生成开发版的带参二维码. tip:接口A加上接口C,总共生成的码数量限制为100,000,请谨慎调用. tip: P ...
- 微信小程序二维码是无法识别二维码跳转到小程序
今天测试了一下,微信小程序圆形二维码是不能直接识别跳转到小程序: 但h5页面的那种微信公众号二维码是可以直接识别
- Java开发微信公众号(二)---开启开发者模式,接入微信公众平台开发
接入微信公众平台开发,开发者需要按照如下步骤完成: 1.填写服务器配置 2.验证服务器地址的有效性 3.依据接口文档实现业务逻辑 资料准备: 1.一个可以访问的外网,即80的访问端口,因为微信公众号接 ...
- ESA2GJK1DH1K微信小程序篇: 测试微信小程序扫描Air202上面的二维码绑定设备,并通过MQTT控制设备
前言 一,微信小程序篇小程序下载(该功能为小程序篇基础功能源码) 实现功能概要 微信小程序通过扫描GPRS上的二维码,绑定GPRS设备.然后使用小程序通过GPRS远程控制开发板上的继电器, 远程显示单 ...
随机推荐
- find the mincost route【无向图最小环】
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1599 Problem Description 杭州有N个景区,景区之间有一些双向的路来连接,现在860 ...
- 小结Fragment与FragmentPagerAdapter的生命周期及其关系
本博客部分内容是来自http://blog.csdn.net/dreamzml/article/details/9951577 FragmentPagerAdapter FragmentPagerAd ...
- sql数据库的基础语句
1, 创建数据库 create database database-name 2, 删除数据库 drop database dbname 3, 备份sql server 创建 备份数据的device ...
- Shell脚本之流程控制(if、for、while)
if 判断 if语句的三种格式: (1)if (2)if else (3)if elif else 语法格式如下: #if 语法格式 if 条件 then 命令1... 命令2... fi #if e ...
- 如何使用RedisTemplate访问Redis数据结构之字符串操作
Redis 数据结构简介 Redis 可以存储键与5种不同数据结构类型之间的映射,这5种数据结构类型分别为String(字符串).List(列表).Set(集合).Hash(散列)和 Zset(有序集 ...
- Linux IO模式以及select poll epoll详解
一 背景 同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,到底有什么区别?不同的人在不同的上下文下给出的答案是不同的.所以先限定一下本文的上下文. 本文讨论的背景是Linux环境下的network ...
- ecshop二次开发笔记
1. robots.txt 爬虫协议 网站通过Robots协议告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取. 2. 入口文件 index.php 3. 目录结构分析 admin 后台 api 接口 ...
- Python list,tuple,dict,set高级变量常用方法
list列表 增加 append 在列表中追加,一次只能加一个 insert 按索引插入,一次只能插一个 extend 迭代追加到列表中 list1 = [1, 2, 3] list2 = [4, 5 ...
- 笔记-3:mysql数据定义
1.定义数据库 1.1 创建数据库:创建数据库是在系统磁盘上划分一块区域用于数据的存储和管理. # 基本语法: create {database | schema} [if not exists] d ...
- 第九章 MIZ702 ZYNQ片上ADC的使用
9.0难度系数★☆☆☆☆☆☆ 9.1实验概述 这次借助zynq的内嵌的XADC来采集zynq内部的一些参数: •VCCINT:内部PL核心电压 •VCCAUX:辅助PL电压 •VREFP:XADC ...