使用釘釘開源api發送釘釘工作消息

在工作管理系統場景中,上下級和不同部門之間常常有請假,餐補等流程操作,而這些操作通常需要人員手動進行,這里我們引入一個釘釘的api,可以基于釘釘來發送工作消息通知

1、導入釘釘sdk
<dependency><groupId>com.aliyun</groupId><artifactId>alibaba-dingtalk-service-sdk</artifactId><version>2.0.0</version></dependency><dependency><groupId>com.aliyun</groupId><artifactId>dingtalk</artifactId><version>2.2.26</version></dependency>
2、登錄釘釘開發者后臺,選擇租戶

3、點擊右上角創建應用

4、申請開通工作消息API基礎權限

5、獲取企業AngentId并獲取ClientID和ClientSecret,用于后續程序中獲取token

6、配置clientId和clientSecret

7、進行api的調用和業務邏輯的開發(這里我封裝了一個接口用于發送釘釘消息,方便前端調用)
@Tag(name = "釘釘-發送工作消息")
@RestController
@RequestMapping("/dingtalk")
@Validated
public class DingTalkController {@Resourceprivate DingTalkService dingTalkService;@PostMapping("/sendSubmitMessage")@Operation(summary = "釘釘發送消息通知提交餐補證明")
/*    @PreAuthorize("@ss.hasPermission('dingtalk:hr:sendsubmitmsg')")*/public CommonResult<Boolean> sendSubmitMessage(@RequestBody List<Long> ids) {Boolean result = dingTalkService.sendSubmitMessageToUser(ids);return success(result);}@PostMapping("/sendReSubmitMessage")@Operation(summary = "釘釘發送消息通知重新提交餐補證明")/*@PreAuthorize("@ss.hasPermission('dingtalk:hr:sendremsg')")*/public CommonResult<Boolean> sendReSubmitMessage(@RequestParam Long poofId, @RequestParam String remark) {dingTalkService.sendReSubmitMessageToUser(poofId, remark);return success(true);}
}
這里我們以發送上傳餐補證明消息給指定用戶接口為例
@Service
@Slf4j
public class DingTalkServiceImpl implements DingTalkService {// 注入釘釘應用的 AppKey 和 AppSecret@Value("${justauth.type.DINGTALK.client-id}")private String clientId;@Value("${justauth.type.DINGTALK.client-secret}")private String clientSecret;private static final String DINGTALK_API_BASE_URL = "https://oapi.dingtalk.com";private static final String GET_TOKEN_URL = "/gettoken";@Resourceprivate AdminUserApi adminUserApi;@Resourceprivate RestTemplate restTemplate;@Resourceprivate MealAllowanceProofMapper mealAllowanceProofMapper;@Resourceprivate MealAllowanceDataMapper mealAllowanceDataMapper;@Overridepublic Boolean sendSubmitMessageToUser(List<Long> userIds) {/*** 發送釘釘消息* @param*///遍歷用戶idBoolean result = true;for (Long userId : userIds) {//通過用戶id得到對應用戶的釘釘idString userRemark = adminUserApi.getUserRemark(userId).replaceAll("\\D+", "");//通過用戶id得到對應用戶的餐補總金額BigDecimal totalAmount = mealAllowanceDataMapper.selectByUserId(userId).getTotalAmount();// 調用下方方法發送result = sendSingleUserNotice(userRemark, totalAmount);if (!result) {throw exception(DING_TALK_SEND_MESSAGE_ERROR);}}return result;}
發送消息體封裝邏輯和消息外觀構造:
@SneakyThrowsprivate Boolean sendSingleUserNotice(String dingUserId, BigDecimal amount){//獲取AccessTokenString accessToken = getAccessToken();//"https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2"為釘釘發送消息的接口請求地址DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2");//構建消息請求體OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request();request.setAgentId(#自己企業的AngentId#);//設置發送給對應用戶的釘釘idrequest.setUseridList(dingUserId);//不發給全體成員request.setToAllUser(false);//構建PC端和移動端的url跳轉路徑地址,點擊路徑可以跳轉到提交餐補信息的平臺String PcUrl = "http://effi.fzxs.com.cn:8089/overtime/meal-allowance";String mobileUrl = "dingtalk://dingtalkclient/page/link?url=" + URLEncoder.encode(PcUrl, "UTF-8") + "&pc_slide=false";// 使用ActionCard消息類型創建帶按鈕的消息OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();msg.setMsgtype("action_card");// 創建ActionCard消息OapiMessageCorpconversationAsyncsendV2Request.ActionCard actionCard = new OapiMessageCorpconversationAsyncsendV2Request.ActionCard();// 設置消息標題actionCard.setTitle("💰 加班餐補通知");// 構建精美的Markdown內容StringBuilder content = new StringBuilder();content.append("## 你有新的加班餐補啦 \n\n");content.append("### **💰餐補金額: ¥").append(amount.toString()).append("**\n\n");content.append("**請及時上傳:** 餐飲消費憑證截圖,不要讓hr小姐姐久等啦 \n\n");content.append("?? **截止時間:** 2個工作日內,過期作廢");actionCard.setMarkdown(content.toString());// 設置按鈕布局為豎直排列actionCard.setBtnOrientation("0");// 創建按鈕列表List<OapiMessageCorpconversationAsyncsendV2Request.BtnJsonList> btnList = new ArrayList<>();// 添加上傳證明按鈕OapiMessageCorpconversationAsyncsendV2Request.BtnJsonList uploadBtn = new OapiMessageCorpconversationAsyncsendV2Request.BtnJsonList();uploadBtn.setTitle("立即上傳餐補證明");uploadBtn.setActionUrl(mobileUrl);btnList.add(uploadBtn);actionCard.setBtnJsonList(btnList);msg.setActionCard(actionCard);request.setMsg(msg);try {OapiMessageCorpconversationAsyncsendV2Response response = client.execute(request, accessToken);if (response.getErrcode() == 0) {log.info("[sendSingleUserNotice][發送餐補通知成功] userId={}, amount={}, taskId={}", dingUserId, amount, response.getTaskId());return true;} else {log.error("[sendSingleUserNotice][發送餐補通知失敗] userId={}, errcode={}, errmsg={}", dingUserId, response.getErrcode(), response.getErrmsg());return false;}} catch (ApiException e) {log.error("[sendSingleUserNotice][發送餐補通知異常] userId={}, error={}", dingUserId, e.getMessage(), e);throw ServiceExceptionUtil.exception(DING_TALK_SEND_MESSAGE_ERROR);}}/*** 創建美觀的釘釘卡片消息* * @param title 卡片標題* @param content 卡片內容* @param pcUrl PC端鏈接* @param mobileUrl 移動端鏈接* @return ActionCard對象*/private OapiMessageCorpconversationAsyncsendV2Request.ActionCard createBeautifulActionCard(String title, String content, String pcUrl, String mobileUrl) {OapiMessageCorpconversationAsyncsendV2Request.ActionCard actionCard = new OapiMessageCorpconversationAsyncsendV2Request.ActionCard();actionCard.setTitle(title);actionCard.setMarkdown(content);actionCard.setBtnOrientation("1");// 添加操作按鈕List<OapiMessageCorpconversationAsyncsendV2Request.BtnJsonList> btnList = new ArrayList<>();// 移動端按鈕OapiMessageCorpconversationAsyncsendV2Request.BtnJsonList mobileBtn = new OapiMessageCorpconversationAsyncsendV2Request.BtnJsonList();mobileBtn.setTitle("📱 移動端處理");mobileBtn.setActionUrl(mobileUrl);btnList.add(mobileBtn);// PC端按鈕OapiMessageCorpconversationAsyncsendV2Request.BtnJsonList pcBtn = new OapiMessageCorpconversationAsyncsendV2Request.BtnJsonList();pcBtn.setTitle("💻 電腦端處理");pcBtn.setActionUrl(pcUrl);btnList.add(pcBtn);actionCard.setBtnJsonList(btnList);return actionCard;}
獲取accessToken方法封裝:
/*** 獲取釘釘訪問令牌* @return*/public String getAccessToken() {try {String url = UriComponentsBuilder.fromHttpUrl(DINGTALK_API_BASE_URL + GET_TOKEN_URL).queryParam("appkey", clientId).queryParam("appsecret", clientSecret).toUriString();ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);JSONObject result = JSON.parseObject(response.getBody());if (result.getInteger("errcode") != 0) {log.error("獲取釘釘訪問令牌失敗:{}", result.getString("errmsg"));throw exception(AUTH_ACCESS_TOKEN_ERROR);}return result.getString("access_token");} catch (Exception e) {log.error("獲取釘釘訪問令牌異常",e);throw exception(AUTH_ACCESS_TOKEN_ERROR);}}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/916303.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/916303.shtml
英文地址,請注明出處:http://en.pswp.cn/news/916303.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

拒絕SQL恐懼:用Python+pyqt打造任意Excel數據庫查詢系統

一、引言 在數字化轉型浪潮中&#xff0c;超過76%的基層業務人員仍被困在"SQL恐懼癥"的泥潭里——他們精通業務邏輯卻受限于技術門檻&#xff0c;面對海量數據時只能反復請求IT部門協助。本項目通過PythonPyQt來構建基于Excel風格的查詢系統&#xff0c;從而打破這種…

KubeKey安裝KubeSphere、部署應用實踐問題總結

使用KubeSphere的KubeKey 安裝K8s 集群過程中&#xff0c;碰到了一些問題&#xff0c;現在都一一解決了&#xff0c;以此記錄一下。 kubekey 安裝k8s 集群報錯 execute task timeout, Timeout1m error: Pipeline[CreateClusterPipeline] execute failed: Module[GreetingsModul…

基于粒子群優化的PID控制在藥液流量控制系統中的應用

基于粒子群優化的PID控制在藥液流量控制系統中的應用 前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家,覺得好請收藏。點擊跳轉到網站。 1. 引言 在現代工業控制系統中,精確的流量控制是許多生產過程的關鍵環節。本文針對藥液流量控制…

不用電腦要不要關機?

1. 短時間不用&#xff08;午休、臨時外出&#xff09;&#xff1a;建議「睡眠」或「休眠」睡眠&#xff1a;電腦暫停工作&#xff0c;喚醒速度快&#xff0c;耗電較少適合需要快速恢復工作的場景休眠&#xff1a;整機斷電&#xff0c;喚醒速度比睡眠慢&#xff0c;但完全不耗電…

【Spring AI】SiliconFlow-硅基流動

硅基流動 https://docs.siliconflow.cn/cn/userguide/introduction

swagger基本注解@Tag、@Operation、@Parameters、@Parameter、@ApiResponse、@Schema

swagger基本注解 Tag 介紹&#xff1a;用于給接口分組&#xff0c;用途類似于為接口文檔添加標簽。用于&#xff1a;方法、類、接口。常用屬性&#xff1a; name&#xff1a;分組的名稱 RestController RequestMapping("/sysUser") Tag(name "管理員接口&quo…

Unity 實現幀率(FPS)顯示功能

一、功能介紹本教程實現一個 FPS 顯示腳本&#xff0c;支持 TextMeshProUGUI 組件。腳本會每秒更新一次幀率&#xff0c;并顯示在 UI 上&#xff0c;便于開發和調試時觀察性能變化。二、完整代碼將以下代碼保存為 FPS.cs 腳本&#xff1a;using UnityEngine; using TMPro;[Requ…

【星野AI】minimax非活動時間充值優惠漏洞

點開發現有活動即將開啟。把手機時間修改為20250729&#xff0c;或者其它活動內時間。發現活動的充值接口未進行時間校驗。疊加新人首充優惠&#xff0c;充值六元&#xff0c;獲得1800鉆。在非活動時間獲取了優惠。

Python 程序設計講義(22):循環結構——for 循環

Python 程序設計講義&#xff08;22&#xff09;&#xff1a;循環結構——for 循環 目錄Python 程序設計講義&#xff08;22&#xff09;&#xff1a;循環結構——for 循環一、for 循環的語法二、for 循環執行的流程三、for 循環應用舉例while 循環的循環次數往往是不確定的&am…

自動駕駛---視覺語言模型(VLM)引導的模型預測控制器(MPC)

1 背景之前大家普遍認為的端到端就是傳感器輸入&#xff0c;控制輸出&#xff0c;這也確實是真正的端到端&#xff0c;但目前車企走的更多的是軌跡生成。自動駕駛端到端控制瓶頸主要有以下兩點&#xff1a;可解釋性缺失&#xff1a;傳統端到端模型&#xff08;如純VLM控制器&am…

最優估計準則與方法(5)加權最小二乘估計(WLS)_學習筆記

前言 最優估計理論中研究的最小二乘估計&#xff08;LS&#xff09;為線性最小二乘估計&#xff08;LLS&#xff09;&#xff0c;包括古典最小二乘估計&#xff08;CLS&#xff09;[1]、加權最小二乘估計&#xff08;WLS&#xff09;和遞推最小二乘估計&#xff08;RLS&#x…

Linux——線程互斥

文章目錄一、有關概念原子性錯誤認知澄清加鎖二、鎖的相關函數全局鎖局部鎖初始化銷毀加鎖解鎖三、鎖相關如何看待鎖一個線程在執行臨界區的代碼時&#xff0c;可以被切換嗎&#xff1f;鎖是本身也是臨界資源&#xff0c;它如何做到保護自己&#xff1f;&#xff08;鎖的實現&a…

扣子(Coze)宣布開源兩大核心項目——Coze Studio(扣子開發平臺)和Coze Loop(扣子羅盤),附安裝步驟

2025年7月26日,字節跳動旗下AI開發平臺“扣子(Coze)”宣布開源兩大核心項目——Coze Studio(扣子開發平臺)和Coze Loop(扣子羅盤),采用Apache 2.0協議,支持免費商用及本地化部署。 開源內容 Coze Studio:提供可視化AI智能體開發工具,支持零代碼/低代碼拖拽式工作流編…

InfluxDB Flux 查詢協議實戰應用(二)

四、實戰案例解析4.1 服務器性能監控數據查詢在服務器性能監控場景中&#xff0c;InfluxDB 和 Flux 查詢協議能夠發揮重要作用&#xff0c;幫助運維人員實時了解服務器的運行狀態&#xff0c;及時發現性能問題。假設我們的服務器性能監控數據存儲在名為server-monitoring的存儲…

二層隧道協議(PPP、PPTP、L2TP)

PPP —— 點對點鏈路上的“鏈路層會話層”協議&#xff0c;解決撥號認證、IP 分配和多協議封裝。PPTP —— 在 IP 網絡里開一條“PPP-over-GRE”隧道&#xff0c;把 PPP 封裝進公共網絡&#xff0c;速度快但已不安全。L2TP —— 在 IP/UDP 里再開一條“PPP-over-UDP”隧道&…

openmv特征點檢測

AGAST 角點檢測器和 FAST 角點檢測器&#xff1a; 兩者都是計算機視覺中快速檢測圖像角點的算法&#xff0c;核心目的是高效找到圖像中 "有辨識度的點"&#xff0c;但細節略有不同&#xff1a; &#xff08;1&#xff09;FAST 角點檢測器 ? 特點&#xff1a;速度極快…

基于深度學習的CT圖像3D重建技術研究

基于深度學習的CT圖像3D重建技術研究 摘要 本文詳細探討了使用深度學習技術進行CT(計算機斷層掃描)圖像3D重建的全過程。我們從CT成像基本原理出發,系統介紹了數據預處理、深度學習模型構建、訓練優化以及三維可視化等關鍵技術環節。研究采用了先進的深度學習架構如3D U-Net…

JVM相關面試八股

什么是雙親委派模型&#xff1f; 如果一個類加載器在接到加載類的請求時&#xff0c;它首先不會自己嘗試去加載這個類&#xff0c;而是把這個請求任務委托給父類加載器去完成&#xff0c;依次遞歸&#xff0c;如果父類加載器可以完成類加載任務&#xff0c;就返回成功&#xff…

Javaweb————HTTP消息體拆分講解

??????一.HTTP請求消息結構 &#xff08;1&#xff09;請求行 &#x1f499; 請求方法 &#x1f499;URL地址 &#x1f499;協議名 &#xff08;2&#xff09;請求頭 報文頭包含若千個屬性格式為“屬性名:屬性值”, 服務端據此獲取客戶端的基本信息 &#xff08;3&…

GitHub的免費賬戶的存儲空間有多少?

GitHub的免費賬戶在存儲空間方面的具體限制如下: 一、普通倉庫(非LFS)存儲限制 公共倉庫 總存儲:無明確總容量限制,但建議單個倉庫不超過1GB以確保性能。若倉庫過大(如超過5GB),可能會收到GitHub的優化提示郵件。 文件大小:單個文件最大100MB,超過100MB的文件會被直…