对接钉钉消息通知_接入钉钉API发送企业消息
工作中有个需求,是要把录入的销售机会由系统自动分配给销售,然后对接钉钉给销售人员发送企业消息,通知他进行跟单。
参考资料
1. 获取Access_Token
Access_Token是企业访问钉钉开放平台全局接口的唯一凭证,即调用接口时需携带Access_Token。
对于企业接入来说,AccessToken需要用CorpID和CorpSecret来换取,CorpID是企业在钉钉中的标识;每个企业拥有一个唯一的CorpID,CorpSecret是企业每个微应用的凭证密钥。
注意:token 一段时间后会刷新,因此必须实时动态获取。
2. 创建微应用
比如发送企业消息,需要创建微应用,获取agent_id,步骤如下:
登录OA,点击工作台,选择『自建应用』
20180326152204804041237.png
进行微应用内容的设置,获取agent_id
20180326152204828144931.png
3. 根据需求调用对应的API
4. 编写钉钉工具类
package com.yuxin.wx.util;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.CorpMessageCorpconversationAsyncsendRequest;
import com.dingtalk.api.response.CorpMessageCorpconversationAsyncsendResponse;
import com.taobao.api.ApiException;
import com.yuxin.wx.model.user.Users;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* @Description:对接钉钉的工具类
* @Authod:zhang_cq
* @Date:2018/3/19 下午2:59
*/
public class DingDingUtil {
private static String CORPID = "Xxx"; // 企业Id
private static String CORPSECRET = "Xxx"; // 企业应用的凭证密钥
public static Long AGENTID = 1677000L; // 自动分配微应用的ID
/**
* @Description:获得token
* @Method:getToken
* @Authod:zhang_cq
* @Date:2018/3/19 下午3:00
* @param corpid 企业Id
* @param corpsecret 企业应用的凭证密钥
*/
private static String getToken(String corpid, String corpsecret){
try {
String result = ClientUtil.sendGet("https://oapi.dingtalk.com/gettoken?corpid="+ corpid + "&corpsecret=" + corpsecret);
JSONObject json = JSONObject.fromObject(result);
if (json != null && "0".equals(json.get("errcode").toString())) {
return json.get("access_token").toString();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* @Description:发送消息
* @Method:sendDDMessage
* @Authod:zhang_cq
* @Date:2018/3/19 下午4:55
* @param agentId 微应用的ID
* @param userId 接收者的用户userid列表
* @param msgcontent 消息内容
*/
public static JSONObject sendDDMessage(Long agentId, String userId, String msgcontent) {
DingTalkClient client = new DefaultDingTalkClient("https://eco.taobao.com/router/rest");
CorpMessageCorpconversationAsyncsendRequest req = new CorpMessageCorpconversationAsyncsendRequest();
req.setMsgtype("oa"); // 消息类型
req.setAgentId(agentId);
req.setUseridList(userId);
req.setToAllUser(false); // 是否发送给企业全部用户
req.setMsgcontentString(msgcontent);
try {
String token = getToken(CORPID,CORPSECRET);
CorpMessageCorpconversationAsyncsendResponse rsp = client.execute(req, token);
JSONObject json = JSONObject.fromObject(rsp.getResult());
if (json != null) {
return json;
}
} catch (ApiException e) {
e.printStackTrace();
}
return null;
}
/**
* @Description:根据部门ID获取用户信息
* @Method:getDDUsersByDeptId
* @Authod:zhang_cq
* @Date:2018/3/20 上午11:19
* @param departmentId
*/
public static List getDDUsersByDeptId(Long departmentId){
try {
String accessToken = getToken(CORPID,CORPSECRET);
String result = ClientUtil.sendGet("https://oapi.dingtalk.com/user/list?access_token="+accessToken+"&department_id=" + departmentId);
JSONObject json = JSONObject.fromObject(result);
if (json != null && "0".equals(json.get("errcode").toString())) {
JSONArray userlist = JSONArray.fromObject((json.get("userlist")));
if (userlist != null && userlist.size() > 0) {
List userList = new ArrayList();
for(int i=0;i
JSONObject user = userlist.getJSONObject(i);
String mobile = user.getString("mobile");
String userId = user.getString("userid");
String name = user.getString("name");
Users users = new Users();
if(!StringUtils.isBlank(mobile)){
users.setMobile(mobile);
users.setDDUserId(userId);
users.setRealName(name);
userList.add(users);
}
}
return userList;
}
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* @Description:根据部门ID获取用户信息(userid和name)
* @Method:getDDSimpleUsersByDeptId
* @Authod:zhang_cq
* @Date:2018/3/20
* @param accessToken
* @param departmentId
*/
public static void getDDSimpleUsersByDeptId(String accessToken, Long departmentId){
try {
String result = ClientUtil.sendGet("https://oapi.dingtalk.com/user/simplelist?access_token="+accessToken+"&department_id=" + departmentId);
JSONObject json = JSONObject.fromObject(result);
if (json != null && "0".equals(json.get("errcode").toString())) {
JSONArray userlist = JSONArray.fromObject((json.get("userlist")));
if (userlist != null && userlist.size() > 0) {
for(int i=0;i
JSONObject user = userlist.getJSONObject(i);
String name = user.getString("name");
String userId = user.getString("userid");
System.out.println(name + ":" + userId);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* @Description:获取员工的打卡记录
* @Method:getRecordInfo
* @Authod:zhang_cq
* @Date:2018/3/21 下午5:42
* @param checkDateFrom 查询考勤打卡记录的起始工作日
* @param checkDateTo 查询考勤打卡记录的结束工作日。注意,起始与结束工作日最多相隔7天
*/
private static String getRecordInfo(String userId, String checkDateFrom, String checkDateTo){
try {
String token = getToken(CORPID,CORPSECRET);
Map data = new HashMap();
data.put("userIds","["+userId+"]");
data.put("checkDateFrom",checkDateFrom);
data.put("checkDateTo",checkDateTo);
JSONObject dataJson = JSONObject.fromObject(data);
String result = sendHttpPost("https://oapi.dingtalk.com/attendance/listRecord?access_token="+token,dataJson.toString());
System.out.println(result);
JSONObject json = JSONObject.fromObject(result);
if (json != null && "0".equals(json.get("errcode").toString())) {
JSONArray recordresult = JSONArray.fromObject((json.get("recordresult")));
if (recordresult != null && recordresult.size() > 0) {
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String sendHttpPost(String url, String body) throws Exception {
String result = null;
HttpClient client = HttpClients.createDefault();
URIBuilder builder = new URIBuilder();
try {
HttpPost post = new HttpPost(url);
//设置请求头
post.setHeader("Content-Type", "application/json");
//设置请求体
post.setEntity(new StringEntity(body));
//获取返回信息
HttpResponse response = client.execute(post);
HttpEntity entity = response.getEntity();
if (entity != null) {
entity = new BufferedHttpEntity(entity);
InputStream in = entity.getContent();
byte[] read = new byte[1024];
byte[] all = new byte[0];
int num;
while ((num = in.read(read)) > 0) {
byte[] temp = new byte[all.length + num];
System.arraycopy(all, 0, temp, 0, all.length);
System.arraycopy(read, 0, temp, all.length, num);
all = temp;
}
result = new String(all,"UTF-8");
if (null != in) {
in.close();
}
}
return result;
} catch (Exception e) {
System.out.println("接口请求失败"+e.getStackTrace());
}
return result;
}
public static String doPost(String url, JSONObject jsonObject, String charset){
HttpClient httpClient = null;
HttpPost httpPost = null;
String result = null;
try{
httpClient = HttpClients.createDefault();
httpPost = new HttpPost(url);
//设置参数
List list = new ArrayList();
StringEntity entity = new StringEntity(jsonObject.toString(),charset);
entity.setContentEncoding("UTF-8");
entity.setContentType("application/json");
httpPost.setEntity(entity);
HttpResponse response = httpClient.execute(httpPost);
if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity resEntity = response.getEntity();
if(resEntity != null){
result = EntityUtils.toString(resEntity,charset);
}
}
}catch(Exception ex){
ex.printStackTrace();
}
return result;
}
/**
* @Description:销售是否上班打卡
* @Method:getSignInInfo
* @Authod:zhang_cq
* @Date:2018/3/22 上午10:08
*/
public static Boolean getSignInInfo(String userId){
String token = getToken(CORPID,CORPSECRET);
String recordUrl = "https://oapi.dingtalk.com/attendance/list?access_token=" + token;
JSONObject jsonObject = new JSONObject();
jsonObject.put("workDateFrom","2018-03-21 06:00:00");
jsonObject.put("workDateTo","2018-03-21 19:00:00");
List usersList = new ArrayList();
usersList.add(userId);
jsonObject.put("userIdList",usersList);
jsonObject.put("offset",0);
jsonObject.put("limit",1);
String result = doPost(recordUrl,jsonObject,"utf-8");
JSONObject resutJSON = jsonObject.fromObject(result);
String msg = (String)resutJSON.get("errmsg");
if("ok".equals(msg)){
JSONArray jsonArray = JSONArray.fromObject(resutJSON.get("recordresult"));
if (jsonArray != null && jsonArray.size() > 0) {
JSONObject recordInfo = JSONObject.fromObject(jsonArray.get(0));
String checkType = recordInfo.get("checkType").toString();
if("OnDuty".equals(checkType)){
return true;
}
//System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(time))); // 上班打卡时间
}
}
return false;
}
// 测试主方法
public static void main(String[] args) {
//String msgcontent = "{\"message_url\": \"http://dingtalk.com\",\"head\": {\"bgcolor\": \"FFBBBBBB\",\"text\": \"头部标题\"},\"body\": {\"title\": \"正文标题\",\"form\": [{\"key\": \"姓名:\",\"value\": \"张三\"},{\"key\": \"爱好:\",\"value\": \"打球、听音乐\"}],\"rich\": {\"num\": \"15.6\",\"unit\": \"元\"},\"content\": \"大段文本大段文本大段文本大段文本大段文本大段文本大段文本大段文本大段文本大段文本大段文本大段文本\",\"image\": \"@lADOADmaWMzazQKA\",\"file_count\": \"3\",\"author\": \"李四 \"}}";
//String msgcontent = "{\"message_url\": \"http://qixiantong.info\",\"head\": {\"bgcolor\": \"FFBBBBBB\",\"text\": \"头部标题\"},\"body\": {\"title\": \"销售机会自动分配\",\"form\": [{\"key\": \"公司名称:\",\"value\": \"腾讯\"}],\"content\": \"您的销售机会已分配,请撸起袖子抓紧干吧!\",\"image\": \"http://upload-images.jianshu.io/upload_images/763193-c46dd76b34b3d1cb.JPG?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240\",\"author\": \"云朵课堂 \"}}";
//sendDDMessage(AGENTID,"manager4807","",msgcontent);
getSignInInfo("071323270524189541");
}
}
5. 分配成功后的调用
// 钉钉通知销售
String DDUserid = sales.getDDUserId();
if(!org.apache.commons.lang.StringUtils.isBlank(DDUserid)){
String toUrl = ""; // 点击查看详情跳转的路径
String companyName = cCompany.getCompanyName()==null?"":cCompany.getCompanyName();
String msgcontent = "{\"message_url\": \""+toUrl+"\",\"head\": {\"bgcolor\": \"FFBBBBBB\",\"text\": \"头部标题\"},\"body\": {\"title\": \"销售机会自动分配\",\"form\": [{\"key\": \"公司名称:\",\"value\": \""+companyName+"\"}],\"content\": \"您的销售机会已分配,请撸起袖子抓紧干吧!\",\"image\": \"\",\"author\": \"云朵课堂 \"}}";
JSONObject json = DingDingUtil.sendDDMessage(DingDingUtil.AGENTID,DDUserid,msgcontent);
if (json != null) {
if (!"true".equals(json.get("success").toString())){
logger.info("自动分配钉钉通知销售人员失败,失败原因:" + json.get("errorMsg").toString());
}
}
}
对接钉钉消息通知_接入钉钉API发送企业消息相关推荐
- 微信服务通知消息找回_第三方平台微信服务号模板消息怎么发送
使用公众号平台模板消息功能,无法发送模板消息,如果想要发送模板消息,可以用第三方平台微号帮功能模板消息群发实现,也可自己根据公众号平台的接口开发实现,均可以为微信服务号发送模板消息,且发送模板消息不占 ...
- 企业微信加密消息体_无代码开发能保障企业系统数据的安全吗?这篇文章为你全面解析!...
轻流<无代码开发白皮书>是从五年来的行业探索经验出发,对比研究了管理软件不同开发方式的优劣,总结了管理软件未来的发展趋势,并率先对无代码开发理念进行系统性阐述:详细解读了无代码开发广阔的应 ...
- 消费消息删除_【进阶之路】可靠消息最终一致性解决方案
导言 大家好,我是南橘,从接触java到现在也有差不多两年时间了,两年时间,从一名连java有几种数据结构都不懂超级小白,到现在懂了一点点的进阶小白,学到了不少的东西.知识越分享越值钱,我这段时间总结 ...
- java qq托盘 消息提醒_如何仿QQ实现托盘闪动消息提醒
当QQ收到好友的消息时,托盘的图标会变成好友的头像,并闪动起来,点击托盘,就会弹出与好友的聊天框,随即,托盘恢复成QQ的图标,不再闪动.当然,如果还有其它的好友的消息没有提取,托盘的图标会变成另一个好 ...
- golang 实现不定数量企微群机器人消息通知 顺序必须一致 并不超过群机器人消息每分钟提醒上限20条
要实现功能: 企微机器人提醒 机器人数量不一定 机器人提醒企微有限制 一分钟不能超过20条 准备好发送markdown消息的方法 type RobotRsp struct {ErrCode int ` ...
- 公众号模板消息怎么添加?公众号如何发送模板消息的服务通知?
公众号模板消息的使用场景: 如下图所示,主要包括报名成功提醒.登陆提醒.支付凭证.订单签收/派送通知--,还有公众号在做裂变活动时,也需要通过模板消息来发送实时进度. 公众号裂变活动模板消息 所以公众 ...
- rocketmq 消息 自定义_跟我学RocketMQ[1-4]之消息消费及支持spring
博客地址:朝·闻·道www.wuwenliang.net 本文我将继续讲解如何使用DefaultMQPushConsumer对RocketMQ中的消息进行消费,同时在文章的第二部分将继续带领读者朋友 ...
- 企业微信加密消息体_微信公众平台开发者中心安全模式消息体加解密实现
关键字:微信公众平台 消息体签名 消息体加解密 EncodingAESKey 安全模式 一.消息体加解密 微信公众平台在配置服务器时,提供了3种加解密的模式供开发者选择,即明文模式.兼容模式.安全模式 ...
- mysql 消息队列_一个简单的 MySQL 批量事务消息队列
基于 MySQL 的批量事务消息队列 消息队列本质上是一个存储介质,通常是链表结构,不同的进程或线程可以向消息队列中写入或读取消息.消息队列的使用场景有很多,比如异步处理任务.应用解耦.流量削锋等等. ...
最新文章
- 考研国家线罕见大幅上涨,12个学科涨幅10分以上,超300万人将落榜
- 第6章 数组----复制数组
- 搭建kafaka_kafka单机环境搭建及其基本使用
- 第二篇:白话tornado源码之待请求阶段
- 2020 中国技术力量年度榜单
- python包括哪些部分_第一部分 Python基础篇
- 【Python】成绩等级判断
- dedecms php5.4 无法退出后台,DedeCMS 织梦在 Windows 的 PHP5.4 环境下登录后台空白的解决办法...
- 3371 【模板】单源最短路径(Dijsktra)
- Windows10安装 virtualbox虚拟机
- 图像型PDF如何免费转换成可编辑的文字
- python自动化运维快速入门 pdf 郑征_Python自动化运维快速入门
- [转]中国古代兵事纵横谈[强文]
- 半波对称振子方向图_对称振子阵列天线.ppt
- 计算机调查应用表格,大学计算机实验课_调查报告_表格模板_应用文书.doc
- Python 淘宝商品价格爬取(requests库+正则表达式)
- 泛函分析笔记2:赋范空间
- 【CTO论道】京东商城李大学:京东研发团队管理经验谈
- java计算机毕业设计网上扶贫农产品销售系统源码+系统+数据库+lw文档+mybatis+运行部署
- [转载] Elasticsearch如何做到亿级数据查询毫秒级返回