零、前言

上一次做消息推送,是微信公众号的定时消息通知。

由于自己当时的水平不够,加上企鹅家的开发文档普遍不太友好,导致根本看不懂文档在写什么,不得不去看第三方博客来学习公众号的开发。

这次就不一样了,昨天刚看了一下,阿里的开发文档比鹅厂要清晰的多,而且在同一功能上,使用了多种语言作为示例代码,可以说很友好了。可能这就是阿里和鹅厂的区别吧...辣鸡文档和好文档的区别...

本着“授之以渔”的态度,写了这篇文章,作为官方文档的补充。

一、在群里添加机器人

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

比较关键的一步,是进行安全设置。

加密方式一共有三种,既可以选择一种也可以使用多种方式组合:

自定义关键词

加签

IP地址

为了让博客起到效果,我们选择相对安全、也比较难的加签方式。

选择加签之后,把密钥复制出来,然后就可以点确定了。

二、构建请求地址和内容

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

第一步,把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上,导入很方便。

org.apache.httpcomponents

httpclient

4.5.9

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();

}

}

}

}

总结

消息推送别烦恼,这个功能非常好。

只要原理好好搞,融会贯通没烦恼。

写完代码心情好,庆祝一下少不了。

出门上街到处跑,去吃秘制小汉堡。

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

参考资料

springboot集成钉钉_Java(SpringBoot)实现钉钉机器人消息推送相关推荐

  1. 持续集成之群聊机器人消息推送:钉钉 vs 企业微信

    企业微信和钉钉都有面向群的消息推送机器人,两者的使用非常相近,也有一些细节上的特性的区别,这篇文章将结合前面的使用示例进行总结. 使用方式 不同点 企业微信:先创建群,然后在群中添加机器人,可添加多个 ...

  2. java开发钉钉企业内部应用,免登授权+消息推送

    1.申请账号登操作直接看文档去申请就ok了,管理员身份登录,创建微应用 地址:钉钉管理后台 - 钉钉统一身份认证 2.免登授权 CORP_ID :企业id,CORP_SECRET:企业秘钥,agent ...

  3. springboot整合微信公众号(服务号)之消息推送

    前言 没必要说废话直接开整- 开始 (一)先直接上效果图 (二)开始前的准备工作 首先你得有一个公众号吧

  4. 友盟消息推送服务器demo,umeng友盟消息推送功能集成

    umeng友盟消息推送功能集成(本人使用的是eclipse开发) 1.首先请自行观看友盟消息推送集成的API文档. 观看地址如下: 2.集成步骤如下 下载sdk 注意:有两种sdk如果用户已经集成支付 ...

  5. 持续集成之消息推送:钉钉与企业微信的群聊机器人通用示例

    使用钉钉和企业微信的群聊机器人可以进行消息推送,这篇文章使用一个简单的脚本来说明其使用方式. 推送消息的方法 钉钉或者企业微信的群机器人都可提供消息推送的功能,相关的机器人的添加和消息推送的方法可以参 ...

  6. 持续集成之钉钉消息推送:2:推送消息格式说明

    这篇文章介绍一下目前企业微信所支持的推送消息的格式和使用方法,大部分内容与消息示例均来源于目前钉钉的开发文档. 推送消息示例 curl 'https://oapi.dingtalk.com/robot ...

  7. python上传图片到钉钉_python实现钉钉群机器人报告推送

    前言 Python+七牛云+钉钉+ODPS实现数据获取及群消息自动推送. 几个步骤获取数据 制表.绘图 利用七牛云获取图片url 通过钉钉sdk发送群消息如果有很多信息需要推送,可以考虑在绘图时直接用 ...

  8. 钉钉 服务器 消息推送,【20210727 更新】 全能推送PushBot(原钉钉推送)支持企业微信,PushPlus,Bark...

    本帖最后由 然后七年 于 2021-7-27 21:51 编辑 公告: 自2021年04月25日起,本项目luci-app-serverchand改名为luci-app-pushbot 全能推送. o ...

  9. 用python控制钉钉软件_Python实现钉钉消息推送

    钉钉是一个功能非常完善的办公软件,对于数据来说能不能也可以很好的利用钉钉这个资源呢?答案是肯定的.钉钉机器人是钉钉群的一个高级扩展功能,而且有很多种类型,如下: 对于我们日常数据消息推送的话则选择自定 ...

最新文章

  1. 中国剩余定理(孙子定理)的证明和c++求解
  2. SAP 对HU做货物移动报错-Only 0 serial numbers entered instead of 30 -
  3. CVPR14与图像视频检索相关的论文
  4. JS与OC中的方法相互调用
  5. JavaFX 架构与框架 (译)
  6. 计算机体系结构 -- 第一章3 -- 设计的定量4个原则
  7. 产品经理与项目经理的区别
  8. 五年一贯制专转本计算机网络真题,金陵科技学院2017年五年一贯制专转本考试大纲(计算机网络基础)...
  9. scrollTop的兼容性小结
  10. dmb: 数据库监控及灾备系统(for mysql)_MySQL企业级数据库灾备(备份)系统-DMB v2.1发布...
  11. python能做什么-python能干嘛
  12. 帆软填报Execl表格不定行导入
  13. 阿里张勇《人民日报》刊发署名文章:抓住数字新基建的机遇
  14. java图片转为矢量文件_java 通过batik 把svg格式的矢量图生成png图片
  15. SharePoint - CAML
  16. python 人物关系图_python简单实战项目:《冰与火之歌1-5》角色关系图谱构建——人物关系可视化...
  17. vue + element 实现文件上传
  18. 970万,看美女是如何炼成巨贪的!
  19. C/C++ %s %d %u 基本概念与用法
  20. 2021软科计算机科学与技术,2021软科世界一流学科即将重磅发布!

热门文章

  1. java pgsql connection 是否可同时执行sql_Java教程:解读JDBC是什么
  2. python json loads 中文乱码_python实现智能语音天气预报
  3. 插画类引导页设计灵感|友好结合,总能带给人惊喜~
  4. PSD分层模板,助你设计出有创意的圣诞海报
  5. 酷炫的深色模式APP设计模板|2020设计潮流趋势
  6. php array_search多条件,php使用array_search与array_column函数实现二维数组内元素查找...
  7. java代码修改数据库里图片_java如何修改sql存储的图片?
  8. jquery 加载显示loading图标_王者荣耀100强什么意思?loading界面左上角100强有什么含义...
  9. oracle full table scan,ORACLE优化之执行规划(1) - TABLE FULL SCAN/INDEX FULL SCAN
  10. DLL注入(CreateRemoteThread方式)