我的小程序之旅五:微信公众号扫码登录PC端网页
代码仓库:https://gitee.com/wlovet/gzh-qrlogin
一、准备材料
1、已认证的公众号(必须为服务号,订阅号没有该接口的权限)
2、一个网址,用于微信回调,推荐一个内网穿透的工具:内网穿透
3、Redis,用于存储token
4、一个SpringBoot项目
二、实现原理
1、使用微信公众号(服务号)的appId和appSecret生成一个token,这个token可以复用,但是有时效性
2、使用token当做参数调用微信api:qrcode/create创建一个二维码
3、使用微信扫码,用户订阅后,微信官方会回调我们的一个地址,将openId传过来
4、将openId保存下来,下次扫描时根据openId进行判断用户身份
三、注意点
1、只有服务号才有生成带参数的二维码接口权限
2、该接口每天100000次,适用于小规模用户登录
3、获取的AccessToken有时效性,可以利用redis进行保存
4、公众号开发有白名单限制,所以服务端在调用时需要配置白名单
四、实现步骤
公众号相关
1、登录公众号,获取appId和appKey
2、配置服务器回调地址
服务端相关
1、创建SpringBoot项目将复制下来的appId和appkey配置好,并加上一个redis
2、由于微信的回调值格式是XML格式,所以需要一个解析工具类
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、回调接口,此处需要区分两个不同的事件:订阅和扫码,简单的处理逻辑如下
/** * 接收微信推送事件 * @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"; }
本文来自博客园,作者:sum墨,转载请注明原文链接:https://www.cnblogs.com/wlovet/p/15843470.html