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×tamp=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"),"UTF-8"); System.out.println(timestamp); System.out.println(sign); String result = "×tamp=" + 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 釘釘機器人訊息推送內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!