【企业微信】获取token & 发送应用消息

2023-05-16

企业微信获取token 存入redis 设置时长2小时 && 发送企业应用消息接口

1.常量类

package com.ruoyi.common.constant;

/**
 * 微信常用常量
 * @author chenkai
 */
public class WeChatConstants {

    /**
     * 获取企业微信access_token地址
     */
    public static final String BASE_URL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken";

    /**
     * 获取企业微信部门地址
     */
    public static final String DEPARTMENT_URL = "https://qyapi.weixin.qq.com/cgi-bin/department/list";

    /**
     * 企业微信推送消息地址
     */
    public static final String sendMessage_url = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=ACCESS_TOKEN";

    /**
     * 获取企业微信access_token组装URL
     */
    public static final String ACCESS_TOKEN_URL = BASE_URL + "?corpid=%s&corpsecret=%s";

    /**
     * 企业微信返回错误信息
     */
    public static final String ERRCODE = "errcode";

    /**
     * 企业微信token redis key
     */
    public static final String ACCESS_TOKEN = "access_token";

    /**
     * 企业微信agentSecret redis key
     */
    public static final String AGENT_SECRET = "agent_secret";

    /**
     * 企业微信corpID redis key
     */
    public static final String CORP_ID = "corp_id";




}

2.消息发送文本类

package com.ruoyi.system.domain.weChat;

import lombok.Data;

/**
 * 消息发送文本
 * @author chenkai
 */
@Data
public class TextMessage extends BaseMessage{
    /** 文本*/
    private Text text;
    /** 否 表示是否是保密消息,0表示否,1表示是,默认0*/
    private int safe;
}

3.企业微信发送基本参数类

package com.ruoyi.system.domain.weChat;

import lombok.Data;

/**
 * @author chenkai
 */
@Data
public class BaseMessage {
    /**否 成员ID列表(消息接收者,多个接收者用‘|’分隔,最多支持1000个)。特殊情况:指定为@all,则向该企业应用的全部成员发送*/
    private String touser;
    /**否 部门ID列表,多个接收者用‘|’分隔,最多支持100个。当touser为@all时忽略本参数*/
    private String toparty;
    /**否 标签ID列表,多个接收者用‘|’分隔,最多支持100个。当touser为@all时忽略本参数*/
    private String totag;
    /**是 消息类型*/
    private String msgtype;
    /**是 企业应用的id,整型。可在应用的设置页面查看*/
    private int agentid;

}

4.文本类

package com.ruoyi.system.domain.weChat;
import lombok.Data;

/**
 * 文本
 * @author 15553051722
 */
@Data
public class Text {
    /**是    消息内容,最长不超过2048个字节*/
    private String content;
}

5.接受入参类

package com.ruoyi.system.domain.weChat.DTO;

import lombok.Data;

/**
 * 企业微信发送消息实体类
 * @author chenkai
 */
@Data
public class MessageDTO {
    /**消息*/
    private String content;
    /**用户id*/
    private String userid;
    /**部门id*/
    private String toparty;
}

6.实现类

package com.ruoyi.system.service.impl;

import com.alibaba.fastjson2.JSON;
import com.google.gson.Gson;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.WeChatConstants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.system.domain.weChat.DTO.MessageDTO;
import com.ruoyi.system.domain.weChat.Text;
import com.ruoyi.system.domain.weChat.TextMessage;
import com.ruoyi.system.service.IEnterpriseWeChatService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.concurrent.TimeUnit;


/**
 * 企业微信实现类
 * @author chenkai
 */
@Service
public class EnterpriseWeChatServiceImpl implements IEnterpriseWeChatService {

    @Autowired
    private RedisCache redisCache;


   /**
     * 发送应用消息
     * 先从redis中获取 如获取不到或不可用 则重新获取
     * 并存入redis设置时长2小时 因为每天获取token的次数是有限的
     * @param messageDTO 消息内容 发送人 发送部门
     * @return accessToken
     */
    @Override
    public void weCharMessage(MessageDTO messageDTO) {
        if (StringUtils.isNull(messageDTO.getUserid())&&StringUtils.isNull(messageDTO.getToparty())){
            throw new ServiceException("发送人或发送部门最少选一个");
        }
        String url = WeChatConstants.sendMessage_url.replace("ACCESS_TOKEN", this.getAccessToken());
        // 2.获取发送对象,并转成json
        Gson gson = new Gson();
        Text text = new Text();
        //发送消息实体
        TextMessage textMessage = new TextMessage();
        //非必需
        textMessage.setTouser(messageDTO.getUserid());
        textMessage.setToparty(messageDTO.getToparty());
        //必须
        textMessage.setAgentid(1000002);
        //设置消息类型
        textMessage.setMsgtype("text");
        //存入消息文本
        text.setContent(messageDTO.getContent());
        //将消息文本存入实体
        textMessage.setText(text);
        String jsonMessage = gson.toJson(textMessage);
        Map response = (Map) JSON.parse(HttpUtils.sendPost(url,jsonMessage));
        //获取错误日志
        if (response.containsKey(WeChatConstants.ERRCODE) && (Integer) response.get(WeChatConstants.ERRCODE) != 0) {
            throw new ServiceException("消息发送失败", (Integer) response.get(WeChatConstants.ERRCODE));
        }
    }


    /**
     * 通过corpID获取AccessToken
     *
     * 从redis中获取accessToken如果为空
     * 或者当前accessToken校验失败
     * 则重新访问企业微信获取accessToken接口
     * 并存入redis
     * @return accessToken
     */
    @Override
    public String getAccessToken() {
        //获取redis里的accessToken
        String accessToken = redisCache.getCacheObject(getCacheKey(WeChatConstants.ACCESS_TOKEN));
        //redis中有并且redis中的token可正常使用就返回redis中的token
        //如果redis中没有 或者 redis中的token不可正常使用 则重新获取token
        if (StringUtils.isNotEmpty(accessToken) && this.isToken(accessToken)) {
            return accessToken;
        }
        //获取token必携带数据 corpId agentSecret 具体获取方法 查看企业微信api文档
        //之前手动存入redis 组装redisKey 从redis中获取
        String corpId = redisCache.getCacheObject(getCacheKey(WeChatConstants.CORP_ID));
        String agentSecret = redisCache.getCacheObject(getCacheKey(WeChatConstants.AGENT_SECRET));
        if (StringUtils.isEmpty(corpId) || StringUtils.isEmpty(agentSecret)) {
            throw new ServiceException("企业ID和应用secret不能为空");
        }
        //将企业微信获取accessTokenURL组装
        String getAccessTokenUrl = String.format(WeChatConstants.ACCESS_TOKEN_URL, corpId, agentSecret);
        //将访问企业微信接口 返回的String数据 转换成map
        Map response = (Map) JSON.parse(HttpUtils.sendGet(getAccessTokenUrl));
        //获取错误日志
        if (response.containsKey(WeChatConstants.ERRCODE) && (Integer) response.get(WeChatConstants.ERRCODE) != 0) {
            throw new ServiceException("获取token失败", (Integer) response.get(WeChatConstants.ERRCODE));
        }
         //获取token 并存入redis 设置时间两个小时
        accessToken = (String) response.get(WeChatConstants.ACCESS_TOKEN);
        redisCache.setCacheObject(getCacheKey(WeChatConstants.ACCESS_TOKEN), accessToken, 2, TimeUnit.HOURS);
        return accessToken;
    }




    /**
     * 校验token访问企业微信接口是否成功
     *
     * @param accessToken 参数键
     * @return 缓存键key
     */
    private boolean isToken(String accessToken) {
        Map department = (Map) JSON.parse(HttpUtils.sendGet(WeChatConstants.DEPARTMENT_URL, "access_token=" + accessToken));
        if (department.containsKey(WeChatConstants.ERRCODE) && (Integer) department.get(WeChatConstants.ERRCODE) != 0) {
            throw new ServiceException("token校验错误", (Integer) department.get(WeChatConstants.ERRCODE));
        }
        return true;
    }

    /**
     * 设置cache key
     *
     * @param configKey 参数键
     * @return 缓存键key
     */
    private String getCacheKey(String configKey) {
        return CacheConstants.SYS_CONFIG_KEY + configKey;
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【企业微信】获取token & 发送应用消息 的相关文章

  • JVM系列(八):堆(Heap)的相关知识介绍

    目录 1 JVM堆的概念 2 JVM堆的特点 3 JVM堆的内部结构 3 1 组成 3 2 堆内存内部空间所占比例 3 3 永久代和元空间区别 4 堆空间的大小设置 5 堆空间垃圾回收 1 JVM堆的概念 JVM中的堆是用来存放对象的内存空
  • C++读写TIF格式

    参考文章 xff1a xff08 1 xff09 https www cnblogs com gywei p 3393816 html xff08 2 xff09 https blog csdn net han jiang xue arti
  • matlab Fourier变换--方波信号的分解与重建

    N 61 200 采用的数据点数 dt 61 4 N 采样的间隔 for n 61 1 N 生成一个方波 if n dt gt 61 2 x n 61 0 8 else x n 61 0 8 end end figure subplot 2
  • matlab 小波分析--高通滤波器和低通滤波器

    xff08 一 xff09 加载一个尺度滤波器 load db8 w 61 db8 figure subplot 4 2 1 stem w title 39 原尺度滤波器 39 计算4个滤波器 Lo D Hi D Lo R Hi R 61
  • C/C++中rand() 函数产生随机数与srand()设置随机数种子

    xff08 1 xff09 rand 产生随机数 xff0c 输出的随机数序列是确定的 xff0c 即每次运行结果一致 include lt iostream gt int main int i j for i 61 0 i lt 10 i
  • matlab与数字图像处理--膨胀和腐蚀

    对于初学者 xff0c 参考一篇很好的说明 xff1a https blog csdn net alw 123 article details 83868878 左边是一个二值化的测试图像 xff0c 白色为图像元素 xff0c 黑色为背景
  • Emmet语法

    Emmet语法 1 1 快速生成HTML结构语法1 2 快速生成CSS样式语法1 3 快速格式化代码 Emmet语法的前身是Zen coding 它使用缩写 来提高html css的编写速度 Vscode内部已经集成该语法 快速生成HTML
  • CString,int,string,char*之间的转换

    C 43 43 标准函数库 中说的 有三个函数可以将字符串的内容转换为字符数组和C string 1 data 返回没有 0 的字符串数组 2 c str xff0c 返回有 0 的字符串数组 3 xff0c copy int 转 CStr
  • C++ TCP网络编程--服务器端多线程处理会话连接

    客户端程序 xff1a include lt winsock h gt include lt iostream gt pragma comment lib 34 ws2 32 lib 34 include lt Windows h gt i
  • matlab复杂函数多元函数拟合

    简介 本文介绍了基于matlab实现的复杂函数以及多元函数的拟合 在工程和研究中偶尔会遇到要用一个非常复杂的数学公式来拟合实验测量数据 xff0c 对这些复杂的数学公式拟合时 xff0c 采用常见的拟合方法往往会失败 xff0c 或者得不到
  • 基于模板替换的word文档自动生成

    简介 word文档自动生成程序是一个根据用户提供的模板word文档以及一些必要的数据文件来渲染生成所要的word文档的工具 关键词 xff1a 批量word文档生成 word文档渲染 自动生成word 使用场景 xff1a 几种典型的可以采
  • word文档-样例1-模板文档

  • word文档-样例1-结果文档

  • Omnibus F4V3 Pro飞控,APM飞控显示电池电压电流

    默认时 xff0c Omnibus F4 Pro烧写APM飞控后 xff0c 电池检测器没有设置的 想要屏幕上显示电池电压和电流信息 xff0c 就需要设置一下 设置信息如下 xff1a BATT MONITOR 61 4 然后重启 xff
  • 网络通信之大小端、字节序转换函数

    在上篇文章中我们提到了UDP xff0c TCP有关函数 xff0c 并知道了一个重要的结构体struct sockaddr 想要实现通信首先要知道通信端的地址 xff0c 所以首先了解一下IPv4套接字地址结构体 span class t
  • MAVROS +ardupilot +gazebo 无人机集群仿真 (一)

    MAVROS 43 ardupilot 43 gazebo 无人机集群仿真 xff08 一 xff09 无人机仿真环境搭建仿真软件安装仿真环境测试无人机多机仿真apm launch文件修改修改 iris ardupilot world修改
  • ubuntu搭建APT源简单方法

    一 为什么需要搭建APT源 原因如下 xff1a 1 在公司内网离线情况下 xff0c ubuntu无法通过apt原生源进行下载 2 有些源国内无法正常访问 xff0c 需要翻墙 基于以上原因 xff0c 需要自建APT源 二 准备条件 需
  • 输入IO、输出IO

    输入IO 这里所说的输入IO xff0c 指的是只作为输入 xff0c 不具有输出功能 此时对于input引脚的要求就是高阻 xff08 高阻与三态是同一个概念 xff09 基本输入电路的类型大致可以分为3类 xff1a 基本输入IO电路
  • 一句话搞懂奇偶校验

    一句话搞奇偶校验 一句话搞懂奇偶校验奇偶校验是啥一句话搞懂奇偶校验实例 一句话搞懂奇偶校验 奇偶校验是一种常见的校正数据错误的方式 奇偶校验是啥 奇偶校验是是数据传送时采用的一种校正数据错误的一种方式 xff0c 分为奇校验和偶校验两种 奇
  • LINUX下如何创建TCP客户端和服务器,实现通信

    TCP的客户端和服务器的创建 1 socket是属于LINUX下的进程间通信的一种方式BSD xff0c xff08 socket xff09 套接字 既可以实现同一台主机间的进程间通信 xff0c 也可以实现不同主机间的进程间通信 xff

随机推荐