钉钉企业机器人单聊消息发送实践-大数据平台(XSailboat)消息中心消息推送

发布时间:2024年01月22日

1. 背景

在笔者开发的大数据平台XSailboat中有 消息中心 模块,用来全平台的消息收集,整理分拆、订阅发送等功能。消息推送方式支持钉钉群聊、钉钉单聊、短信通知。现记录一下企业机器人消息单聊推送的实现过程。

2. 钉钉开发文档

这是官方的开发文档地址:《机器人发送、查询和撤回单聊消息》

将其中的主要过程抄录一下:

步骤一:登录开发者后台,点击应用开发-企业内部开发,创建机器人。
步骤二:点击机器人应用-基础信息,获取AppKey和AppSecret。
步骤三:添加接口调用权限,点击“机器人”,申请企业内机器人发送消息权限。申请权限无需审批,默认开通。
步骤四:上线机器人。进入版本管理与发布页面,点击上线,机器人的状态变更为已发布。
步骤五:获取应用访问凭证获取企业内部应用的accessToken。调用接口时,通过accessToken鉴权调用者身份。
步骤六:调用机器人单聊相关的API:

  • 调用服务端API-批量发送单聊消息,获取消息processQueryKey。
  • 根据消息processQueryKey,调用服务端API-批量查询单聊机器人是否已读,查询机器人发送的单聊消息对方是否已读。
  • 根据消息processQueryKey,调用服务端API-批量撤回单聊消息,撤回机器人发送的单聊消息。

3. 记录自己的操作过程

  1. 上企业的 开发者后台 创建应用(应用名:大数据平台-消息中心)。
  2. 创建了应用之后,再点进应用,创建机器人,创建好了之后发布。
    在这里插入图片描述
  3. 申请“机器人”里面的 “企业内机器人发送消息权限” 和“通讯录管理”中的 “根据手机号姓名获取成员信息的接口访问权限”
  4. 根绝Appkey和AppSecret获取token。
  1. 定向向某人发送钉钉消息时需要指定userId,而消息中心配置的消息订阅人设置的是手机号。所以需要将手机号翻译成userId。
  1. 发送消息的API。

4. 示例代码

package com.cimstech.sailboat.ms.msg;

import com.cimstech.sailboat.ms.msg.sender.Letter;
import com.cimstech.xfront.common.http.HttpClient;
import com.cimstech.xfront.common.http.Request;
import com.cimstech.xfront.common.json.JSONArray;
import com.cimstech.xfront.common.json.JSONObject;
import com.cimstech.xfront.common.text.XString;
import com.cimstech.xfront.common.time.XTime;

public class Test
{
	/**
	 * 获取token,查询userId的服务地址
	 */
	static final String sDingService = "https://oapi.dingtalk.com" ;
	
	/**
	 * 发送钉钉消息的服务地址
	 */
	static final String sDingSendService = "https://api.dingtalk.com" ;
	
	/**
	 * 凭借appKey和appSecret获取token
	 */
	static final String sPath_GetToken = "/gettoken" ;
	
	/**
	 * 通过手机号获取企业账号用户
	 */
	static final String sPath_GetUserByMobile = "/topapi/v2/user/getbymobile" ;
	
	static final String sPath_SendMsgOfSingleChat = "/v1.0/robot/oToMessages/batchSend" ;
	
	static final String sDetailPtn_n = "[以及另外{}条详情..]({})" ;
	static final String sDetailPtn_1 = "[详情..]({})" ;
	
	static final String sNoLink = "以及另外{}条" ;
	
	static String[] sColors = new String[] {"#FF0000"
			, "#ffa500"
			, "#0fdbdb"
			, "#12e512"} ;
	
	static String sDetailLink = "http://XXXXX/sailmsg/msgrow?sendBatch={}&totalAmount={}" ;
	
	static JSONObject toJSON(Letter aLetter)
	{
		int level = aLetter.getLevel() ;
		String color = level < sColors.length? sColors[level]:null ;
		StringBuilder strBld = new StringBuilder("【消息中心-").append(aLetter.getSubscriberItemName())
				.append("】")
				.append("-[") ;
		if(color != null)
			strBld.append("<font color=").append(color).append(">") ;
		strBld.append(level).append("级") ;
		if(color != null)
			strBld.append("</font>") ;
//		String partition = aLetter.getPartition() ;
		strBld.append("]") ; // .append(sSiteMap.getOrDefault(partition , partition)) ;
		String title = strBld.toString() ;
		
		strBld.setLength(0);
		strBld.append("**").append(title).append("**  \n  > ")
				.append("<font color=#000000>")
				.append(aLetter.getContent())
				.append("</font>")
				.append("  \n  \n  ") ;
		strBld.append("<font color=#666666>")
				.append(aLetter.getEventTime())
				.append("</font>")
				.append("&nbsp;&nbsp;&nbsp;&nbsp;") ;
		
		if(XString.isEmpty(sDetailLink))
		{
			if(aLetter.getReduceAmount() > 0)
				strBld.append(XString.msgFmt(sNoLink , aLetter.getReduceAmount())) ;
		}
		else
		{
			if(aLetter.getReduceAmount() > 1)
			{
				strBld.append(XString.msgFmt(sDetailPtn_n, aLetter.getReduceAmount()
						, XString.msgFmt(sDetailLink , aLetter.getSendBatch() , aLetter.getReduceAmount()))) ;
			}
			else
			{
				strBld.append(XString.msgFmt(sDetailPtn_1
						, XString.msgFmt(sDetailLink , aLetter.getSendBatch() , aLetter.getReduceAmount()))) ;
			}
		}
		String content = strBld.toString() ;
		
		return new JSONObject().put("title" , title)
						.put("text", content)
				;
	}

	public static void main(String[] args) throws Exception
	{
		String appKey = "ddddddddddddddd" ;
		String appSecret = "ssssssssssssssssssssssssssssssss" ;
		String mobile = "130XXXXXXXXX" ;
		String robotCode = "dingXXXXXXXXX" ;
		
		// 1.获取AccessToken
		HttpClient client = HttpClient.ofUrl(sDingService) ;
		long expireTime = System.currentTimeMillis() ;
		/**
		 * {
		 *   "errcode": 0,
		 *   "access_token": "aaaaaaaaaaaaaaaaa",
		 *   "errmsg": "ok",
		 *   "expires_in": 7200
		 * }
		 */
		JSONObject jo = client.askJo(Request.GET().path(sPath_GetToken)
				.queryParam("appkey" , appKey)
				.queryParam("appsecret", appSecret)) ;
		System.out.println("获取到的Token:"+jo) ;
		String accessToken = jo.optString("access_token") ;
		expireTime += jo.optLong("expires_in") * 1000 ;
		
		/**
		 * {
         *   "errcode": 0,
         *   "errmsg": "ok",
         *   "result":
         *   {
         *     "exclusive_account_userid_list": [],
         *     "userid": "bbbbbbbbbbbbb"
         *   },
         *   "request_id": "ccccccc"
         * }
		 */
		// 2. 查询userId
		jo = client.askJo(Request.POST().path(sPath_GetUserByMobile).queryParam("access_token" , accessToken)
				.setJsonEntity(new JSONObject().put("mobile" , mobile)
						.put("support_exclusive_account_search" , true))) ;
		System.out.println("获取到的User信息:"+jo);
		
		String userId = jo.pathString(null , "result" , "userid") ;
		
		
		Letter letter = new Letter(null) ;
		letter.setLevel(5);
		letter.setContent("单聊测试") ;
		letter.setEventTime(XTime.current$yyyyMMddHHmmss());
		letter.setReduceAmount(1) ;
		letter.setSendBatch("xxxxxxxxxxxxxxx") ;
		letter.setSubscriberItemName("单聊测试订阅项");
		
		String msgParam = toJSON(letter).toJSONString() ;
		
		/**
		 * {
         *   "flowControlledStaffIdList": [],
         *   "invalidStaffIdList": [],
         *   "processQueryKey": "xxxxxxxxxxxxxx"
         * }
		 */
		// 3.发送消息
		jo = HttpClient.ofUrl(sDingSendService).askJo(Request.POST().path(sPath_SendMsgOfSingleChat)
				.header("x-acs-dingtalk-access-token" , accessToken)
				.setJsonEntity(new JSONObject().put("robotCode" , robotCode)
						.put("userIds", new JSONArray().put(userId))
						.put("msgKey", "sampleMarkdown")
						.put("msgParam" , msgParam))) ;
		
		System.out.println("发送消息收到的回复:"+jo);
	}

}

效果:
在这里插入图片描述

文章来源:https://blog.csdn.net/OkGogooXSailboat/article/details/135715653
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。