一、前言
扫码前
扫码后
准备材料
-
已认证的公众号(必须为服务号,订阅号没有该接口的权限)
-
一个公网访问网址,用于微信回调
-
缓存或者数据库,用于存储token
-
一个SpringBoot项目
实现步骤一览
-
使用微信公众号(服务号)的appId和appSecret生成一个token,这个token可以复用,但是有时效性
-
使用token当做参数调用微信api:qrcode/create创建一个二维码
-
使用微信扫码,用户订阅后,微信官方会回调我们的一个地址,将openId传过来
-
将openId保存下来,下次扫描时根据openId进行判断用户身份
注意点
-
只有服务号才有生成带参数的二维码接口权限
-
该接口每天100000次,适用于小规模用户登录
-
获取的AccessToken有时效性,可以利用redis进行保存
-
公众号开发有白名单限制,所以服务端在调用时需要配置白名单
二、实现步骤
1. 公众号相关
(1)登录公众号,获取appId和appKey
(2)配置服务器回调地址
2. 服务端相关
(1)创建SpringBoot项目将复制下来的appId和appkey配置好,并加上一个redis
(2)由于微信的回调值格式是XML格式,所以需要一个解析工具类
java
package com.zzj.qlogin.utils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* 微信返回值解码工具类
*/
public class XmlUtil {
/**
* 简单解析xml
* @param in
* @return
*/
public static Map<String,Object> parseXML(InputStream in){
Map<String,Object> map=new HashMap<>();
try {
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(in);
Element root = document.getRootElement();
Iterator iterator = root.elementIterator();
while (iterator.hasNext()){
Element element = (Element) iterator.next();
map.put(element.getName(),element.getStringValue());
}
} catch (DocumentException e) {
e.printStackTrace();
}
return map;
}
}
(3)回调接口,此处需要区分两个不同的事件:订阅和扫码,简单的处理逻辑如下
java
/**
* 接收微信推送事件
* @param request
* @return
*/
@PostMapping("/handleWxCheckSignature")
@ResponseBody
public String handleWxEvent(HttpServletRequest request){
try {
InputStream inputStream = request.getInputStream();
Map<String, Object> map = XmlUtil.parseXML(inputStream);
String userOpenId = (String) map.get("FromUserName");
String event = (String) map.get("Event");
if("subscribe".equals(event)){
// TODO:获取openid判断用户是否存在,不存在则获取新增用户,自己的业务
//自己生成的二维码不管是关注还是扫码都能取到ticket凭证
String ticket = (String) map.get("Ticket");
redisCacheManager.set(ticket,ticket,10*60);
logger.info("用户关注:{}",userOpenId);
}else if("SCAN".equals(event)){
//自己生成的二维码不管是关注还是扫码都能取到ticket凭证
String ticket = (String) map.get("Ticket");
redisCacheManager.set(ticket,ticket,10*60);
logger.info("用户扫码:{}",userOpenId);
}
logger.info("接收参数:{}",map);
} catch (IOException e) {
e.printStackTrace();
}
return "success";
}
通过回调,微信会把当前扫码的用户的openid返回给我们,通过openid就可以获取用户信息了。