接入钉钉API发送企业消息

工作中有个需求,是要把录入的销售机会由系统自动分配给销售,然后对接钉钉给销售人员发送企业消息,通知他进行跟单。


1. 获取Access_Token

Access_Token是企业访问钉钉开放平台全局接口的唯一凭证,即调用接口时需携带Access_Token

对于企业接入来说,AccessToken需要用CorpIDCorpSecret来换取,CorpID是企业在钉钉中的标识;每个企业拥有一个唯一的 CorpID,CorpSecret 是企业每个微应用的凭证密钥。

注意:token 一段时间后会刷新,因此必须实时动态获取。

获取方式:token获取方式

2. 创建微应用

比如发送企业消息,需要创建微应用,获取agent_id,步骤如下:

  1. 登录 OA,点击工作台,选择『自建应用』
    20180326152204804041237.png
  2. 进行微应用内容的设置,获取 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"; // 企业Idprivate 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<Users> 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<Users> userList = new ArrayList<Users>();for(int i=0;i<userlist.size();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<userlist.size();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<String, String> data = new HashMap<String, String>();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<NameValuePair> list = new ArrayList<NameValuePair>();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<String> usersList = new ArrayList<String>();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\": \"李四 \"}}";sendDDMessage(AGENTID,"manager4807","",msgcontent);}
}

5. 分配成功后的调用

// 钉钉通知销售
String DDUserid = sales.getDDUserId();
if(!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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/19853.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

钉钉通知-调用钉钉发送企业内部消息开发

首先&#xff0c;我们要明确需求&#xff1a;自己的系统需要发送通知消息到用户&#xff0c;接收消息用户为同一企业内的人员&#xff0c;选用短信可能涉及到费用问题&#xff0c;故可以选用钉钉或者企业微信&#xff0c;在此我使用钉钉进行发送消息。 调用钉钉发送企业内部消…

Prometheus+Alertmanager+webhook-dingtalk实现钉钉告警

文章目录 一、前提准备及规划二、安装及启动2.1 Prometheus安装启动2.2 Node_export安装启动2.3 Alertmanager安装启动2.4 Webhook-dingtalk安装启动 三、配置及测试3.1 Webhook-dingtalk配置钉钉webhook地址3.2 Alertmanager配置钉钉告警3.3 Prometheus集成Alertmanager及告警…

和chatgpt学架构02-环境搭建

目录 1 安装vs code2 vs code功能介绍3 安装nodejs4 安装vue5 在vs code打开工程总结 我们在上一篇 技术选型 里咨询了chatgpt前后端的框架选择和数据库的选择。有了框架之后就需要选择合适的开发工具了&#xff0c;继续咨询一下chatgpt 我现在选型&#xff0c;前端使用vue&am…

〖编程初学者的自我修养 - 职业规划篇①〗- 大学生选择职业前的自我认知与剖析

历时18个月&#xff0c;采访 850 得到的需求。 不管你是在校大学生、研究生、还是在职的小伙伴&#xff0c;该专栏有你想要的职业规划、简历、面试的答案。说明&#xff1a;该文属于 编程初学者的自我修养 专栏&#xff0c;购买任意白宝书体系化专栏可加入易编程社区&#xff0…

谷歌Bard被曝剽窃ChatGPT?BERT一作跳槽OpenAI,揭惊天内幕

【导读】谷歌有大麻烦了&#xff01;外媒爆料说&#xff0c;Bard的训练数据部分来自ChatGPT。谷歌可能跳到黄河里也洗不清了。 3月29日&#xff0c;外媒The Information曝出了一个惊天大瓜&#xff01; 谷歌的离职员工、已跳槽OpenAI的顶级研究员竟然曝出——Bard竟是用ChatG…

人工智能AIGC最新综述:从 GAN 到 ChatGPT 的AI生成历史

一句话总结 本综述全面回顾了生成模型的历史、基本模型组件、AIGC从单模态交互和多模态交互的最新进展&#xff0c;以及模态之间的交叉应用&#xff0c;最后讨论了AIGC中存在的开放问题和未来挑战。 摘要 最近&#xff0c;ChatGPT 与 DALL-E-2 和 Codex 一起受到了社会的广泛关…

ChatGPT is not all you need,一文综述6大公司9类生成式AI模型

关注并星标 从此不迷路 计算机视觉研究院 公众号ID&#xff5c;ComputerVisionGzq 学习群&#xff5c;扫码在主页获取加入方式 计算机视觉研究院专栏 作者&#xff1a;Edison_G 生成模型领域里&#xff0c;ChatGPT 并不是一切。 转自《机器之心》 过去两年&#xff0c;AI 领域里…

chatgpt赋能python:Python最简单的小游戏:猜数

Python 最简单的小游戏&#xff1a;猜数 作为一门高效、简单而且易于学习的编程语言&#xff0c;Python 受到了越来越多的开发者的喜爱。其中&#xff0c;编写小游戏是Python语言学习中一个很有趣的领域&#xff0c;因为它可以帮助你通过实践加深对Python语法和概念的理解。在…

chatgpt赋能Python-python3小游戏

Python3小游戏&#xff1a;为你的休闲时光增添乐趣 如果你正处于寻找一款简单好玩的小游戏&#xff0c;那么Python3小游戏将是你的不二之选。作为一名有10年Python编程经验的工程师&#xff0c;我可以说Python3小游戏是一款非常有趣、挑战性适中、易于上手的游戏。接下来&…

Github推荐--PC版微信/QQ/TIM防撤回补丁(我已经看到了,撤回也没用了)

逛Github的时候会遇到一些很好玩的项目 今天分享一个可以在PC端实现QQ防撤回功能的项目。&#xff08;安卓手机有Xposed框架&#xff09; 首先是项目地址&#xff1a; 我已经看到了&#xff0c;撤回也没用了 使用方法&#xff1a; 下载后解压&#xff0c;会出现RevokeMsgPatche…

微信防撤回功能修改

今天无意之中看到了一个帖子&#xff0c;谈到了有关微信消息撤回的。突发奇想实现一下&#xff0c;以后就不怕错过朋友的消息了。 首先介绍一下基本思路&#xff0c;由于微信采用的是CS端原理&#xff0c;所有的数据请求均通过服务器&#xff0c;客户端只是响应指令而已。 A向…

Git 如何撤回已经push到远端上的代码

首先 git log&#xff0c;目的是找到这次想要撤回的提交的上一次提交&#xff0c;并记录下红框中的commit id 回退代码&#xff0c;输入 git reset --soft commit id 回退代码, 回退完成后代码相当于刚写完的状态&#xff0c;即还没有进行add、commit、push…

微信多开防撤回工具再也不用担心好友撤回消息和登录多个账号了

微信&#xff0c;大家工作中生活中用的最多的一款应用&#xff1b;很多公司喜欢用微信来作为工作沟通的工具&#xff0c;官方原版只支持登陆一个微信&#xff0c;这对于需要在电脑上登陆多个微信账号的朋友来说肯定是极其的不方便。另外有的时候别人撤回了一些重要消息&#xf…

Python神级操作,还原已撤回的微信消息

项目环境 语言&#xff1a;Python3 编辑器&#xff1a;Pycharm 导包效果展示 以下截图显示的撤回消息类型依次是文字消息、微信自带表情、图片、语音、定位地图、名片、公众号文章、音乐、视频。有群里撤回的&#xff0c;也有个人号撤回的。 图文来源&#xff1a;http://kk…

利用Python查看微信好友撤回的消息

效果图如下&#xff1a; 不仅可以查看微信好友撤回的文字消息&#xff0c;如位置、视频、音频、图片等等都可以查看。 直接上源代码&#xff1a; # Python查看微信撤回消息 import re import os import time import itchat import platform from itchat.content import TEXT …

用Python实现微信撤回消息还原

在使用微信过程中&#xff0c;有时候我们会撤回一些发错或者不该发的一些信息&#xff0c;今天我就用一段代码实现将撤回的消息还原。。。 从此再也不怕别人撤回消息&#xff0c;自己不能看的尴尬了 import osimport reimport shutilimport timeimport itchatfrom itchat.con…

python学习 -对象把微信消息撤回后好慌,有了这个你就能看到撤回的消息了(超详解)

目录​​​​​​​ 一.简介 普通人 python技术人员 1、准备环境 2、itchat介绍 3、itchat使用 4、pycharm解释器写入代码 一.简介 当我们与朋友&#xff0c;亲人&#xff0c;爱人聊天的时候&#xff0c;我估计每个人都经理过&#xff0c;那就是微信撤回功能中所提到的…

微信能自定义“撤回消息”? QQ 笑了!

大家有没有遇到过和小伙伴聊天&#xff0c;结果输入法突然崛起&#xff0c;等到你撤回的时候尴尬到不行的窘境&#xff1f; 没办法&#xff0c;只好撤回...&#xff08;咳咳&#xff0c;只能说我的输入法已经妖魔化了 但是小伙伴的&#xff1f;号已经紧随其后&#xff0c;要是…

Telegram防撤回工具(Windows)

使用方法 Telegram v2.8.5 及之后版本 使用最新版本补丁将 TAR-Resources文件夹 、TAR-Launcher-x64.exe 、TAR-Launcher-x86.exe 全部解压到Telegram根目录 通过 TAR-Launcher-x64.exe 或 TAR-Launcher-x86.exe&#xff08;取决于你安装的Telegram版本&#xff0c;如果不知道…

用python实现监听微信撤回消息

import itchat from itchat.content import * import os import time import xml.dom.minidom temp d:/itchat / 撤回的消息 if not os.path.exists(temp):os.mkdir(temp)itchat.auto_login(True) dict {} itchat.msg_register([TEXT, PICTURE, FRIENDS, CARD, MAP, …