Skip to content

Docs for DingTalk 1.x

Jaemon edited this page Nov 26, 2020 · 2 revisions

DingTalk 1.x使用文档

开发环境说明

  • JDK1.8
  • springboot版本: 2.0.3.RELEASE

 

引入maven依赖

    <dependency>
        <groupId>com.github.answerail</groupId>
        <artifactId>dingtalk-spring-boot-starter</artifactId>
        <version>3.0.0-RELEASE</version>
    </dependency>

 

yml配置

spring:
  dingtalk:
    # dingtalk功能开关
    enabled: true
    # 项目id, 推荐值: ${spring.application.name}
    project-id: ${spring.application.name}
    token-id: c60d4824e0ba4a30544e81212256789331d68b0085ed1a5b2279715741355fbc
    # 自定义关键字, 仅支持text和markdown消息类型
    title: 消息推送
    # 签名秘钥
    secret: APC3eb471b2761851d6ddd1abcndf2d97be21447d8818f1231c5ed61234as52d1w0
    # 是否异步执行
    async: true
    # 服务状态监控通知开关
    monitor:
      # 服务启动成功通知
      success: true
      # 服务退出通知, 注意: kill -9 <PID>不会触发通知
      exit: false
      # 服务启动失败通知
      falied: false
    # 异步处理线程池参数配置, 可选
#   executor-pool:
    # http客户端配置(优先使用项目中已有的), 可选
#   ok-http:
  • enabled: 选填, 是否启用dingtalk功能开关
  • token-id: 必填, 获取方式
  • project-id: 必填, 项目名称。 建议: 可以用 project-id 作为 钉钉机器人设置安全策略-自定义关键词(自定义关键词有长度限制,可自行截取前缀或后缀)
  • title: 选填。 默认值(通知)
  • secret: 选填, 需要签名时必填, 获取方式
  • async: 选填, true | false(默认)
  • monitor: 选填,默认值(false)
  • decrypt: 选填, 是否需要对tokenId进行加密(默认false)
  • decryptKey: 选填, tokenId解密秘钥, decrypt为true时必填, 获取方式有以下两种
    • java -jar dingtalk-spring-boot-starter-[1.0.5]-RELEASE.jar [tokenId]
    • ConfigTools.encrypt(tokenId);
  • dinger-locations: 选填, 定义 XXXDinger.xml 文件存放路径(使用xml方式定义消息体时则必填)

 

SpringBoot中使用

预警消息推送

    public class Demo {
        @Autowired
        private DingTalkSender dingTalkSender;
        
        public void test() {
            // text类型
            dingTalkSender.send(MsgTypeEnum.TEXT, "DYZ3AALTRBD2AIDLL0Y3EQ4TYGLJDUM", "服务启动通知", "服务启动异常啦。。。");
            // text类型带@
            dingTalkSender.send(MsgTypeEnum.TEXT, "DYZ3AALTRBD2AIDLL0Y3EQ4TYGLJDUM", "服务启动通知", "服务启动异常啦。。。", Lists.newArrayList("135XXXXXXXX"));
            // text类型带全部
            dingTalkSender.sendAll(MsgTypeEnum.TEXT, "DYZ3AALTRBD2AIDLL0Y3EQ4TYGLJDUM", "服务启动通知", "服务启动异常啦。。。");

            // markdown类型
            dingTalkSender.send(MsgTypeEnum.MARKDOWN, "DYZ3AALTRBD2AIDLL0Y3EQ4TYGLJDUM", "服务启动通知", "服务启动异常啦。。。");
            // markdown类型带@
            dingTalkSender.send(MsgTypeEnum.MARKDOWN, "DYZ3AALTRBD2AIDLL0Y3EQ4TYGLJDUM", "服务启动通知", "服务启动异常啦。。。", Lists.newArrayList("135XXXXXXXX"));
        }         
    }

markdown消息体暂时不支持@全部

 

其他格式消息类型

    public class Demo {
        @Autowired
        private DingTalkSender dingTalkSender;

        // 整体跳转ActionCard类型
        public void singleActionCardReq() {
            String keyword = "DYZ3AALTRBD2AIDLL0Y3EQ4TYGLJDUM";
    
            SingleActionCardReq actionCardReq = new SingleActionCardReq();
            SingleActionCardReq.SingleActionCard actionCard = new SingleActionCardReq.SingleActionCard();
            actionCardReq.setActionCard(actionCard);
            actionCard.setTitle("乔布斯 20 年前想打造一间苹果咖啡厅,而它正是 Apple Store 的前身");
            actionCard.setText("\"![screenshot](https://gw.alicdn.com/tfs/TB1ut3xxbsrBKNjSZFpXXcXhFXa-846-786.png) \n" +
                    " ### 乔布斯 20 年前想打造的苹果咖啡厅 \n" +
                    " Apple Store 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划");
            actionCard.setBtnOrientation("0");
            actionCard.setSingleTitle("阅读全文");
            actionCard.setSingleURL("https://github.com/AnswerAIL");
    
            dingTalkSender.send(keyword, actionCardReq);
        }

        // 独立跳转ActionCard类型
        public void actionCardReq() {
            String keyword = "DYZ3AALTRBD2AIDLL0Y3EQ4TYGLJDUM";
    
            ActionCardReq actionCardReq = new ActionCardReq();
            ActionCardReq.ActionCard actionCard = new ActionCardReq.ActionCard();
            actionCardReq.setActionCard(actionCard);
            actionCard.setTitle("乔布斯 20 年前想打造一间苹果咖啡厅,而它正是 Apple Store 的前身");
            actionCard.setText("![screenshot](https://gw.alicdn.com/tfs/TB1ut3xxbsrBKNjSZFpXXcXhFXa-846-786.png) \n" +
                    " ### 乔布斯 20 年前想打造的苹果咖啡厅 \n" +
                    " Apple Store 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划");
            actionCard.setBtnOrientation("0");
            List<ActionCardReq.ActionCard.Button> buttons = Lists.newArrayList();
            actionCard.setBtns(buttons);
            buttons.add(new ActionCardReq.ActionCard.Button("内容不错", "https://github.com/AnswerAIL"));
            buttons.add(new ActionCardReq.ActionCard.Button("不感兴趣", "https://github.com/AnswerAIL"));
    
            dingTalkSender.send(keyword, actionCardReq);
        }
    
        // FeedCard类型
        public void feedCardReq() {
            String keyword = "DYZ3AALTRBD2AIDLL0Y3EQ4TYGLJDUM";
    
            FeedCardReq feedCardReq = new FeedCardReq();
            FeedCardReq.FeedCard feedCard = new FeedCardReq.FeedCard();
            feedCardReq.setFeedCard(feedCard);
            List<FeedCardReq.FeedCard.Link> links = Lists.newArrayList();
            feedCard.setLinks(links);
            links.add(new FeedCardReq.FeedCard.Link("时代的火车向前开1", "https://github.com/AnswerAIL", "https://gw.alicdn.com/tfs/TB1ut3xxbsrBKNjSZFpXXcXhFXa-846-786.png"));
            links.add(new FeedCardReq.FeedCard.Link("时代的火车向前开2", "https://github.com/AnswerAIL", "https://gw.alicdn.com/tfs/TB1ut3xxbsrBKNjSZFpXXcXhFXa-846-786.png"));
    
            dingTalkSender.send(keyword, feedCardReq);
        }
    }

 


个性化整体配置


    @Configuration
    public class MyConfiguration extends DingTalkConfigurerAdapter {
        @Override
        public void configure(DingTalkManagerBuilder config) throws Exception {
            // ...
        }
    }

 


个性化独立配置


自定义消息体

    @Configuration
    public class MyConfiguration {
        // 自定义text类型消息体
        @Bean
        public CustomMessage textMessage() {
            return (dingTalkProperties, subTitle, keyword, content, phones) -> {
                String message = null;
                // ...
                return message;
            };
        }
    
        // 自定义markdown类型消息体
        @Bean
        public CustomMessage markDownMessage() {
            return (dingTalkProperties, subTitle, keyword, content, phones) -> {
                String message = null;
                // ...
                return message;
            };
        }
    }

仅支持text和markdown消息类型

 

自定义异常回调

    @Configuration
    public class MyConfiguration {
        // 自定义异常回调函数
        @Bean
        public Notice notice() {
            return (dkExCallable) -> {
                // ...
            };
        }
    }

 

自定义签名体

  • 更改前: URL_PREV&sign=XXX&timestamp=XXX
  • 更改后: URL_PREV&timestamp=XXX&sign=XXX
    @Data
    @AllArgsConstructor
    public class SignDTO extends SignBase {
        private String sign;
        private Long timestamp;
    
        @Override
        public String transfer() {
            StringBuilder signStr = new StringBuilder(SEPERATOR);
            signStr
                    .append("timestamp=").append(this.timestamp).append(SEPERATOR)
                    .append("sign=").append(this.sign);
            return signStr.toString();
        }
    }
    @Configuration
    public class MyConfiguration {
        @Bean
        public DkSignAlgorithm<SignDTO> dkSignAlgorithm() {
            return new DkSignAlgorithm<SignDTO>() {
                @Override
                public SignDTO sign(String secret) throws Exception {
                    Long timestamp = System.currentTimeMillis();
                    // TODO 使用默认算法, 如果后期算法改变, 可在此更变签名算法
                    String sign = algorithm(timestamp, secret);
                    return new SignDTO(sign, timestamp);
                }
            };
        }
    }

该功能只针对后期版本变更进行扩展, 当前版本没有使用的必要

 

自定义处理ID生成器

    @Configuration
    public class MyConfiguration {
        @Bean
        public DkIdGenerator dkIdGenerator() {
            return () -> {
                String dkid = null;
                // ...
                return dkid;
            };
        }  
    }

注意ID最好保证全局唯一,同步调用直接返回响应结果,异步操作返回处理id(dkid)

 

自定义异步执行结果回调处理器

    @Configuration
    public class MyConfiguration {
        @Bean
        public DkCallable dkCallable() {
            return (dkid, result) -> {
                // ...
            };
        }    
    }

此处方法形参(dkid, result),其中: dkid也就是异步通知的返回结果, result为请求实际的响应报文字符串。

 

自定义线程池(可选)

    @Configuration
    public class MyConfiguration {
        @Bean
        public Executor dingTalkExecutor() {
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            // ...
            return executor;
        }
    }

注意开启异步处理时使用内置线程池, 如果项目中有定义其他线程池配置, 注入线程池对象时请指定线程池名称。 如: @Qualifier("executor")

 

自定义http客户端(可选)

    @Configuration
    public class MyConfiguration {
        @Bean
        public OkHttpClient okHttpClient() {
            // ...
        }
    }

 


自定义服务状态通知消息体


服务状态通知需艾特所有人

    @Configuration
    public class MyConfiguration {
        @Bean
        public Notification notification() {
            return new DefaultApplicationEventNotification() {
                @Override
                public MsgType message(String text) {
                    TextReq message = (TextReq) super.message(text);
                    Message.At at = new Message.At();
                    at.setIsAtAll(true);
                    message.setAt(at);
                    return message;
                }
            };
        }
    }
    

 

服务状态通知只需启动失败时艾特所有人,其他情况不艾特

    @Configuration
    public class MyConfiguration {
        @Bean
        public Notification notification() {
            return new DefaultApplicationEventNotification() {
                @Override
                public MsgType failed(ApplicationFailedEvent event, String projectId) {
                    TextReq message = (TextReq) super.failed(event, projectId);
                    Message.At at = new Message.At();
                    at.setIsAtAll(true);
                    message.setAt(at);
                    return message;
                }
            };
        }
    }

 

服务状态通知需自定义消息内容

    @Configuration
    public class MyConfiguration {
        @Bean
        public Notification notification() {
            return new Notification() {
                @Override
                public String successMessage(ApplicationReadyEvent event, String projectId) {
                    String message = null;
                    // TODO ...
                    return message;
                }
    
                @Override
                public String failedMessage(ApplicationFailedEvent event, String projectId) {
                    String message = null;
                    // TODO ...
                    return message;
                }
    
                @Override
                public String exitMessage(ContextClosedEvent event, String projectId) {
                    String message = null;
                    // TODO ...
                    return message;
                }
            };
        }    
    }
Clone this wiki locally