SpringBoot实现钉钉机器人消息推送的示例代码

零、前言

上一次做消息推送,是微信公众号的定时消息通知。
由于自己当时的水平不够,加上企鹅家的开发文档普遍不太友好,导致根本看不懂文档在写什么,不得不去看第三方博客来学习公众号的开发。
这次就不一样了,昨天刚看了一下,阿里的开发文档比鹅厂要清晰的多,而且在同一功能上,使用了多种语言作为示例代码,可以说很友好了。可能这就是阿里和鹅厂的区别吧...辣鸡文档和好文档的区别...
本着“授之以渔”的态度,写了这篇文章,作为官方文档的补充。

一、在群里添加机器人

在群设置的智能群助手中添加自定义机器人,它长这个样子:

比较关键的一步,是进行安全设置。
加密方式一共有三种,既可以选择一种也可以使用多种方式组合:

  • 自定义关键词
  • 加签
  • IP地址

各种加密方式的介绍,详见官网:https://ding-doc.dingtalk.com/doc#/serverapi2/qf2nxq

为了让博客起到效果,我们选择相对安全、也比较难的加签方式。
选择加签之后,把密钥复制出来,然后就可以点确定了。

二、构建请求地址和内容

先看看官方文档怎么描述加签的:

第一步,把timestamp+"\n"+密钥当做签名字符串,使用HmacSHA256算法计算签名,然后进行Base64 encode,最后再把签名参数再进行urlEncode,得到最终的签名(需要使用UTF-8字符集)。
第二步,把 timestamp和第一步得到的签名值拼接到URL中。

官方的解释很高大上,其实原理很简单,就是把机器人密钥加密后,放在URL的参数中,所以我们需要分别获取时间戳和密钥,组合一下,加密一下,再拼接一下就好了,如图:

I have a Pen,
I have an Apple,
Oh~ Applepen~

官方给出了这样的示例代码:

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import java.net.URLEncoder;

public class Test {
 public static void main(String[] args) throws Exception {
  Long timestamp = System.currentTimeMillis();
  String secret = "this is secret";

  String stringToSign = timestamp + "\n" + secret;
  Mac mac = Mac.getInstance("HmacSHA256");
  mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"));
  byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
  String sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)),"UTF-8");
  System.out.println(sign);
 }
}

然而,org.apache.commons.codec.binary.Base64不是Java的内置类,也就是说,示例代码并不能直接拿过来用:

查了一下,发现Java8中内置的java.util已经包含了Base64,因此用它替换掉原来的codec,无需再引入第三方包:

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.net.URLEncoder;

public class ding {
 public static void main(String[] args) throws Exception {
  //获取时间戳
  Long timestamp = System.currentTimeMillis();
  //定义密钥
  String secret = "this is secret";
  //把时间戳和密钥拼接成字符串,中间加入一个换行符
  String stringToSign = timestamp + "\n" + secret;
  //声明一个Mac对象,用来操作字符串
  Mac mac = Mac.getInstance("HmacSHA256");
  //初始化Mac对象,设置Mac对象操作的字符串是UTF-8类型,加密方式是SHA256
  mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"));
  //把字符串转化成字节形式
  byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
  //新建一个Base64编码对象
  Base64.Encoder encoder = Base64.getEncoder();
  //把上面的字符串进行Base64加密后再进行URL编码
  String sign = URLEncoder.encode(new String(encoder.encodeToString(signData)),"UTF-8");
  //分别输出时间戳和加密信息
  System.out.println(timestamp);
  System.out.println(sign);
 }
}

用最笨的方法,在终端执行一下看看:

成功输出了时间戳和验证信息。

我们测试上述代码的时候,可以手动拼接URL,直接发起请求:
(URL一共有三个参数:access_token、timestamp、sign,需要换成自己的,也就是上面终端输出的结果)

//替换参数后,在终端执行
curl 'https://oapi.dingtalk.com/robot/send?access_token=70c168d03e73728ef36abea63c3c10048cbd054913cfeb&timestamp=1584607421017&sign=gJ3l4mhnlMuHxK1qFUx1kKUSdjuCNntsdG%2Bv%2BTCrLQM%3D' \
 -H 'Content-Type: application/json' \
 -d '{"msgtype": "text",
  "text": {
    "content": "我就是我, 是不一样的烟火"
  },
  "sign": "gJ3l4mhnlMuHxK1qFUx1kKUSdjuCNntsdG%2Bv%2BTCrLQM%3D"
  }'

然后就出现了:

经过测试,代码正常运行,接下来就是部署到生产环境了。

三、部署代码

我们需要先找一下Spring如何发起HTTP请求。

以前,笔者只用过前台的HttpClient,对于后台的HTTP工具并不了解。

一开始尝试用Spring内置的RestTemplate,去网上查了它的用法,写了一堆代码,但怎么也不成功。由于从来没用过RestTemplate,也没耐心去看它的源码,于是放弃。

后来,只能老老实实的用apache的httpClient,查了一下用法,虽然有点麻烦,很多操作没法自动完成,但还算通俗易懂,而且它的包托管在Maven上,导入很方便。

<dependency>
 <groupId>org.apache.httpcomponents</groupId>
 <artifactId>httpclient</artifactId>
 <version>4.5.9</version>
</dependency>

httpClient的使用很灵活,这里使用的是POST方式,有一个参数,发起POST请求时,必须将字符集编码设置成UTF-8。

粗略步骤如图:

直接来一段稍微改一下就能用的代码:

public class DingService {
 //请求地址以及access_token
 String Webhook = "https://oapi.dingtalk.com/robot/send?access_token=YOUR TOKEN";
 //密钥
 String secret = "YOUR SECRET";

 /*
 ** 生成时间戳和验证信息
 */

 public String encode() throws Exception {
  //获取时间戳
  Long timestamp = System.currentTimeMillis();
  //把时间戳和密钥拼接成字符串,中间加入一个换行符
  String stringToSign = timestamp + "\n" + this.secret;
  //声明一个Mac对象,用来操作字符串
  Mac mac = Mac.getInstance("HmacSHA256");
  //初始化,设置Mac对象操作的字符串是UTF-8类型,加密方式是SHA256
  mac.init(new SecretKeySpec(this.secret.getBytes("UTF-8"), "HmacSHA256"));
  //把字符串转化成字节形式
  byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
  //新建一个Base64编码对象
  Base64.Encoder encoder = Base64.getEncoder();
  //把上面的字符串进行Base64加密后再进行URL编码
  String sign = URLEncoder.encode(new String(encoder.encodeToString(signData)),"UTF-8");
  System.out.println(timestamp);
  System.out.println(sign);
  String result = "&timestamp=" + timestamp + "&sign=" + sign;
  return result;
 };

 /* param: message 要发送的信息
 ** return: void 无返回值
 ** 作用:把传入的message发送给钉钉机器人*/

 public void dingRequest(String message){
  CloseableHttpClient httpClient = HttpClientBuilder.create().build();
  String url = null;
  try {
   url = this.Webhook + this.encode();
  } catch (Exception e) {
   e.printStackTrace();
  }
  HttpPost httpPost = new HttpPost(url);
  //设置http的请求头,发送json字符串,编码UTF-8
  httpPost.setHeader("Content-Type", "application/json;charset=utf8");
  //生成json对象传入字符
  JSONObject result = new JSONObject();
  JSONObject text = new JSONObject();
  text.put("content", message);
  result.put("text", text);
  result.put("msgtype", "text");
  String jsonString = JSON.toJSONString(result);
  StringEntity entity = new StringEntity(jsonString, "UTF-8");
  //设置http请求的内容
  httpPost.setEntity(entity);
  // 响应模型
  CloseableHttpResponse response = null;
  try {
   // 由客户端执行(发送)Post请求
   response = httpClient.execute(httpPost);
   // 从响应模型中获取响应实体
   HttpEntity responseEntity = response.getEntity();
   System.out.println("响应状态为:" + response.getStatusLine());
   if (responseEntity != null) {
    System.out.println("响应内容长度为:" + responseEntity.getContentLength());
    System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));
   }
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   try {
    // 释放资源
    if (httpClient != null) {
     httpClient.close();
    }
    if (response != null) {
     response.close();
    }
   } catch (Exception e) {
    e.printStackTrace();
   }
  }
 }
}

总结

其实消息推送的功能并不难,只是由于初次接触,需要查很多的文档,在这个过程中,锻炼了文本阅读能力和独立解决问题的能力。

参考资料

Java如何进行Base64的编码(Encode)与解码(Decode)

Spring RestTemplate介绍

Spring--Http请求--HttpClient

到此这篇关于SpringBoot实现钉钉机器人消息推送的示例代码的文章就介绍到这了,更多相关SpringBoot 钉钉机器人消息推送内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • java实现钉钉机器人消息推送的示例代码

    先建个钉钉群,并加好机器人 此时,机器人已经添加完毕,接下来编写我们连接机器人小哥的代码 import com.alibaba.fastjson.JSON; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import java.util.List; import java.util.Map; /** * @author yanghao * @version DingTalkTest.j

  • python3实现钉钉消息推送的方法示例

    背景 偶然发现一个python实现的按照农历/阴历推送消息提醒的程序,钉钉群消息推送.此处总结并对其可推送的消息做. DingtalkNotice 环境:python3.7 安装: pip install schedule #实现定时任务的模块 pip install DingtalkChatbot #python封装的各种消息的调用 pip install sxtwl #日历库 钉钉自定义机器人: 钉钉群机器人是一个高级扩展的功能,可以将第三方服务的信息聚合到钉钉群众,实现信息的自动化同步.1

  • SpringBoot实现钉钉机器人消息推送的示例代码

    零.前言 上一次做消息推送,是微信公众号的定时消息通知. 由于自己当时的水平不够,加上企鹅家的开发文档普遍不太友好,导致根本看不懂文档在写什么,不得不去看第三方博客来学习公众号的开发. 这次就不一样了,昨天刚看了一下,阿里的开发文档比鹅厂要清晰的多,而且在同一功能上,使用了多种语言作为示例代码,可以说很友好了.可能这就是阿里和鹅厂的区别吧...辣鸡文档和好文档的区别... 本着"授之以渔"的态度,写了这篇文章,作为官方文档的补充. 一.在群里添加机器人 在群设置的智能群助手中添加自定义

  • SpringBoot+WebSocket+Netty实现消息推送的示例代码

    上一篇文章讲了Netty的理论基础,这一篇讲一下Netty在项目中的应用场景之一:消息推送功能,可以满足给所有用户推送,也可以满足给指定某一个用户推送消息,创建的是SpringBoot项目,后台服务端使用Netty技术,前端页面使用WebSocket技术. 大概实现思路: 前端使用webSocket与服务端创建连接的时候,将用户ID传给服务端 服务端将用户ID与channel关联起来存储,同时将channel放入到channel组中 如果需要给所有用户发送消息,直接执行channel组的writ

  • Springboot整合企业微信机器人助手推送消息的实现

    目录 前言 本篇内容: 正文 机器人创建步骤: 前言 这个东西有啥用,好玩? 确实, 好玩归好玩,其实很有使用场景. 可以自己选则一些业务节点触发这个机器人助手的消息推送: 简单举例: 1. 有人给你的系统留下反馈意见了,推送到运营群去: 2.项目部署成功了,推送到运维群去: 3.有人新增业务资料了,推送到客服群去: 本篇内容: 对接企微机器人,推送消息到群聊. 消息类型有四种: 文本消息 图片消息 MarkDown格式文本消息 小卡片消息(小卡片哦~) 效果: 正文 注意点: 1.企业微信群聊

  • Java中websocket消息推送的实现代码

    一.服务层 package com.demo.websocket; import java.io.IOException; import java.util.Iterator; import java.util.concurrent.ConcurrentLinkedQueue; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import org.springframew

  • 基于ajax与msmq技术的消息推送功能实现代码

    周末在家捣鼓了一下消息推送的简单例子,其实也没什么技术含量,欢迎大伙拍砖. 我设计的这个推送demo是基于ajax长轮询+msmq消息队列来实现的,具体交互过程如下图: 先说说这个ajax长轮询,多长时间才算长呢?这个还真不好界定. 这里是相对普通ajax请求来说的,通常处理一个请求也就是毫秒级别的时间.但是这里的长轮询方式 在ajax发送请求给服务器之后,服务器给调用端返回数据的时间多长那可还真不好说.嘿嘿,这关键要看 我们啥时候往msmq队列中推送数据了,先看看推送的效果图吧..... 抱歉

  • Android中利用App实现消息推送机制的代码

    1.消息推送机制 服务器器端需要变被动为主动,通知客户一些开发商认为重要的信息,无论应用程序是否正在运行或者关闭. 我想到了一句话:don't call me,i will call you! qq今天在右下角弹出了一个对话框:"奥巴马宣布本拉登挂了...",正是如此. 自作聪明,就会带点小聪明,有人喜欢就有人讨厌. 2.独立进程 无论程序是否正在运行,我们都要能通知到客户,我们需要一个独立进程的后台服务. 我们需要一个独立进程的后台服务. 在androidmanifest.xml中注

  • Python编程实现微信企业号文本消息推送功能示例

    本文实例讲述了Python微信企业号文本消息推送功能.分享给大家供大家参考,具体如下: 企业号的创建.企业号应用的创建.组.tag.part就不赘述了,一搜一大堆,但是网上拿的那些个脚本好多都不好使,所以自己修了一个 坦率的讲,这个脚本是用来作为zabbix的通知媒介脚本的,本人是个菜鸟,如果哪里不对,大神们不要笑话,python也处于学习阶段,如果有哪些地方不合理,很希望可以不吝赐教,废话不多说,脚本奉上: #!/usr/bin/python # _*_coding:utf-8 _*_ imp

  • 微信小程序模板消息限制实现无限制主动推送的示例代码

    需求背景 基于微信的通知渠道,微信小程序为开发者提供了可以高效触达用户的模板消息能力,在用户本人与小程序页面有交互行为后触发,通过微信聊天列表中的服务通知可快捷进入查看消息,点击查看详情还能跳转到下发消息的小程序的指定页面. 微信小程序允许下发模板消息的条件分为两类:支付或者提交表单.通过提交表单来下发模板消息的限制为"允许开发者向用户在7天内推送有限条数的模板消息(1次提交表单可下发1条,多次提交下条数独立,相互不影响)". 然而,用户1次触发7天内推送1条通知是明显不够用的.比如,

  • php实现微信模板消息推送

    本文实例为大家分享了php微信模板消息推送的具体代码,供大家参考,具体内容如下 1.微信公众号模板消息配置 2.PHP代码 /** * 发送模板消息 */ public function send_notice(){ //获取access_token if ($_COOKIE['access_token']){ $access_token2=$_COOKIE['access_token']; }else{ $json_token=$this>curl_post("https://api.w

随机推荐