项目实践-SpringBoot项目对接钉钉发送工作通知

**书山有路勤为径,学海无涯苦作舟**
记录程序员生活点点滴滴,希望记录的内容能帮助到努力爬山的各位伙伴!标签:Java/钉钉/工作通知

前言

  1. 业务场景:目前很多企业在日常运行中的消息会议,工作通知,任务安排等信息一般都通过企业微信/邮件等通讯软件来进行交流和消息分发,避免了口头传达的不及时性和传递错误性。在笔者的项目研发中,业务中到审批流的消息分发,在支持企业微信/邮件等形式的基础上,开发支持钉钉发送工作通知消息的方式,毕竟支持通知的方式越多,说明系统的功能越完备嘛!
  2. 开发步骤:(这里以笔者自建的钉钉组织架构为例)
    – 创建属于自己的企业管理平台(钉钉开放平台)
    – 应用开发-企业内部应用-钉钉用用-H5微应用
    – 参照开发者文档,设置微应用的权限/IP等信息(开发者文档-消息通知)
    – 代码开发(下面会逐步介绍)

一、钉钉应用申请?

1.钉钉应用创建,若开发人员的钉钉账号已经是既有组织的平台管理账号,可以直接登录钉钉管理后台,若没有管理权限则可以通过管理员授权或者自己创建组织的形式来完成开发工作。
2.工作通知创建的应用类别为:企业内部应用–H5微应用,这里需要注意的是,应用创建完成后需要完成IP设置和权限设置

二、SpringBoot实现钉钉工作通知

1.引入钉钉SDK工具包pom依赖

     <!--钉钉工具包--><dependency><groupId>com.dingtalk.api</groupId><artifactId>top-api-sdk</artifactId><version>2.0.0-RELEASE</version></dependency>

这里在引入SDK工具包的时候需要注意,多数环境的私服中不存在SDK的工具包,需要手动下载然后挂载到maven仓库中

  • 挂载的过程
    从官方或者笔者的资源中下载SDK工具包(可以私信我免费获取)
    在项目控制台中通过命令将jar包挂载到仓库中
mvn install:install-file -DgroupId=com.dingtalk.api -DartifactId=top-api-sdk-dev -Dversion=ding-open-mc-SNAPSHOT -Dfile=lib/taobao-sdk-java-auto_1479188381469-20210630.jar -Dpackaging=jar -DgeneratePom=true

2.Nacos配置

dingding:agentId: ********(按应用填写)appKey: dingsg*********ceyk(按应用填写)appSecret: pghvjQeW********vObLlkLlIh88ng0Elm42M***m8JhPa7CSciPntRjarjo(按应用填写)# 获取Access_tokengetTokenUrl: https://oapi.dingtalk.com/gettoken# 根据电话号码获取uridgetByMobileUrl: https://oapi.dingtalk.com/user/get_by_mobile# 发送消息通知asyncMessageUrl: https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2# 根据电话号码获取用户信息userByMobileUrl: https://oapi.dingtalk.com/topapi/v2/user/getbymobile# 更新通讯录用户userUpdateUrl: https://oapi.dingtalk.com/topapi/v2/user/update# 新增通讯录用户userAddUrl: https://oapi.dingtalk.com/topapi/v2/user/create

备注:
笔者此处将应用的参数和涉及的开放Api配置到nacos中,避免在服务运行过程中因应用调整或Api升级需要重新调整项目代码。

3.实现钉钉工作通知
整体思路

  • 同步系统平台人员到钉钉通讯录(根据项目需要进行同步,也可以选择不同步)
  • 获取钉钉Access_Token
  • 根据钉钉通知类别组装消息体
  • 钉钉通知发送
    A.获取Access_Token
/**- @author Miracle- @title: DingdingServiceImpl- @projectName proxy- @description: 【钉钉服务接口】Access_Token- @date 2021/7/614:52*/
@Service
@Slf4j
public class DingdingServiceImpl implements DingdingService {@Value("${mare.loginUrl}")private String loginUrl;@Value("${dingding.agentId}")private Long AgentId;@Value("${dingding.appKey}")private String APP_KEY;@Value("${dingding.appSecret}")private String APP_SECRET;@Value("${dingding.getTokenUrl}")private String getTokenUrl;@Value("${dingding.getByMobileUrl}")private String getByMobileUrl;@Value("${dingding.asyncMessageUrl}")private String asyncMessageUrl;@Value("${dingding.userByMobileUrl}")private String userByMobileUrl;@Value("${dingding.userUpdateUrl}")private String userUpdateUrl;@Value("${dingding.userAddUrl}")private String userAddUrl;/*** 获取AccessToken* @return*/public String getAccessToken() throws ApiException {DefaultDingTalkClient client =new DefaultDingTalkClient(getTokenUrl);OapiGettokenRequest request = new OapiGettokenRequest();//Appkeyrequest.setAppkey(APP_KEY);//Appsecretrequest.setAppsecret(APP_SECRET);/*请求方式*/request.setHttpMethod("GET");OapiGettokenResponse response = client.execute(request);return response.getAccessToken();}
}

B.同步平台人员到钉钉通讯录

/*** 同步钉钉通讯录*/@Overridepublic void syncUsers() {try {// 获取钉钉AccessToken信息String accessToken = this.getAccessToken();log.info("获取钉钉AccessToken信息完成");// 获取平台全量人员信息Map<String, StaffObject> staffMap = getPlatformStaffs();log.info("获取平台全量人员信息完成");if(staffMap != null && staffMap.size() > 0){for (Map.Entry<String, StaffObject> entry : staffMap.entrySet()){StaffObject staff = entry.getValue();// 根据平台人员手机账号判断是否存在DingTalkClient client = new DefaultDingTalkClient(userByMobileUrl);OapiV2UserGetbymobileRequest req = new OapiV2UserGetbymobileRequest();req.setMobile(staff.getPhoneNum());OapiV2UserGetbymobileResponse user = client.execute(req, accessToken);// 返回码String errcode = user.getErrorCode();// 通讯录中存在该用户if("0".equals(errcode) || errcode == "0"){OapiV2UserGetbymobileResponse.UserGetByMobileResponse json = user.getResult();String userId = json.getUserid();DingTalkClient updateClient = new DefaultDingTalkClient(userUpdateUrl);OapiV2UserUpdateRequest updateReq = new OapiV2UserUpdateRequest();updateReq.setUserid(userId);updateReq.setName(staff.getName());// 用户信息更新OapiV2UserUpdateResponse updateRst = updateClient.execute(updateReq, accessToken);log.info("【钉钉通讯录更新】电话号码:" + staff.getPhoneNum() + ",更新结果:" + updateRst.getErrcode() + "/" + updateRst.getErrmsg());}else {// 新增用户DingTalkClient addClient = new DefaultDingTalkClient(userAddUrl);OapiV2UserCreateRequest addReq = new OapiV2UserCreateRequest();addReq.setName(staff.getName());addReq.setMobile(staff.getPhoneNum());addReq.setDeptIdList("1");OapiV2UserCreateResponse addRst = addClient.execute(addReq, accessToken);log.info("【钉钉通讯录新增】电话号码:" + staff.getPhoneNum() + ",更新结果:" + addRst.getResult());}}}} catch (ApiException e) {e.printStackTrace();} }

C.发送工作通知(以Text类型为例,其他类型可以参考开发者文档)

/*** 发送钉钉消息* @return* @throws ApiException*/@Overridepublic boolean sendDingMsg(DingEntity dingEntity) throws ApiException {Boolean sendResult = false;// 开始获取钉钉Access_Token,开启消息通知String accessToken = this.getAccessToken();// 通知接收人电话号码// String mobile = "15686457316,15712366325";if(StringUtils.isBlank(mobile)){return false;}String userIdList = "";// 循环处理拼接用户列表String[] split = mobile.split(",");for(String cell : split){DingTalkClient client2 = new DefaultDingTalkClient(getByMobileUrl);OapiUserGetByMobileRequest req = new OapiUserGetByMobileRequest();req.setMobile(cell);req.setHttpMethod("GET");OapiUserGetByMobileResponse rsp = client2.execute(req, accessToken);// 获取的urid即为发送的目标人员的IDString urid = rsp.getUserid();// 将接受人员的urid按照(user123,user456)的形式拼接userIdList = userIdList + urid + ",";}DingTalkClient client = new DefaultDingTalkClient(asyncMessageUrl);OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request();request.setUseridList(userIdList);request.setAgentId(AgentId);request.setToAllUser(false);OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();// 消息类别时文本消息msg.setMsgtype("text");msg.setText(new OapiMessageCorpconversationAsyncsendV2Request.Text());//  msg.getText().setContent("工作通知:你存在未处理的待办任务,请及时处理待办事项!");request.setMsg(msg);// 消息发送OapiMessageCorpconversationAsyncsendV2Response dingResult = client.execute(request, accessToken);JSONObject json = JSONObject.fromObject(dingResult);return json.get("errcode").equals("0");}

备注:

  • 因为钉钉暂时不支持获取全量的通讯录信息,因此笔者采用通过号码校验的方式来判断通讯录人员是否存在,此处会存在资源浪费和效率地下的情况,大家可以考虑采用更优的方案解决。
  • 钉钉消息通知的次数存在上限,具体信息参考官方开发者文档。

总结

登山路上的慕码人,理解不透的地方还请各位指点!
欢迎大家多多指正交流!

项目实践-SpringBoot项目对接钉钉发送工作通知相关推荐

  1. 通过钉钉机器人发送群消息通知

    添加群机器人 可以查看这篇文章:添加机器人到钉钉群 使用命令行工具curl快速验证自定义机器人是否可以正常工作.可以使用如下命令,把对应的链接调整成对应群的webhook地址即可. curl 'htt ...

  2. spring boot 整合钉钉机器人发送消息通知

    钉钉消息通知 主要用于系统预警.资源预警.重要消息通知,随时随地可以掌握重要信息 一.通知效果 1.文本通知 2.带链接的通知 3.makrdown格式 通知 4.ActionCard 通知 5.Fe ...

  3. YOLOv5的项目实践 | 手势识别项目落地全过程(附源码)

    欢迎关注" 计算机视觉研究院 " 计算机视觉研究院专栏 计算机视觉研究院 专注CV领域公众号 作者:Edison_G 长按二维码关注 前言  计算机视觉可以学习美式手语,进而帮助听 ...

  4. python项目实践_Python 项目实践三(Web应用程序)第二篇

    接着上节的继续学习,使用Django创建网页的过程通常分三个阶段:定义URL.编写视图和编写模板.首先,你必须定义URL模式,每个URL都被映射到特定的视图--视图函数获取并处理网页所需的数据.视图函 ...

  5. SpringMVC项目升级SpringBoot项目参考

    升级原因 首先纠正以前一个错误认识:SpringMVC与SpringBoot没有半毛钱关系! Spring Boot本身并不提供Spring框架的核心特性以及扩展功能,只是用于快速.敏捷地开发新一代基 ...

  6. 【Java相关的项目】2022最强毕业设计选题参考,包含了JSP项目,SSH项目,SSM项目还有Springboot项目

    基于jsp+Spring+hibernate+struts2的SSH招聘网站源码代码,包含设计文稿 基于jsp+mysql的网络教学平台源码代码(设计文稿+答辩PPT+开题报告) 基于jsp+Spri ...

  7. springboot项目层次结构_Springboot项目结构Springboot项目结构

    运用Spring Boot 在start.spring.io可以直接下载Spring Boot项目 | | pom.xml | | \---src +---main | +---java | | \- ...

  8. web项目实践1-iwebshop项目-页面初始化数据与sql数据库中的数据对比

    当拿到项目后首先应该根据页面初始化数据与SQL数据库中的查询数据进行比对,进行初始化界面测试 初始化页面数据加载分析 1.查询首页的顶级分类 select * from iwebshop_catego ...

  9. 调用钉钉API发送消息通知给个人或部门 ,钉钉后台

    https://www.pianshen.com/article/22171673623/

最新文章

  1. 招财铃:即时通信整合,
  2. mybatis-plus中 queryWrapper查询对象常见方法
  3. 使用Azure轻松实现Teams App的全球合规性
  4. 无法开启计算机,Win7下鼠标右键无法开启计算机属性怎么办?
  5. UCSB微软提出VIOLET,用Masked Visual-token Modeling进行端到端的视频语言学习!性能SOTA...
  6. GitHub#C#:在终端里面显示一个UI窗口(TerminalGfx)
  7. [Asp.net core]使用Polly网络请求异常重试
  8. C# 如何在空间运行时调整控件位置和大小
  9. 图说丨京东《技术重构社会供应链——未来科技趋势白皮书》
  10. 金角大王 python_【51CTO学院三周年】 老男孩python全栈心路
  11. 重新写了一个拼音输入法词库转换小程序
  12. MyBatis注解开发方式
  13. ubuntu下查看显卡型号
  14. AUTOCAD——中心线绘制、CAD默认线宽是多少?可以修改吗?
  15. 科研:中科大论文查新查引所用论文数据库
  16. VLAN和交换机接口模式:access、trunk、hybrid
  17. 面试经验之字节跳动暑期实习
  18. c++ eos智能合约开发_EOS开发完全解析(六):手摸手实现第一个EOS智能合约——Hello EOS...
  19. 图像透视变换原理及实现
  20. SpringBoot 直接访问静态资源

热门文章

  1. 【ROS】ROS入门笔记-Gazebo仿真与实物测试篇
  2. 每天都在吃的水果和蔬菜,你知道怎么区分吗?
  3. 计算机配置太低怎么办,计算机虚拟内存太低怎么解决?
  4. 在宝塔中把sll证书配置到nginx中,把http变为https
  5. 无限试驾2 服务器,《无限试驾 2》PC版本配置需求公布
  6. 《基因突变和基因重组》在线教学案例
  7. 2022-01-13 微信小程序-简历小项目(一) 小程序中的flex布局,简历首页的制作,箭头区域的制作
  8. 香港银行账户最新消息
  9. 插本计算机哪个2b学校好,广东专插本2B学校排名情况
  10. 1 mapinfo 前台配合 同频异频重选切换 CSFB SRVCC