关于推送钉钉消息和钉钉群消息 -YB

钉钉消息推送

一、MES 服务里调用发送钉钉消息

参考 1:达摩院温俊可的帖子:http://119.96.220.140:9099/article/1594458652783

参考 2:CSDN:https://blog.csdn.net/weixin_44994494/article/details/123729251

或者查看官方 api 文档。
image.png

另外:IMOM16L 项目已引入,可借鉴参考。

二、长春捷翼 - 周晓星做了一个钉钉消息推送的服务:

发送 post 请求给这个服务:
image.png

效果:
image.png

三、解放传动 - 客户提供了一个钉钉接口 - 给某个人推送钉钉消息

传参:组织 id、手机号、标题、内容,即可。要求手机号对应的人员在组织里。

接口地址:String url = “https://zd-faw-cn-8n8eppuothxcry.ztna-dingtalk.com/messageserver/message/push/V2”;

调用过程:
image.png

效果:
image.png

注意:换行拼接 \n\n

项目封装方法:MsgDingDingCDService#sendDingMsg()

四、解放传动 - 需要给某个钉钉群推送钉钉消息 - 参考大柴漆亮

找漆亮沟通后实现,他的笔记:
一汽大柴 MOM 项目:钉钉消息推送开发配置 v1.0-20240305.docx

使用钉钉群的自定义机器人。

他的主要代码:

image.png

自己实现后的效果:
image.png

注意:换行拼接 \n

项目封装方法:MsgDingDingCDService#sendGroupMessage()

五、解放传动 - 钉钉群配置升级改造 -20241112

开发页面配置群,作群、类型、工作中心的关联维护:
image.png

用于实现同一种群消息类型,不同的工作中心推送给不同的群。
V20241112_ 建表钉钉群配置主子表.sql
主要代码:

/**
 * @MethodName: dingUrlCenter
 * @Description: 获取钉钉群消息的推送url。 对应功能名、工作中心编码找到对应钉钉群发送群消息-20241113 新增钉钉群配置主子表后使用。
 * @param funcName  功能节点名称
 * @param centerCode  工作中心编码
 * @Return List<String> 可能找到多个适配的钉钉群地址,就都要分别推一次
 * @Author: yuanbao
 * @Date: 2024/11/13
 **/
@SneakyThrows
private List<String> dingUrlCenter(String funcName, String centerCode)
{
	List<String> list = new ArrayList<>();
	// 钉钉群机器人地址
	String webhook = ""; // 以前默认给质量的 sysParamManager.getSysParamValByCode("DD_CD_GROUP_URL")
	String secret = ""; // sysParamManager.getSysParamValByCode("DD_CD_GROUP_SECRET")

	List<MtsDinggroupConfig> configListTotal = Lists.newArrayList();
	// 找钉钉群按功能名称匹配,是否按工作中心的分为两部分分别查询
	// a.关联工作中心的、严格匹配工作中心
	String hql = "select c from MtsDinggroupConfigCenter cc left join cc.config c where cc.isDelete=0 and c.isDelete=0" + " and c.isActive=0 and c.isRelCenter=1 and c.funcNode like '%" + funcName + "%' and cc.workCenterCode = :centerCode";
	List<MtsDinggroupConfig> configList = this.getDao().createQuery(hql).setParameter("centerCode", centerCode).list();
	configListTotal.addAll(configList);
	// b.不需要关联工作中心的
	String hql2 = "select c from MtsDinggroupConfig c where c.isDelete=0 and c.isActive=0 and c.isRelCenter!=1 and c.funcNode like '%" + funcName + "%'";
	List<MtsDinggroupConfig> configList2 = this.getDao().createQuery(hql2).list();
	configListTotal.addAll(configList2);

	// 遍历处理
	long timestamp = Instant.now().toEpochMilli();
	Mac mac = Mac.getInstance("HmacSHA256");
	for (MtsDinggroupConfig config : configListTotal)
	{
		webhook = config.getGroupUrl();
		secret = config.getGroupLicense();

		String stringToSign = timestamp + "\n" + secret;
		mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
		byte[] signData = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
		String sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8");

		String url = webhook + "&timestamp=" + timestamp + "&sign=" + sign;
		list.add(url);
	}

	return list;
}

/**
 * @MethodName: sendGroupMessage
 * @Description: 【重要】发送普通消息到钉钉群,支持 @指定的群成员,对应功能名、工作中心编码找到对应钉钉群发送群消息-20241113 新增钉钉群配置主子表后使用。
 * @param message  消息内容 text格式
 * @param isNotAll 是否 @群内所有人
 * @param userIds 被@人的手机号(支持多个)
 * @param funcName  功能节点名称
 * @param centerCode  工作中心编码
 * @Return void
 * @Author: yuanbao
 * @Date: 2024/11/13
 **/
public void sendGroupMessage(String message, boolean isNotAll, List<String> userIds, String funcName, String centerCode) throws ApiException
{
	// 1、查询钉钉群配置主子表,根据功能名、工作中心编码找到对应钉钉群
	// 可能有多个钉钉群都符合,就分别都推送一次
	List<String> dingUrlList = dingUrlCenter(funcName, centerCode);
	if (dingUrlList.size() <= 0)
	{
		MestarLogger.info(String.format("钉钉群配置没有找到符合的钉钉群,请检查!功能节点为:%s,工作中心为:%s", funcName, centerCode));
		return;
	}

	// 2、遍历钉钉群,分别发送消息
	for (String dingUrl : dingUrlList)
	{
		DingTalkClient client = new DefaultDingTalkClient(dingUrl);
		OapiRobotSendRequest request = new OapiRobotSendRequest();
		// 消息类型,此时固定为:text
		request.setMsgtype("text");
		OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
		// 消息内容
		text.setContent(message);
		request.setText(text);
		OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
		// @ 群成员list
		// 用户转化手机号
		List<String> mobiles = this.getUserMobiles(userIds, 0);
		at.setAtMobiles(mobiles);
		// 不 @ 所有人
		at.setIsAtAll(isNotAll);
		request.setAt(at);
		client.execute(request);
	}
}

六、消息的相关规范

1、消息类别:

  • WEB/APP 消息(是同一个表),推送单人还是多人。多人是分别一条还是共用同一条,如根据角色取到所有用户共用一条消息。
  • 钉钉消息
  • 钉钉群消息(需给定群名,如质量群、调度群)

2、什么时候触发推送消息

哪个页面哪个操作触发,推送什么类型的消息,消息内容是啥。

3、消息体格式:

需给定标题、内容、消息接收者。
一般某个单据的操作推送消息,其标题是固定的,内容可根据单据信息拼接,接收者为单据的某字段。

用 {} 表示取单据上的字段代入。
完整格式 DEMO:
标题:
异常发起消息
内容:
工作中心:{异常单据的工作中心字段}
工位:{异常单据的工位字段}
异常类型:{异常单据的异常类型字段}
异常内容:{异常单据的异常内容字段}
异常描述:{异常单据的异常描述字段}
发起人:{异常单据的 createId 字段,需取真实姓名}
接收者:
{异常流程中相应节点对应的角色下的所有人,逗号拼接}

4、待优化项:

  • APP 消息模块升级 webSocket- 下周优先处理掉
  • WEB 消息弹窗 - 待根据大柴

七、核心代码文件:

MsgDingDingCDService.java