springboot集成钉钉,发送钉钉日报

目录

1.说明

2.示例

3.总结


1.说明

学习地图 - 钉钉开放平台

在钉钉开放文档中可以查看有关日志相关的api,主要用到以下几个api:

①获取模板详情

②获取用户发送日志的概要信息

③获取日志接收人员列表

④创建日志

发送日志时需要根据模板规定日志的格式,所以先获取要发送日志的模板信息,然后获取用户在最近一段时间内发送的日志的概要信息,并根据最新一次的日志信息获取日志的接收人员信息,然后调用创建日志的api,设置日志内容,及接收人员。

2.示例

依赖

        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>alibaba-dingtalk-service-sdk</artifactId>
            <version>2.0.0</version>
        </dependency>

钉钉工具类

package com.kingagroot.info.common.tools.common;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.*;
import com.dingtalk.api.response.*;
import com.kingagroot.info.common.contants.CommonContants;
import com.kingagroot.info.common.tools.thirdparty.DingDingTool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.*;

/**
 * @Author linaibo
 * @Date 2024/1/6 16:18
 * @Version 1.0
 */
@Component
public class DingTool {

    private static LogTool logTool;

    @Autowired
    public void setLogTool(LogTool logTool) {
        DingTool.logTool = logTool;
    }

    // 权限用户名
    private static String accessKey;
    // 权限密码
    private static String secret;
    // agent_id
    private static Long agentId;
    // tokenUrl
    private static String tokenUrl;
    // 发送消息url
    private static String sendMsgUrl;
    // 系统url
    private static String sysUrl;
    // 模板名称
    private static String dingTemplateName;
    // 模板url
    private static String dingTemplateUrl;
    // 创建日报url
    private static String dingCreateUrl;
    // 日志信息url
    private static String simpleListUrl;
    // 接收人信息url
    private static String receiverUrl;


    @NacosValue(value = "${dingding.appkey}", autoRefreshed = true)
    public void setAccessKey(String accessKey) {
        DingTool.accessKey = accessKey;
    }

    @NacosValue(value = "${dingding.appsecret}", autoRefreshed = true)
    public void setSecret(String secret) {
        DingTool.secret = secret;
    }

    @NacosValue(value = "${dingding.agentId}", autoRefreshed = true)
    public void setAgentId(Long agentId) {
        DingTool.agentId = agentId;
    }

    @NacosValue(value = "${dingding.gettoken}", autoRefreshed = true)
    public void setTokenUrl(String tokenUrl) {
        DingTool.tokenUrl = tokenUrl;
    }

    @NacosValue(value = "${dingding.sendMsg}", autoRefreshed = true)
    public void setSendMsgUrl(String sendMsgUrl) {
        DingTool.sendMsgUrl = sendMsgUrl;
    }

    @NacosValue(value = "${sys.url}", autoRefreshed = true)
    public void setSysUrl(String sysUrl) {
        DingTool.sysUrl = sysUrl;
    }

    @NacosValue(value = "${dingding.templateName}", autoRefreshed = true)
    public void setDingTemplateName(String dingTemplateName) {
        DingTool.dingTemplateName = dingTemplateName;
    }

    @NacosValue(value = "${dingding.templateUrl}", autoRefreshed = true)
    public void setDingTemplateUrl(String dingTemplateUrl) {
        DingTool.dingTemplateUrl = dingTemplateUrl;
    }

    @NacosValue(value = "${dingding.createUrl}", autoRefreshed = true)
    public void setDingCreateUrl(String dingCreateUrl) {
        DingTool.dingCreateUrl = dingCreateUrl;
    }

    @NacosValue(value = "${dingding.simpleListUrl}", autoRefreshed = true)
    public void setSimpleListUrl(String simpleListUrl) {
        DingTool.simpleListUrl = simpleListUrl;
    }

    @NacosValue(value = "${dingding.receiverUrl}", autoRefreshed = true)
    public void setReceiverUrl(String receiverUrl) {
        DingTool.receiverUrl = receiverUrl;
    }

    /**
     * 获取钉钉token
     *
     * @return
     */
    public static String getDingToken() {
        DingTalkClient client = new DefaultDingTalkClient(tokenUrl);
        OapiGettokenRequest request = new OapiGettokenRequest();
        request.setAppkey(accessKey);
        request.setAppsecret(secret);
        request.setHttpMethod("GET");
        try {
            OapiGettokenResponse response = client.execute(request);
            if (response.isSuccess()) {
                // 调用成功返回token信息
                return response.getAccessToken();
            }
            // 调用接口异常,输出异常信息,发送钉钉通知
            processErrMsg("getDingToken", "获取钉钉token失败", JSON.toJSONString(response));
        } catch (Exception e) {
            // 调用接口异常,输出异常信息
            processErrMsg("getDingToken", "获取钉钉token失败", JSON.toJSONString(e));
        }
        return null;
    }

    public static void processErrMsg(String method, String errorMsg, String responseMsg, String... dingId) {
        StringBuilder errMsg = new StringBuilder();
        errMsg.append(errorMsg).append(",响应信息:").append(JSON.toJSONString(responseMsg));
        if (dingId.length != CommonContants.NUM_0) {
            errMsg.append(",钉钉id:").append(dingId[0]);
        }
        logTool.saveExceptionLog("", "DingTool", method, errMsg.toString());
        DingDingTool.sendDingMsg(errMsg.toString());
    }

    /**
     * 发送钉钉通知
     *
     * @param token
     * @param pwd
     * @param userCode
     */
    public static boolean sendMsg(String token, String pwd, String userCode) {
        DingTalkClient client = new DefaultDingTalkClient(sendMsgUrl);
        OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request();
        request.setAgentId(agentId);
        request.setUseridList(userCode);
        request.setToAllUser(false);

        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
        msg.setMsgtype("text");
        msg.setText(new OapiMessageCorpconversationAsyncsendV2Request.Text());
        StringBuilder content = new StringBuilder();
        content.append("系统地址: ");
        content.append(sysUrl);
        content.append("  ");
        content.append("密码: ");
        content.append(pwd);
        msg.getText().setContent(content.toString());
        request.setMsg(msg);

        try {
            OapiMessageCorpconversationAsyncsendV2Response result = client.execute(request, token);
            if (result.isSuccess()) {
                return true;
            }
            // 调用接口异常,输出异常信息
            processErrMsg("sendMsg", "发送钉钉消息(密码)失败", JSON.toJSONString(result));
        } catch (Exception e) {
            // 调用接口异常,输出异常信息
            processErrMsg("sendMsg", "发送钉钉消息(密码)失败", JSON.toJSONString(e));
        }
        return false;
    }

    /**
     * 发送钉钉通知
     *
     * @param token
     * @param message
     * @param dingId
     */
    public static void sendMessage(String token, String message, String dingId) {
        DingTalkClient client = new DefaultDingTalkClient(sendMsgUrl);
        OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request();
        request.setAgentId(agentId);
        // 设置接收者列表
        request.setUseridList(dingId);
        // 是否发送给公司全员
        request.setToAllUser(false);
        // 设置发送的消息类型及消息内容
        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
        msg.setMsgtype(CommonContants.TEXT);
        msg.setText(new OapiMessageCorpconversationAsyncsendV2Request.Text());
        msg.getText().setContent(message);
        request.setMsg(msg);
        try {
            OapiMessageCorpconversationAsyncsendV2Response result = client.execute(request, token);
            if (result.isSuccess()) {
                return;
            }
            // 调用接口异常,输出异常信息
            processErrMsg("sendMessage", "发送钉钉消息失败", JSON.toJSONString(result));
        } catch (Exception e) {
            // 调用接口异常,输出异常信息
            processErrMsg("sendMessage", "发送钉钉消息失败", JSON.toJSONString(e));
        }
    }


    /**
     * 查询钉钉模板信息
     *
     * @param token
     * @param dingId
     */
    public static OapiReportTemplateGetbynameResponse.ReportTemplateResponseVo getTemplate(String token, String dingId) {
        DingTalkClient client = new DefaultDingTalkClient(dingTemplateUrl);
        OapiReportTemplateGetbynameRequest req = new OapiReportTemplateGetbynameRequest();
        req.setUserid(dingId);
        req.setTemplateName(dingTemplateName);
        try {
            OapiReportTemplateGetbynameResponse rsp = client.execute(req, token);
            if (rsp.isSuccess()) {
                // 日志内容的校验
                if (CollUtil.isEmpty(rsp.getResult().getFields()) ||
                        !Objects.equals(rsp.getResult().getFields().get(0).getType(), CommonContants.LONG_1)) {
                    processErrMsg("getTemplate", "模板内容已经修改", JSON.toJSONString(rsp.getResult()), dingId);
                    sendMessage(token, "模板内容已经修改,系统无法进行日志推送,请自行发送。" + DateUtil.formatDateTime(new Date()), dingId);
                    return null;
                }
                return rsp.getResult();
            }
            // 调用接口异常,输出异常信息,发送钉钉通知
            processErrMsg("getTemplate", "获取作物育种信息模板失败", JSON.toJSONString(rsp), dingId);
            sendMessage(token, "获取作物育种信息模板失败,系统无法进行日志推送,请自行发送。" + DateUtil.formatDateTime(new Date()), dingId);
        } catch (Exception e) {
            // 调用接口异常,输出异常信息,发送钉钉通知
            processErrMsg("getTemplate", "获取作物育种信息模板失败", JSON.toJSONString(e), dingId);
            sendMessage(token, "获取作物育种信息模板失败,系统无法进行日志推送,请自行发送。" + DateUtil.formatDateTime(new Date()), dingId);
        }
        return null;
    }


    /**
     * 获取用户在某个时间段的日志信息
     *
     * @param dingId
     * @param token
     * @return
     */
    public static OapiReportSimplelistResponse.ReportOapiVo getSimpleReport(String token, String dingId) {
        DingTalkClient client = new DefaultDingTalkClient(simpleListUrl);
        OapiReportSimplelistRequest req = new OapiReportSimplelistRequest();
        long endTime = System.currentTimeMillis();
        long startTime = Instant.now().minus(CommonContants.LONG_21, ChronoUnit.DAYS).toEpochMilli();
        req.setStartTime(startTime);
        req.setEndTime(endTime);
        req.setTemplateName(dingTemplateName);
        req.setUserid(dingId);
        req.setCursor(CommonContants.LONG_0);
        req.setSize(CommonContants.LONG_20);
        try {
            OapiReportSimplelistResponse rsp = client.execute(req, token);
            if (rsp.isSuccess()) {
                List<OapiReportSimplelistResponse.ReportOapiVo> dataList = rsp.getResult().getDataList();
                if (CollUtil.isEmpty(dataList)) {
                    DingDingTool.sendDingMsg("获取最近的日志信息为空,钉钉id:" + dingId);
                    sendMessage(token, "获取最近的日志信息为空,系统无法进行日志推送,请自行发送。" + DateUtil.formatDateTime(new Date()), dingId);
                    return null;
                } else {
                    // 获取最新一次的日报信息
                    Optional<OapiReportSimplelistResponse.ReportOapiVo> lastReport = dataList.stream()
                            .max(Comparator.comparingLong(OapiReportSimplelistResponse.ReportOapiVo::getCreateTime));
                    return lastReport.get();
                }
            }
            processErrMsg("getSimpleReport", "获取最近的日志信息失败", JSON.toJSONString(rsp), dingId);
            sendMessage(token, "获取最近的日志信息失败,系统无法进行日志推送,请自行发送。" + DateUtil.formatDateTime(new Date()), dingId);
        } catch (Exception e) {
            processErrMsg("getSimpleReport", "获取最近的日志信息失败", JSON.toJSONString(e), dingId);
            sendMessage(token, "获取最近的日志信息失败,系统无法进行日志推送,请自行发送。" + DateUtil.formatDateTime(new Date()), dingId);
        }
        return null;
    }

    public static List<String> getReceiver(OapiReportSimplelistResponse.ReportOapiVo report, String token) {
        DingTalkClient client = new DefaultDingTalkClient(receiverUrl);
        OapiReportReceiverListRequest req = new OapiReportReceiverListRequest();
        req.setReportId(report.getReportId());
        try {
            OapiReportReceiverListResponse rsp = client.execute(req, token);
            if (rsp.isSuccess()) {
                List<String> useridList = rsp.getResult().getUseridList();
                if (CollUtil.isEmpty(useridList)) {
                    DingDingTool.sendDingMsg("查询的日志接收人信息为空,请求信息:" + JSON.toJSONString(report));
                    sendMessage(token, "查询的日志接收人信息为空,系统无法进行日志推送,请自行发送。" + DateUtil.formatDateTime(new Date()), report.getCreatorId());
                    return null;
                }
                return useridList;
            }
            processErrMsg("getReceiver", "查询日志的接收人信息失败", JSON.toJSONString(rsp), report.getCreatorId());
            sendMessage(token, "查询日志的接收人信息失败,系统无法进行日志推送,请自行发送。" + DateUtil.formatDateTime(new Date()), report.getCreatorId());
        } catch (Exception e) {
            processErrMsg("getReceiver", "查询日志的接收人信息失败", JSON.toJSONString(e), report.getCreatorId());
            sendMessage(token, "查询日志的接收人信息失败,系统无法进行日志推送,请自行发送。" + DateUtil.formatDateTime(new Date()), report.getCreatorId());
        }
        return null;
    }

    /**
     * 发送钉钉日报
     *
     * @param createDataParam
     * @param token
     */
    public static void createReport(OapiReportCreateRequest.OapiCreateReportParam createDataParam, String token) {
        DingTalkClient client = new DefaultDingTalkClient(dingCreateUrl);
        OapiReportCreateRequest req = new OapiReportCreateRequest();
        req.setCreateReportParam(createDataParam);
        try {
            OapiReportCreateResponse rsp = client.execute(req, token);
            if (!rsp.isSuccess()) {
                // 调用接口异常,输出异常信息
                processErrMsg("createReport", "发送日报失败", JSON.toJSONString(rsp), JSON.toJSONString(createDataParam));
                sendMessage(token, "系统发送日志失败,请自行发送。" + DateUtil.formatDateTime(new Date()), createDataParam.getUserid());
            }
        } catch (Exception e) {
            // 调用接口异常,输出异常信息
            processErrMsg("createReport", "发送日报失败", JSON.toJSONString(e), JSON.toJSONString(createDataParam));
            sendMessage(token, "系统发送日志失败,请自行发送。" + DateUtil.formatDateTime(new Date()), createDataParam.getUserid());
        }
    }
}

发送钉钉日报

    /**
     * 发送钉钉日报
     *
     * @param farmWorkMap
     */
    private void processDingTalkReports(Map<String, List<FarmInfoDto>> farmWorkMap) {
        // 钉钉id为空的用户列表,此类用户没有加入钉钉组织
        StringBuilder errUserId = new StringBuilder();
        // 循环农事信息列表,进行如下处理
        for (Map.Entry<String, List<FarmInfoDto>> farm : farmWorkMap.entrySet()) {
            // 用户及钉钉id
            String userId = farm.getKey();
            String dingId = farm.getValue().get(0).getDingId();
            // 钉钉id为空时,无法进行发送处理
            if (StrUtil.isBlank(dingId)) {
                errUserId.append(userId).append(",");
                continue;
            }
            // 获取钉钉的token信息
            String dingToken = getDingToken();
            if (StrUtil.isBlank(dingToken)) {
                continue;
            }
            // 获取模板信息
            OapiReportTemplateGetbynameResponse.ReportTemplateResponseVo template =
                    DingTool.getTemplate(dingToken, dingId);
            if (ObjectUtil.isNull(template)) {
                continue;
            }
            // 获取接收人信息
            OapiReportSimplelistResponse.ReportOapiVo simpleReport = DingTool.getSimpleReport(dingToken, dingId);
            List<String> receiver = new ArrayList<>();
            if (ObjectUtil.isNotNull(simpleReport)) {
                receiver = DingTool.getReceiver(simpleReport, dingToken);
            }
            if (CollUtil.isNotEmpty(receiver)) {
                // 构建发送日报的请求信息
                OapiReportCreateRequest.OapiCreateReportParam createDataParam = getCreateDataParam(template, farm, receiver);
                // 发送钉钉日报
                DingTool.createReport(createDataParam, dingToken);
            }
        }
        // 如果有问题的用户列表不为空,则将有问题的用户列表推送至钉钉群中
        if (StrUtil.isNotEmpty(errUserId)) {
            DingDingTool.sendDingMsg("以下用户不存在钉钉id,用户:" + errUserId);
        }
    }

    // 获取钉钉token
    public String getDingToken() {
        String dingDingToken = RedisTool.getString(redisEntr.getJedis(), CommonContants.DINGDING_TOKEN);
        if (StrUtil.isEmpty(dingDingToken)) {
            // 获取token
            dingDingToken = DingTool.getDingToken();
            // 存储token
            RedisTool.setString(redisEntr.getJedis(), CommonContants.DINGDING_TOKEN, dingDingToken, 5400);
        }
        return dingDingToken;
    }

 /**
     * 获取创建日报的请求信息
     *
     * @param template
     * @param farmMap
     */
    public OapiReportCreateRequest.OapiCreateReportParam getCreateDataParam(OapiReportTemplateGetbynameResponse.ReportTemplateResponseVo template,
                                                                            Map.Entry<String, List<FarmInfoDto>> farmMap,
                                                                            List<String> receivers) {
        // 获取模板内容信息
        List<OapiReportTemplateGetbynameResponse.Fields> fields = template.getFields();
        // 构建创建日报请求结构
        OapiReportCreateRequest.OapiCreateReportParam createReportParam = new OapiReportCreateRequest.OapiCreateReportParam();
        List<OapiReportCreateRequest.OapiReportContentVo> list = new ArrayList<>();
        OapiReportCreateRequest.OapiReportContentVo obj = new OapiReportCreateRequest.OapiReportContentVo();
        list.add(obj);
        // 添加日报内容,只添加模板的第一项
        OapiReportTemplateGetbynameResponse.Fields field = fields.get(0);
        obj.setSort(field.getSort());
        obj.setType(field.getType());
        obj.setContentType(CommonContants.MARKDOWN);
        StringBuilder farmInfo = new StringBuilder();
        for (int i = 0; i < farmMap.getValue().size(); i++) {
            FarmInfoDto farm = farmMap.getValue().get(i);
            farmInfo.append(i + 1).append(". ").append(farm.getBsName()).append(" ").append(farm.getFarmName()).append(" ");
            if (farm.getWorkCount().compareTo(BigDecimal.ZERO) > CommonContants.NUM_0) {
                farmInfo.append(farm.getWorkCount().stripTrailingZeros().toPlainString()).append(farm.getWorkValue()).append(" ");
            }
            if (StrUtil.isNotBlank(farm.getParticipants())) {
                farmInfo.append("参与人:").append(farm.getParticipants());
            }
            farmInfo.append("\n");
        }
        obj.setContent(farmInfo.toString());
        obj.setKey(field.getFieldName());
        createReportParam.setContents(list);
        // 设置汇报人信息
        createReportParam.setToUserids(receivers);
        // 设置模板id
        createReportParam.setTemplateId(template.getId());
        // 是否发送单聊消息
        createReportParam.setToChat(false);
        // 日志来源
        createReportParam.setDdFrom(CommonContants.TJNS);
        // 创建日志的用户id
        createReportParam.setUserid(template.getUserid());

        return createReportParam;
    }

3.总结

①我使用的是企业内部创建应用的方式,创建应用后可以拿到应用的凭证信息。

②要调用日志相关的接口,需要开通日志接口的权限信息,如下:

③测试时,可以创建一个企业账号,然后创建应用,并开通日志相关接口的权限,拉入相关人员,设置日志模板,并设置人员的上下级关系进行测试。

相关推荐
winxp-pic7 天前
“腾讯、钉钉、飞书” 会议开源平替,免费功能强大
钉钉·飞书
水兵没月7 天前
钉钉群机器人设置——python版本
python·机器人·钉钉
岚天start11 天前
Shell脚本一键推送到钉钉告警并@指定人
钉钉·shell·脚本·告警·钉钉告警·艾特
gf132111111 天前
python_在钉钉群@人员发送消息
android·python·钉钉
gf132111111 天前
【python_钉钉群发图片】
钉钉
研究司马懿14 天前
【DevOps】Jenkins配置钉钉邮件通知
运维·pipeline·jenkins·钉钉·devops
会写代码的健身爱好者15 天前
钉钉消息推送()
java·服务器·钉钉
接口写好了吗17 天前
【流程设计】类似钉钉的流程设计功能样式demo
开发语言·javascript·钉钉·流程设计·oa审核流程
liuzmx20 天前
【钉钉在线笔试题】字符串表达式的加减法
笔记·python·钉钉