企业微信机器人java代码对接

news2024/10/5 21:15:40

如何使用群机器人

假设webhook是:https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=693a91f6-7xxx-4bc4-97a0-0ec2sifa5aaa
特别特别要注意:一定要保护好机器人的webhook地址,避免泄漏!不要分享到github、博客等可被公开查阅的地方,否则坏人就可以用你的机器人来发垃圾消息了。
以下是用curl工具往群组推送文本消息的示例(注意要将url替换成你的机器人webhook地址,content必须是utf8编码):

curl 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=693axxx6-7aoc-4bc4-97a0-0ec2sifa5aaa' \
   -H 'Content-Type: application/json' \
   -d '
   {
    	"msgtype": "text",
    	"text": {
        	"content": "hello world"
    	}
   }'

我们发现msgtype字段是通用的封装。所以可以构建一个父级类WebhookBody:

@Getter
public abstract class WebhookBody {

    private final String msgtype;

    /**
     * 构造函数
     *
     * @param msgtype 消息类型
     */
    protected WebhookBody(String msgtype) {
        this.msgtype = msgtype;
    }

}

text消息体WebhookTextBody类:

@EqualsAndHashCode(callSuper = true)
@ToString
@Getter
public class WebhookTextBody extends WebhookBody {

    private final WebhookText text;

    /**
     * Instantiates a new Webhook text body.
     *
     * @param text the text
     */
    WebhookTextBody(WebhookText text) {
        super("text");
        this.text = text;
    }

    /**
     * From webhook text body.
     *
     * @param content the content
     * @return the webhook text body
     */
    public static WebhookTextBody from(String content, List<String> mentionedList,
                                       List<String> mentionedMobileList) {
        WebhookText webhookText = new WebhookTextBody.WebhookText(content);
        webhookText.setMentionedList(mentionedList);
        webhookText.setMentionedMobileList(mentionedMobileList);
        return new WebhookTextBody(webhookText);
    }


    @ToString
    @Getter
    @Setter
    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
    public static class WebhookText {
        /**
         * 消息内容
         */
        private final String content;
        /**
         * 被@人的列表,若为空则不会@人
         */
        private List<String> mentionedList;
        /**
         * 被@人的手机列表,若为空则不会@人
         */
        private List<String> mentionedMobileList;
    }

图片类型

在这里插入图片描述

{
    "msgtype": "image",
    "image": {
        "base64": "DATA",
		"md5": "MD5"
    }
}

图片封装WebhookImgBody:

@EqualsAndHashCode(callSuper = true)
@ToString
@Getter
public class WebhookImgBody extends WebhookBody {

    private final ContentImage image;

    @ToString
    @Getter
    public static class ContentImage {

        private final String base64;

        private final String md5;

        public ContentImage(String base64, String md5) {
            this.base64 = base64;
            this.md5 = md5;
        }
    }


    WebhookImgBody(ContentImage image) {
        super("image");
        this.image = image;
    }

    /**
     * From webhook text body.
     *
     * @return the webhook text body
     */
    public static WebhookImgBody from(InputStream inputStream) {
        //base64编码
        byte[] bytes = IoUtil.readBytes(inputStream);
        String encode = Base64.encode(bytes);
        //md5
        String md5 = MD5.create().digestHex(bytes);
        ContentImage image = new ContentImage(encode, md5);
        return new WebhookImgBody(image);
    }

}

MarkDown消息

{
    "msgtype": "markdown",
    "markdown": {
        "content": "实时新增用户反馈<font color=\"warning\">132例</font>,请相关同事注意。\n
         >类型:<font color=\"comment\">用户反馈</font>
         >普通用户反馈:<font color=\"comment\">117例</font>
         >VIP用户反馈:<font color=\"comment\">15例</font>"
    }
}

MarkDown 的消息体WebhookMarkDownBody类:

@EqualsAndHashCode(callSuper = true)
@ToString
@Getter
public class WebhookMarkDownBody extends WebhookBody {

    private final ContentText markdown;

    @ToString
    @Getter
    public static class ContentText {
        private final String content;

        /**
         * Instantiates a new Content text.
         *
         * @param content the content
         */
        public ContentText(String content) {
            this.content = content;
        }
    }


    WebhookMarkDownBody(ContentText markdown) {
        super("markdown");
        this.markdown = markdown;
    }

    /**
     * From webhook text body.
     *
     * @param content the content
     * @return the webhook text body
     */
    public static WebhookMarkDownBody from(ContentText content) {
        return new WebhookMarkDownBody(content);
    }

}

图文消息

{
    "msgtype": "news",
    "news": {
       "articles" : [
           {
               "title" : "中秋节礼品领取",
               "description" : "今年中秋节公司有豪礼相送",
               "url" : "www.qq.com",
               "picurl" : "http://res.mail.qq.com/node/ww/wwopenmng/images/independent/doc/test_pic_msg1.png"
           }
        ]
    }
}

在这里插入图片描述
代码:

@EqualsAndHashCode(callSuper = true)
@ToString
@Getter
public class WebhookNewsBody extends WebhookBody {

    private final ContentNews news;

    @ToString
    @Getter
    public static class ContentNews {

        private List<ContentArticle> articles;

        public ContentNews(List<ContentArticle> articles) {
            this.articles = articles;
        }
    }


    WebhookNewsBody(ContentNews news) {
        super("news");
        this.news = news;
    }

    /**
     * From webhook text body.
     *
     * @return the webhook text body
     */
    public static WebhookNewsBody from(List<ContentArticle> articles) {
        return new WebhookNewsBody(new ContentNews(articles));
    }

}

图文消息类ContentArticle:

@Data
public class ContentArticle {

    /**
     * 图文消息标题
     */
    private String title;
    /**
     * 图文消息描述
     */
    private String description;
    /**
     * 图文消息点击跳转链接
     */
    private String url;
    /**
     * 图文消息封面图片链接
     */
    private String picurl;

}

请求工具类WeChatRobotRequest

有了请求体还需要最后的WeChatRobotRequest发送消息类,botKey是配置文件中的一个机器人key。使用Spring框架的@Value注解注入配置文件中的机器人密钥(botKey),并利用HTTP客户端发送消息至企业微信机器人:

@Component
@Slf4j
public class WeChatRobotRequest {

    private final static String URL = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send";

    @Value("${weChatRobot:}")
    private String botKey;

    /**
     * 发送消息
     *
     * @param body 消息
     */
    public String post(String body) {
        if (StrUtil.isBlank(botKey)) {
            return null;
        }
        String jsonStr = JSONUtil.toJsonStr(body);
        //返回暂无用
        String post = HttpUtil.post(URL + "?key=" + botKey, jsonStr);
        log.info("wechat send result:{}",post);
        return post;
    }
}

同时,为了保证安全性,应确保botKey是从安全可靠的途径获取,并且在实际应用中考虑异常处理机制。

文件上传接口

请求方式:POST(HTTPS)
请求地址:https://qyapi.weixin.qq.com/cgi-bin/webhook/upload_media?key=KEY&type=TYPE

使用multipart/form-data POST上传文件或语音, 文件标识名为"media"

POST https://qyapi.weixin.qq.com/cgi-bin/webhook/upload_media?key=693a91f6-7xxx-4bc4-97a0-0ec2sifa5aaa&type=file HTTP/1.1
Content-Type: multipart/form-data; boundary=-------------------------acebdf13572468
Content-Length: 220

---------------------------acebdf13572468
Content-Disposition: form-data; name="media";filename="wework.txt"; filelength=6
Content-Type: application/octet-stream

mytext
---------------------------acebdf13572468--

返回:

{
   "errcode": 0,
   "errmsg": "ok",
   "type": "file",
   "media_id": "1G6nrLmr5EC3MMb_-zK1dDdzmd0p7cNliYu9V5w7o8K0",
   "created_at": "1380000000"
}

注意事项

消息发送频率限制:每个机器人发送的消息不能超过20条/分钟。

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

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

相关文章

QMT量化策略实盘(二)交易触发定时器run_time

上一篇分享中&#xff0c;介绍了QMT量化实盘中最常用的下单函数passorder&#xff0c;和它主要的参数。 如果再结合一个交易触发函数&#xff0c;就可以实现简单的量化交易策略了&#xff01;比如下面的代码可以实现&#xff1a; 在集合竞价期间以指定价买入中信证券100股 #c…

小狐狸JSON-RPC:钱包连接,断开连接,监听地址改变

detect-metamask 创建连接&#xff0c;并监听钱包切换 一、连接钱包&#xff0c;切换地址&#xff08;监听地址切换&#xff09;&#xff0c;断开连接 使用npm安装 metamask/detect-provider在您的项目目录中&#xff1a; npm i metamask/detect-providerimport detectEthereu…

蓝桥杯23年第十四届省赛真题-填充|DFS,贪心

题目链接&#xff1a; 1.填充 - 蓝桥云课 (lanqiao.cn) 蓝桥杯2023年第十四届省赛真题-填充 - C语言网 (dotcpp.com) 说明&#xff1a; dfs就不再多说了&#xff0c;对于每个?都有0和1两个分支&#xff0c;数据范围是&#xff1a; 那么有m个 ?&#xff0c;时间复杂度就是…

️ 如何掌握服务器硬件基础知识:为高效运维打下坚实基础

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

GTC 2024 火线评论:DPU 重构文件存储访问

编者按&#xff1a;英伟达2024 GTC 大会上周在美国加州召开&#xff0c;星辰天合 CTO 王豪迈在大会现场参与了 GPU 与存储相关的最新技术讨论&#xff0c;继上一篇《GTC 2024 火线评论&#xff1a;GPU 的高效存储利用》之后&#xff0c;这是他发回的第二篇评论文章。 上一篇文章…

网络七层模型之表示层:理解网络通信的架构(六)

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

服务器被挖矿了怎么办,实战清退

当我们发现服务器资源大量被占用的时候&#xff0c;疑似中招了怎么办 第一时间重启服务是不行的&#xff0c;这些挖矿木马一定是会伴随着你的重启而自动重启&#xff0c;一定时间内重新霸占你的服务器资源 第一步检查高占用进程 top -c ps -ef 要注意这里%CPU&#xff0c;如果…

企微这个工具太好用,提升企业销售业绩效果好!

在商海浮沉中&#xff0c;销售业绩的提升始终是企业的核心追求。想要把产品卖出去&#xff0c;首要任务便是吸引客户。如今&#xff0c;线上线下的销售模式已然成为主流&#xff0c;短视频社交媒体如抖音、快手等平台更是成为了流量争夺的热门战场。但面对这些平台上的海量且流…

自动发卡平台源码优化版,支持个人免签支付

源码下载地址&#xff1a;自动发卡平台源码优化版.zip 环境要求&#xff1a; php 8.0 v1.2.6◂ 1.修复店铺共享连接时异常问题 2024-03-13 23:54:20 v1.2.5 1.[新增]用户界面硬币增款扣款操作 2.[新增]前台对接库存信息显示 3.[新增]文件缓存工具类[FileCache] 4.[新增]库存同…

营销大师:小米汽车定价的道道!喝酒买车你沾了吗?——早读(逆天打工人爬取热门微信文章解读)

雷神之锤降临&#xff0c;睡不着的是车企&#xff0c;不应该是你 引言Python 代码第一篇 雷军&#xff1a;小米SU7 现已开启定购&#xff5c;人车合一&#xff0c;我心澎湃第二篇 人民日报 来啦新闻早班车要闻社会政策 结尾 “物有所值乃生存之基石&#xff0c;性价比则为选择之…

Ribbon简介

目录 一 、概念介绍 1、Ribbon是什么 2、认识负载均衡 2.1 服务器端的负载均衡 2.2 客户端的负载均衡 3、Ribbon工作原理 4、Ribbon的主要组件 IClientConfig ServerList ServerListFilter IRule Iping ILoadBalancer ServerListUpdater 5、Ribbon支持…

Vue生命周期,从听说到深入理解(全面分析)

每个 Vue 组件实例在创建时都需要经历一系列的初始化步骤&#xff0c;比如设置好数据侦听&#xff0c;编译模板&#xff0c;挂载实例到 DOM&#xff0c;以及在数据改变时更新 DOM。在此过程中&#xff0c;它也会运行被称为生命周期钩子的函数&#xff0c;让开发者有机会在特定阶…

1.10 类、方法、封装、继承、多态、装饰器

一、介绍类 类(class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例 实例化&#xff1a;创建一个类的实例&#xff0c;类的具体对象。 对象&#xff1a;通过类定义的数据结构实例。对象包括两个数据成员&#x…

FebHost:意大利个人或企业都注册.IT域名吗?

对于广大意大利企业而言,拥有一个属于自己的”.IT”域名已经成为了一种标准做法。无论是中小型本土企业还是知名跨国公司,他们都纷纷选择这一突出意大利特色的国家顶级域名来彰显自身的品牌形象。 数据显示,截至2023年6月,在全球注册的350多万个”.IT”域名中,有超过220万个来…

python pytz是什么

pytz模块常用于时区的转换&#xff0c;常常配合datetime一起使用。我们知道datetime除了data方法生成的时间是没有时区概念&#xff0c;其他如time、datetime等都是有时区概念&#xff0c;即指定了tzinfo信息。 >>> import datetime >>> datetime.datetime.n…

FPGA工程师职业发展道路

作为FPGA工程师&#xff0c;你可以通过以下几个步骤来发展自己的职业道路&#xff1a; 1. 学习基础知识&#xff1a;首先&#xff0c;你需要学习数字电路设计和计算机体系结构的基础知识。了解FPGA的原理、架构和工作原理是非常重要的。 2. 掌握HDL编程语言&#xff1a;掌握至…

企微侧边栏开发(内部应用内嵌H5)

一、背景 公司的业务需要用企业微信和客户进行沟通&#xff0c;而客户的个人信息基本都存储在内部CRM系统中&#xff0c;对于销售来说需要一边看企微&#xff0c;一边去内部CRM系统查询&#xff0c;比较麻烦&#xff0c;希望能在企微增加一个侧边栏展示客户的详细信息&#xf…

有效的数独-java

题目描述: 请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 &#xff0c;验证已经填入的数字是否有效即可。 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。&#xff08;请参考示例图&#…

C++实现A*路径规划的库

作者&#xff1a;CodeLikeAGirl 编译&#xff1a;东岸因为一点人工一点智能公众号 C实现A*路径规划的库本文中&#xff0c;我们探索了A*路径规划在Robotic Project C中的迷人世界&#xff0c;了解了一些超酷的C库。https://mp.weixin.qq.com/s/WyTIzkmWS-0t5oaII6or-Q 01 A*…

ventoy_grub2_boot_win7_win10.md

ventoy (grub2) 的 extMenu启动 win7 efi 、win10 efi ventoy界面按F6&#xff08;extMenu菜单&#xff09; 弹出 ventoy/ventoy_grub.cfg中的菜单内容 ventoy (grub2) 的 extMenu启动 win7 efi 1. 生成 老式 分区启动记录 EFI\Microsoft\Boot\bootmgfw.efi: 命令: bcdboot…