您的位置:首页 > 教育 > 锐评 > 设计素材网站特点_影视广告制作拍摄公司_seo营销培训_杭州网站外包

设计素材网站特点_影视广告制作拍摄公司_seo营销培训_杭州网站外包

2025/1/8 1:39:02 来源:https://blog.csdn.net/qq_31745863/article/details/144968857  浏览:    关键词:设计素材网站特点_影视广告制作拍摄公司_seo营销培训_杭州网站外包
设计素材网站特点_影视广告制作拍摄公司_seo营销培训_杭州网站外包

钉钉官方文档(Webhook同步数据)

在这篇博客中,我们将详细介绍如何使用 Spring Boot 集成钉钉机器人,构建一个发送钉钉消息的服务,并通过 OkHttp 实现 HTTP 请求,同时使用 Hutool 提供便捷的 POST 请求工具。


功能概述

本服务的主要功能是通过钉钉机器人接口发送 Markdown 格式的消息。

  • 自动化生成签名(sign)以保障接口安全。
  • 支持 @ 特定用户或全体成员。
  • 使用 OkHttpClient 发送 POST 请求。
  • 支持以 JSON 格式组织消息内容。

实现步骤

1. 新建群聊(添加机器人)

设置关键词keyword,加签获取secret

完成后拿到Webhook

2. 配置依赖

在项目的 pom.xml 文件中引入必要的依赖:

<dependencies><!-- Spring Boot Starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><!-- Hutool 工具类 --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.10</version></dependency><!-- OkHttp --><dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>4.11.0</version></dependency><!-- FastJSON 2 --><dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId><version>2.0.36</version></dependency>
</dependencies>

3. 配置钉钉机器人参数

钉钉机器人支持text、link、markdown、actionCard、feedCard这几种消息类型,本文使用的markdown,如果需要使用其他类型可以查看官方文档钉钉官方文档(Webhook同步数据)

参数参数类型是否必填说明
msgtypeString消息类型,此时固定为:markdown。
titleString首屏会话透出的展示内容。
textStringmarkdown格式的消息。
atMobilesArray在content里添加被@人的手机号。
提示:只有在群内的成员才可被@,非群内成员手机号会被脱敏
atUserIdsArray在content里添加被@人的用户userid。
isAtAllBoolean是否@所有人。

application.yml 文件中配置钉钉机器人的参数:

ding:webhook: "https://oapi.dingtalk.com/robot/send?access_token=add7e41373b48a88ae9be86a2065e525xxxxxxxxx"keyword: "收到客户提单"secret: "xxxxxxxxxxx9fe24ff0d72ccxxxxxxx"white-ip: []at-all: trueat-user-ids: []at-mobiles: []

4. 配置markdown消息

import cn.hutool.core.util.ArrayUtil;
import lombok.*;
import javax.validation.constraints.NotBlank;
import java.util.Arrays;@Data
public class MarkDownMessage {private static String keyword = "[收到客户提单]";/*** 消息类型,固定为markdown*/@Setter(AccessLevel.NONE)private final String msgtype = "markdown";private MarkDown markdown = new MarkDown();private AT at = new AT();/*** 消息内容*/@Getter@NoArgsConstructor@AllArgsConstructorpublic class MarkDown {/*** 首屏会话透出的展示内容*/@NotBlank@Setterprivate String title = "客户信息";/*** markdown格式的消息* note: 如果钉钉配置中使用了keyword,那么消息体中必须包含keyword;* 如果使用了@功能,也要包含@人的手机号,格式为@150xxxxxxxx*/@NotBlankprivate String text;public void setText(String text) {StringBuilder sb = new StringBuilder();if (ArrayUtil.isNotEmpty(at.getAtMobiles())) {Arrays.stream(at.getAtMobiles()).forEach(sb::append);}sb.append("\n").append(keyword).append("\n").append(text);this.text = sb.toString();}public void setText(String serverName, String env, String url, String msg, String level,String scene) {StringBuilder sb = new StringBuilder();if (ArrayUtil.isNotEmpty(at.getAtMobiles())) {Arrays.stream(at.getAtMobiles()).forEach(mobile -> {sb.append("@").append(mobile);});}sb.append("\n").append(keyword).append("\n").append("客户信息:" + msg);this.text = sb.toString();}}/*** 使用@消息配置*/@Data@NoArgsConstructor@AllArgsConstructorpublic class AT {/*** 被@人的手机号* note: 在text内容里要有@人的手机号*/private String[] atMobiles;/*** 被@人的用户userid*/private String[] atUserIds;/*** 是否@所有人*/private boolean isAtAll;}
}

5. 创建服务实现类

服务类 SendDingServiceImpl 核心逻辑如下:

实现核心功能

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.domain.entity.sms.MessageReq;
import com.ruoyi.common.core.domain.model.msg.MarkDownMessage;
import com.ruoyi.common.core.domain.model.resp.DingRep;
import com.ruoyi.system.service.SendDingMsgService;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.net.URLEncoder;@Slf4j
@Service
public class SendDingServiceImpl implements SendDingMsgService {@Value("${ding.webhook}")private String webhook;@Value("${ding.at-all}")private boolean isAll;@Value("${ding.at-user-ids}")private String[] ids;@Value("${ding.at-mobiles}")private String[] mobiles;@Value("${ding.secret}")private String secret;private final OkHttpClient okHttpClient;public SendDingServiceImpl() {okHttpClient = new OkHttpClient();}@Overridepublic void send(MessageReq req) {String type = "application/json; charset=utf-8";MarkDownMessage markDownMsg = new MarkDownMessage();MarkDownMessage.AT at = markDownMsg.getAt();at.setAtAll(isAll);at.setAtMobiles(mobiles);at.setAtUserIds(ids);MarkDownMessage.MarkDown markdown = markDownMsg.getMarkdown();JSONObject jsonObject = new JSONObject();jsonObject.put("客户姓名", req.getName());jsonObject.put("联系方式", req.getPhone());jsonObject.put("公司名称", req.getCorporate());jsonObject.put("工作邮箱", req.getMailbox());jsonObject.put("需求信息", req.getDemand());markdown.setText("", "", "", jsonObject.toJSONString(), "", "");try {RequestBody body = RequestBody.create(MediaType.parse(type), JSONObject.toJSONString(markDownMsg));Request.Builder builder = new Request.Builder().url(webhook + "&timestamp=" + System.currentTimeMillis() + "&sign=" + getSign(secret));builder.addHeader("Content-Type", type).post(body);Request request = builder.build();Response response = okHttpClient.newCall(request).execute();String rep = response.body().string();DingRep dingRep = JSONObject.parseObject(rep, DingRep.class);if (dingRep.getErrcode() == 0 || dingRep.getErrmsg().equals("ok")) {log.info("钉钉发送消息成功,发送内容:{}", markDownMsg.toString());} else {log.warn("钉钉发送消息失败,发送内容:{}, 失败内容:{}", markDownMsg.toString(), dingRep.toString());}} catch (IOException e) {log.error("钉钉发送消息失败,失败内容:{}", e.getMessage());}}public String getSign(String secret) {String sign = null;try {Long timestamp = System.currentTimeMillis();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"));sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8");} catch (Exception e) {log.error("获取签名失败,失败内容:{}", e.getMessage());}return sign;}
}

6. MessageReq

import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class MessageReq implements Serializable {private static final long serialVersionUID = 1L;@ApiModelProperty("用户姓名")private String name;@ApiModelProperty("联系方式")private String phone;@ApiModelProperty("公司名称")private String corporate;@ApiModelProperty("工作邮箱")private String mailbox;@ApiModelProperty("需求")private String demand;}

测试

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com