PC端微信扫码关注公众号并登录

 

碰到这样一个需求,PC端生成公众号二维码,用户用手机微信扫描,如果用户未关注公众号,则关注公众号后自动登录,如果用户已经关注过公众号,则直接登录。

前端Vue,后端Java实现

分2步来完成:

1.生成带参数的临时二维码

https://developers.weixin.qq.com/doc/offiaccount/Account_Management/Generating_a_Parametric_QR_Code.html

 

2. 公众号后台服务监听扫码事件并获取用户信息

https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_event_pushes.html

https://developers.weixin.qq.com/doc/offiaccount/User_Management/Get_users_basic_information_UnionID.html#UinonId

1.生成带参数的临时二维码

获取临时二维码的接口为微信官方提供的 

https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN,注意为POST方式

@RequestMapping("/getQRCode")
    public Map<String,Object> getQRCode(HttpServletRequest request,String code) {
		Map<String,Object> map = new HashMap<String,Object>();
		String code_url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN";
		try{
            //获取公众号的Token,自行实现,我是定任务获取,存到了数据库
			PcAccessToken token = accessTokenService.findPcToken("");
			code_url = code_url.replace("TOKEN", token.getAccessToken());
			String scene_id = (System.currentTimeMillis()+"").substring(0,10);
			JSONObject json = new JSONObject();
			json.put("expire_seconds", "36000");
			json.put("action_name", "QR_SCENE");
			JSONObject info = new JSONObject();
			JSONObject scen = new JSONObject();
			scen.put("scene_id", scene_id);
			info.put("scene", scen);
			json.put("action_info", info);
			String data = HttpUtil.requestPost(code_url, json.toString());
			JSONObject resp = JSONObject.fromObject(data);
			System.out.println("data=="+data);
			map.put("data", resp);
			map.put("scene_id", scene_id);
			map.put("succ", "1");
		} catch(Exception e){
			map.put("succ", "0");
			e.printStackTrace();
		}
        return map;
    }

请求微信接口返回的数据,url参数即为二维码地址,和scene_id一起返回给前端。

前端vue使用 qrcodejs2组件,将url转为二维码图片,显示在相应位置。请求到二维码后,用sceneId查询扫码登录是否成功。


<div class="" id="qrcode" ref="qrcode"></div>

import QRCode from 'qrcodejs2'
import loginApi from '@/api/login';
  data(){
    return{
      url: '', //二维码地址
      sceneId:'',//二维码带的参数,用来判断是那个用户扫码的
      timer: null,//定时器
    }
  },
  created(){
    getLoginQRCode();
  },
  methods:{
    async getLoginQRCode(){
      this.url = '';
      window.clearInterval(this.timer);
      const res = await loginApi.getQRCode();
      console.log('44res',res)
      if(res.data.succ == '1'){
        this.url = res.data.data.url;
        this.sceneId = res.data.scene_id;
        console.log('sceneId',res.data.scene_id);
        this.timer = setInterval(this.getUserByScene, 1000);
        this.$nextTick(() => {
          this.getQrcode(this.url)
        })
      }
    },
    //根据 sceneId 轮询查询用户信息,判断用户是否登录成功
    async getUserByScene(){
      if(!this.sceneId) return;
      const res = await loginApi.getUserBySceneId({sceneId: this.sceneId});
      console.log('getUser', res);
      if(res.data.succ == '1' && res.data.user){
        this.user = res.data.user;
        window.clearInterval(this.timer);
        this.url = '';
        this.sceneId = '';
        //登录成功,处理登录成功逻辑
        this.$Message.success('登录成功')
      }
    },
    getQrcode (text) {
      this.$refs.qrcode.innerHTML = '' // 清除
      const qrcode = new QRCode('qrcode', {
        width: 160,
        height: 160,
        text: text, // 二维码地址
        colorDark: '#000',
        colorLight: '#fff'
      })
      return qrcode
    },
  }
	

2.公众号后台服务监听扫码事件并获取用户信息

这块要在微信公众平台配置服务地址信息

开发—基本配置

å¨è¿éæå¥å¾çæè¿°å¨è¿éæå¥å¾çæè¿°

服务器配置信息提交的时候要验证 TOKEN,  验证通过才能提交。checkToken接口GET请求用来验证TOKEN,

import java.security.MessageDigest;
//...
@RequestMapping(value="/checkToken",method=RequestMethod.GET)
    public String  checkToken(HttpServletRequest req, HttpServletResponse resp)throws IOException {
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        String message = "success";
        String signature = req.getParameter("signature");
        String timestamp = req.getParameter("timestamp");
        String nonce = req.getParameter("nonce");
        String echostr = req.getParameter("echostr");
        try {
        	String[] arr = {"sjyx", timestamp, nonce};
            Arrays.sort(arr);

            StringBuilder content = new StringBuilder();
            for (int i = 0; i < arr.length; i++) {
                content.append(arr[i]);
            }
            //sha1Hex 加密
            MessageDigest md = null;
            String temp = null;
            md = MessageDigest.getInstance("SHA-1");
            byte[] digest = md.digest(content.toString().getBytes());
            temp = byteToStr(digest);
            if ((temp.toLowerCase()).equals(signature)){
                return echostr;
            }
            return null;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return message;
	}
	 private static String byteToStr(byte[] byteArray){
        String strDigest = "";
        for (int i = 0; i < byteArray.length; i++) {
            strDigest += byteToHexStr(byteArray[i]);
        }
        return strDigest;
    }
    private static String byteToHexStr(byte mByte){
        char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A','B', 'C', 'D', 'E', 'F' };
        char[] tempArr = new char[2];
        tempArr[0] = Digit[(mByte >>> 4)& 0X0F];
        tempArr[1] = Digit[mByte & 0X0F];
        String s = new String(tempArr);
        return s;
    }

checkToken接口POST请求用来监听扫码事件,并获取用户信息

  @RequestMapping(value="/checkToken",method=RequestMethod.POST)
  public String  responseEvent(HttpServletRequest req, HttpServletResponse resp) {
      String message = "success";
      try {
          //把微信返回的xml信息转义成map
          Map<String, String> map = XmlUtil.xmlToMap(req);
          System.out.println("微信接收到的消息为:"+map.toString());
          String openId = map.get("FromUserName");//消息来源用户标识
          String toUserName = map.get("ToUserName");//消息目的用户标识
          String msgType = map.get("MsgType");//消息类型(event或者text)
          String EventKey = map.get("EventKey");//消息来源用户标识
          if(EventKey.contains("_")){ //scene_id首次关注会有前缀,去掉就和生成二维码时带的一致了
            EventKey = EventKey.split("_")[1];
          }
          String scene_Id = EventKey;
          String eventType = map.get("Event");//事件类型
          if("subscribe".equals(eventType) || "SCAN".equals(eventType) ){ //关注  or 浏览
            //获取缓存的最新的公众号 token
            PcAccessToken token = accessTokenService.findPcToken("");
            String USER_INFO_URL = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
            USER_INFO_URL = USER_INFO_URL.replace("ACCESS_TOKEN", token.getAccessToken());
            USER_INFO_URL = USER_INFO_URL.replace("OPENID", openId);
            String info = HttpUtil.getRequest(USER_INFO_URL);
            System.out.println("----user-----"+info);
            JSONObject obj = JSONObject.fromObject(info);
            String unionid = obj.getString("unionid");
            String nickname = obj.getString("nickname");
            String headimgurl = obj.getString("headimgurl");
            String city = obj.getString("city");
            String province = obj.getString("province");
            String qr_scene = obj.getString("qr_scene");
            //获取到用户信息后处理登录逻辑,比如保存用户信息,用户表scene_id 字段,保存二维码的scend_id,供前端查询用户登录情况。
          }
      } catch (Exception e) {
          e.printStackTrace();
      }
      return message;
  }

xml转Map工具类 

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class XmlUtil {
	/*
	 * xml转map
	 */
	public static Map<String, String> xmlToMap(HttpServletRequest request) throws IOException, DocumentException{
		HashMap<String, String> map = new HashMap<String,String>();
		SAXReader reader = new SAXReader();
 
		InputStream ins = request.getInputStream();
		Document doc = reader.read(ins);
 
		Element root = doc.getRootElement();
		@SuppressWarnings("unchecked")
		List<Element> list = (List<Element>)root.elements();
 
		for(Element e:list){
			map.put(e.getName(), e.getText());
		}
		ins.close();
		return map;
	}
}

 

  • 5
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,以下是一个基于Spring Boot的微信扫码登录示例: 1. 首先,需要在微信公众平台中创建一个开发者账号,并创建一个公众号。 2. 在Spring Boot项目中添加以下依赖: ``` <dependency> <groupId>com.github.binarywang</groupId> <artifactId>weixin-java-mp</artifactId> <version>3.4.</version> </dependency> ``` 3. 在application.properties中配置微信公众号的相关信息: ``` wechat.mp.appId=your_app_id wechat.mp.secret=your_secret wechat.mp.token=your_token wechat.mp.aesKey=your_aes_key ``` 4. 创建一个Controller,用于处理微信扫码登录的请求: ``` @RestController public class WechatLoginController { @Autowired private WxMpService wxMpService; @GetMapping("/wechat/login") public String wechatLogin(HttpServletRequest request, HttpServletResponse response) throws Exception { String redirectUrl = "http://your_domain.com/wechat/callback"; String state = UUID.randomUUID().toString(); String url = wxMpService.oauth2buildAuthorizationUrl(redirectUrl, WxConsts.OAuth2Scope.SNSAPI_USERINFO, state); response.sendRedirect(url); return null; } @GetMapping("/wechat/callback") public String wechatCallback(HttpServletRequest request, HttpServletResponse response) throws Exception { String code = request.getParameter("code"); String state = request.getParameter("state"); WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code); WxMpUser user = wxMpService.oauth2getUserInfo(accessToken, null); // TODO: 处理用户信息 return "success"; } } ``` 5. 在微信公众平台中配置授权回调域名为http://your_domain.com,并将http://your_domain.com/wechat/callback添加到网页授权域名中。 6. 启动Spring Boot应用,访问http://your_domain.com/wechat/login即可进行微信扫码登录。 希望这个示例能够帮助到你!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值