企业微信扫码登陆-详细案例

news2024/11/16 18:46:10

以下是实现的pc端企微扫码登陆,话不多时,直接上代码。。。

第1步:企业微信自建应用
在这里插入图片描述
第二步:获取到之后拿到在这里插入图片描述

整体流程:
1.企业发起授权登录请求,企业微信用户允许授权后,企业微信会重定向到企业网站,并且带上授权临时票据code参数;
2.然后企业应用通过 corpid 和 corpsecret 获取access_token ;
3.企业应用通过 access_token 和 code 获取用户身份,进入相应的系统。

相关的代码 如下:
1.通过后端获取到信息,前端加载二维码

   /**
     * 加载二维码
     *
     * @return
     */
    @GetMapping("getWecom")
    @ApiOperation("企微登陆获取二维码信息")
    @ResponseBody
    public AjaxResult getErWeiMa() throws UnsupportedEncodingException {
        AjaxResult res = new AjaxResult();
        res.setData(qwWeiXinUtil.loginGetErWeiMa());
        return res;
    }

2.根据返回的code与accessToken获取用户信息

@GetMapping("loginQwOrGetInfo")
    @ApiOperation("回调并获取用户信息")
    public AjaxResult getCode(HttpServletRequest request, String code) {
        if(StringUtils.isEmpty(code)){
            AjaxResult.error("请重新扫码登陆");
        }
        try {
        AjaxResult ajax = AjaxResult.success();
        //todo 此处是前端传入code
        String userId = qwWeiXinUtil.getUserID(code);
        WeiXinUserInfoDTO weiXinUserInfoDTO = qwWeiXinUtil.getUserInfo(userId);
        //获取到手机号并与库中关联并生成令牌
        String token = loginService.loginByWecom(weiXinUserInfoDTO.getMobile());
        log.info(token);
        ajax.setData(token);
        return ajax;
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }

以下是用到的相关的工具类

package com.cogo.framework.util;

import com.alibaba.fastjson.JSONObject;
import com.cogo.common.core.redis.RedisCache;
import com.cogo.common.utils.StringUtils;
import com.cogo.core.domain.vo.WeiXinLoginDTO;
import com.cogo.core.domain.vo.WeiXinUserInfoDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class QwWeiXinUtil {
    @Autowired
    private RedisCache redisCache;

    @Autowired
    private  WecomUtil wecomUtil;

    /**
     * 获取用户ID
     *
     * @param accessToken
     * @param code
     * @return
     */
    public  String getUserIDByToken(String accessToken, String code) {
        //1.获取请求的url
        String url = wecomUtil.getUserIDUrl.replace("ACCESS_TOKEN", accessToken)
                .replace("CODE", code);
        //2.调用接口,发送请求,获取成员
        JSONObject jsonObject = SendRequest.sendGet(url);

        //3.错误消息处理
        if (null != jsonObject && 0 != jsonObject.getIntValue("errcode")) {
            log.error("获取成员失败 errcode:{} errmsg:{}", jsonObject.getIntValue("errcode"), jsonObject.getString("errmsg"));
        } else {
            log.info("用户ID:" + jsonObject.getString("UserId"));
            log.info("OpenID:" + jsonObject.getString("OpenId"));
            if (!StringUtils.isEmpty(jsonObject.getString("UserId"))) {
                return jsonObject.getString("UserId");
            } else if (jsonObject.getString("OpenId") != null) {
                log.info("该用户不是本企业人员,OpenID为:" + jsonObject.getString("OpenId"));
                return null;
            }
        }
        return null;
    }

    /**
     * 初始加载二维码
     *
     * @return
     * @throws UnsupportedEncodingException
     */
    public  WeiXinLoginDTO loginGetErWeiMa() throws UnsupportedEncodingException {
        String redirect_uri = URLEncoder.encode(wecomUtil.redirectUri, "utf-8");
        WeiXinLoginDTO weiXinLoginDTO = new WeiXinLoginDTO();
        weiXinLoginDTO.setAppid(wecomUtil.appId);
        weiXinLoginDTO.setAgentid(wecomUtil.agentId);
        weiXinLoginDTO.setRedirectUri(redirect_uri);
        return weiXinLoginDTO;
    }

    /**
     * 获取token
     *
     * @return
     */
    public  String getToken() {
        String token = getFirstAccessToken(wecomUtil.appId, wecomUtil.secret);
        redisCache.setCacheObject("qwChatToken", token, 100, TimeUnit.SECONDS);
        return token;
    }

    /**
     * 获取token
     *
     * @param appid
     * @param appsecret
     * @return
     */
    public  String getFirstAccessToken(String appid, String appsecret) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String saveDate = sdf.format(new Date());
        log.info("获取微信TOKN请求开始,当前时间:" + saveDate);
        String requestUrl = wecomUtil.accessTokenUrl.replace("{corpId}", appid)
                .replace("{corpsecret}", appsecret);
        JSONObject jsonObject = SendRequest.sendGet(requestUrl);
        // 如果请求成功
        if (null != jsonObject && jsonObject.getIntValue("errcode") == 0) {
            try {
                log.info("获取的token: " + jsonObject.getString("access_token"));
                log.info("时间" + saveDate);
                return jsonObject.getString("access_token");
            } catch (Exception e) {
                // 获取token失败
                log.error("获取token失败 errcode:{} errmsg:{}",jsonObject.getString("errmsg"));
            }
        } else {
            log.error("获取token失败 errcode:{} errmsg:{}",jsonObject.getString("errmsg"));
        }
        return null;
    }

    /**
     * 获取用户
     *
     * @param accessToken
     * @param userId
     * @return
     */
    public  WeiXinUserInfoDTO getUserInfoByID(String accessToken, String userId) {
        //1.获取请求的url
        String url = wecomUtil.getUserUrl.replace("ACCESS_TOKEN", accessToken)
                .replace("USERID", userId);
        //2.调用接口,发送请求,获取成员
        JSONObject jsonObject = SendRequest.sendGet(url);

        //3.错误消息处理
        if (null != jsonObject && 0 != jsonObject.getIntValue("errcode")) {
            log.error("获取成员失败 errcode:{} errmsg:{}", jsonObject.getIntValue("errcode"), jsonObject.getString("errmsg"));
        } else {
            log.info("用户ID:" + jsonObject.getString("userid"));
            log.info("用户名称:" + jsonObject.getString("name"));
            log.info("用户手机号:" + jsonObject.getString("mobile"));
            log.info("用户邮箱:" + jsonObject.getString("email"));
            WeiXinUserInfoDTO weiXinUserInfoDTO = new WeiXinUserInfoDTO();
            weiXinUserInfoDTO.setUserid(jsonObject.getString("userid"));
            weiXinUserInfoDTO.setName(jsonObject.getString("name"));
            weiXinUserInfoDTO.setMobile(jsonObject.getString("mobile"));
            weiXinUserInfoDTO.setEmail(jsonObject.getString("email"));
            weiXinUserInfoDTO.setAvatar(jsonObject.getString("avatar"));//头像
            weiXinUserInfoDTO.setEnable(jsonObject.getString("enables"));//成员启用状态。1表示启用的成员,0表示被禁用。注意,服务商调用接口不会返回此字段
            return weiXinUserInfoDTO;
        }
        return null;
    }

    /**
     * 获取用户ID
     *
     * @param code
     */
    public  String getUserID(String code) {
        log.info("code:" + code);
        //逻辑判断token是否过期,如果过期刷新,没有过期直接拿来使用
        Object qwChatToken = redisCache.getCacheObject("qwChatToken");
        String token =qwChatToken !=null ? qwChatToken.toString() : this.getToken();
        return this.getUserIDByToken(token, code);
    }

    /**
     * 获取用户信息
     *
     * @param userId
     * @return
     */
    public  WeiXinUserInfoDTO getUserInfo(String userId) {
        //逻辑判断token是否过期,如果过期刷新,没有过期直接拿来使用
        String token = this.getToken();
        //根据userID和token获取用户的基本信息
        WeiXinUserInfoDTO weiXinUserInfoDTO = this.getUserInfoByID(token, userId);
        return weiXinUserInfoDTO;
    }
}


获取配置的工具类

package com.cogo.framework.util;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

/**
 * 微信配置
 *
 * @author wangjunjie
 * @version 1.0
 * @date 2023/5/30 20:50
 */
@Configuration
public class WecomUtil {
    //企业ID
    @Value("${qwchat.appId}")
    public String appId;

    //应用AgentId
    @Value("${qwchat.agentId}")
    public  String agentId;

    //第三方网站指定自己的端口
    @Value("${qwchat.redirectUri}")
    public  String redirectUri;

    @Value("${qwchat.secret}")
    public  String secret;

    public  String accessTokenUrl;

    @Value("${qwchat.accessTokenUrl}")
    public void setAccessTokenUrl(String accessTokenUrl) {
        this.accessTokenUrl = accessTokenUrl;
    }

    public String getUserIDUrl;

    @Value("${qwchat.getUserIDUrl}")
    public void setGetUserIDUrl(String getUserIDUrl) {
        this.getUserIDUrl = getUserIDUrl;
    }

    public  String getUserUrl;

    @Value("${qwchat.getUserUrl}")
    public void setGetUserUrl(String getUserUrl) {
        this.getUserUrl = getUserUrl;
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/712907.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Windows基于WSL搭建Python数据分析环境

最近配置了一台较为不错的台式机,记录下自己配置环境的过程。 安装WSL,提供Linux环境 如果你发现后续的命令无法运行或者说软件商城中找不到,这可能意味着你的操作系统不符合要求。WSL安装要求 Windows 10 version 2004(Build 19…

C++之H数回信

void H数(int 数) {int Lin 数;while (Lin>1){if (!(Lin % 2) || !(Lin % 3) || !(Lin % 5) || !(Lin % 7)){if (!(Lin % 2))Lin / 2;else if (!(Lin % 3))Lin / 3;else if (!(Lin % 5))Lin / 5;else if (!(Lin % 7))Lin / 7;}else return;}cout << 数 << ends…

Proxmox 8.0 “Virtual Environment”发布

导读Proxmox发布新产品Proxmox VE8.0&#xff0c;基于Debian 12.该版本集成了新的Linux内核6.2、QEMU 8.0.2、LXC 5.0.2和OpenZFS 2.1.12&#xff0c;并且还有其他一些新功能和改进。 更新的部分包括更新的Ceph服务器、安装程序ISO增加基于文本的用户界面、整合主机网络桥和VN…

STM32 Proteus UCOSII系统DS1302万年历时钟秒表控制系统-0056

STM32 Proteus UCOSII系统DS1302万年历时钟秒表控制系统-0056 Proteus仿真小实验&#xff1a; STM32 Proteus UCOSII系统DS1302万年历时钟秒表控制系统-0056 功能&#xff1a; 硬件组成&#xff1a;STM32F103R6单片机 LCD1602显示器多个按键DS1302北京时间 1.单片机程序使…

java 分布式事务seata的使用

首先创建一个seata的springboot模块并引入seata的起步依赖 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId> </dependency>模块的目录结构如下 seata.yaml中的内容为&…

vscode高亮插件——highlight-words(高亮代码、高亮变量、突出显示)

文章目录 官方教程高亮文字使用方法配置 演示变量高亮&#xff08;Highlight Toggle Current&#xff09;选择高亮&#xff08;Highlight Selection with Options&#xff09;删除高亮&#xff08;Highlight Remove&#xff09;侧边栏&#xff08;Highlight Toggle Sidebar&…

软件测试用例编写规范文档,模板都给你了我看谁还不会写测试用例

目录 前言 一 概述 1.1目的 1.2使用范围 二 测试用例编写原则 2.1系统性 2.2连贯性 2.3全面性 三 测试用例设计方法 3.1 等价类划分法&#xff1a; 3.2 边界值分析法&#xff1a; 3.3 因果图法&#xff1a; 3.4功能图法 3.5错误推测法 四 测试用例编写规范 4.1…

【ARM】-指令预取中止异常中断处理程序的返回

文章目录 处理流程示例 处理流程 在指令预取时&#xff0c;如果目标地址是非法的&#xff0c;该指令被标记成有问题的指令。这时&#xff0c;流水线上该指令之前的指令继续执行。当执行到该被标记成有问题的指令时&#xff0c;处理器产生指令预取中止异常中断。 当发生指令预取…

解决进入虚拟环境venv后pip路径仍然是在全局路径usr/bin下的问题

问题 解决方法 尝试手动安装pip到你的虚拟环境中。首先&#xff0c;确保在虚拟环境中运行以下命令&#xff1a; python -m ensurepip然后&#xff0c;使用以下命令安装pip到你的虚拟环境中&#xff1a; python -m pip install --upgrade pip

XR-FRAME 开始

目录 新建一个XR组件在页面中使用这个组件添加一个物体来点颜色和灯光有点寡淡&#xff0c;加上图像让场景更丰富&#xff0c;环境数据动起来&#xff0c;加入动画还是不够&#xff0c;放个模型再来点交互组件通信&#xff0c;加上HUD虚拟 x 现实&#xff0c;追加AR能力识别人脸…

ChatGLM6B LORA微调

ChatGLM6B&ChatGLM2-6B微调 目录 ChatGLM6B&ChatGLM2-6B微调 微调硬件需求 3.1. LoRA概述 3.2. LoRA微调ChatGLM步骤 3.2.1. 项目和环境搭建 3.2.2. 数据集处理 3.2.3. 微调 3.2.4. 推理 3.2.5. 完整过程 3.3. LoRA微调ChatGLM步骤-——huggingface PEFT 3.3.1. 项目和…

通过动态地址解决网络数据采集问题

动态地址的作用 说到Python网络爬虫&#xff0c;很多人都会遇到困难。最常见的就是爬取过程中IP地址被屏蔽。虽然大部分都是几个小时内自动解封的&#xff0c;但这对于分秒必争的python网络爬虫来说&#xff0c;是一个关键性的打击&#xff01;当一个爬虫被阻塞时&#xff0c;…

Qt项目环境构建

工欲善其事必先利其器&#xff0c;使用Qt来进行开发&#xff0c;得先配置好一个合适的环境。下面是我关于Qt项目环境构建的一些小结 Qt的项目构建主要依赖.pro文件&#xff08;和.pri文件&#xff1a;include包含文件&#xff0c;提供pro的复用性高的东西给多个项目包含) 所以新…

【企业架构框架】Mitre 架构联邦

定义&#xff1a; 架构联合是用于企业架构开发、维护和使用的框架&#xff0c;它对齐、定位和链接分离但相关的架构和架构信息&#xff0c;以向用户提供无缝的外观。 关键词&#xff1a; 企业架构&#xff0c;联邦架构&#xff0c;适合联邦&#xff0c;语义对齐&#xff0c;分层…

想要做好联络口译,需要掌握哪些技能?

据了解&#xff0c;联络口译员经常需要陪在外宾或者委托人身边出席各种各样的活动&#xff0c;除了翻译工作之外&#xff0c;有时还要兼任接待、导游等工作。那么&#xff0c;想要做好联络口译工作&#xff0c;需要掌握哪些技能&#xff1f; 首先&#xff0c;熟悉中外文化差异及…

在页面里面引入外部网页或者vue的其他页面组件

<div id"iframe-container"><iframe :src"iframeUrl" width"100vw" height"100vh" v-if"flagTwo"></iframe> </div>//可以是路径也可以是网络链接 data(){ return{iframeUrl :, }this.iframeUrl h…

从0到1精通自动化测试,pytest自动化测试框架,Hooks函数获取用例执行结果(二十三)

一、前言 pytest提供的很多钩子(Hooks)方法方便我们对测试用例框架进行二次开发&#xff0c;可以根据自己的需求进行改造 先学习下pytest_runtest_makereport这个钩子方法&#xff0c;可以更清晰的了解用例的执行过程&#xff0c;并获取到每个用例的执行结果 二、pytest_run…

【Part 1】现在去博物馆都预约不上了,黑产多少有点疯狂了

近几年不知道为啥&#xff0c;突然兴起博物馆热了&#xff0c;去某个城市&#xff0c;总想去当地的博物馆去打卡&#xff08;当然&#xff0c;可能重点还在打卡&#xff09;。但是周末去湖南省博物馆&#xff0c;发现免费的博物馆&#xff0c;现在已经预约不上了&#xff0c;最…

python面向对象编程学习1

python面向对象的基本要点&#xff0c; 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。 使用 class 语句来创建一个新类&#xff0c;class 之后为类的名称并以冒号结尾&#xff1b; __init__()方…

lammps教程:固定边界丢失原子的几种解决办法

我是小马老师&#xff0c;本文介绍固定边界丢失原子的几种解决办法。 在lammps摩擦、润湿、冲击等模拟中&#xff0c;z方向多设为固定的f边界&#xff0c;如何设置不合理&#xff0c;会出现丢失原子的情况。 1.原因分析 以切削模拟为例&#xff0c;边界条件设为ppf&#xff…