钉钉服务端api接口使用
第一步:注册钉钉企业账号
打开链接:https://oa.dingtalk.com/#/login,注册账号即可
第二步:创建应用
以创建e应用为例:

还需要授权一个开发人员,并获取CorpSecret,需要把corpId和CorpSecret作为参数请求api接口获取AccessToken,后面的所有接口都需要AccessToken

第三步:接入接口
一、获取token
1 const corpid = 'dingd***587da6ee21d35c2f4657eb63***';
2 const corpsecret = '*********';
3 const requestPromise = require("request-promise");
4
5 const getAccessToken = async (corpid, corpsecret) => {
6 // https://oapi.dingtalk.com/gettoken?corpid={corpid}&corpsecret={corpSecret或开发授权码}
7 const result = await requestPromise({ uri: 'https://oapi.dingtalk.com/gettoken', qs: { corpid, corpsecret } });
8 console.log(result);
9 };
10 getAccessToken(corpid, corpsecret);
二、promise请求接口封装
- function request(url, method, params, headers = {}) {
- const options = {
- url,
- method,
- // timeout: 3000,
- headers: Object.assign(headers, {
- 'content-type': 'application/json',
- }),
- rejectUnauthorized: false, // https
- json: true,
- };
- switch (method) {
- case 'POST':
- case 'PUT':
- options.body = params;
- break;
- case 'GET':
- case 'DELETE':
- options.qs = params;
- break;
- default:
- break;
- }
- return new Promise((resolve, reject) => {
- request(options, (error, response, body) => {
- if (!error) {
- resolve(body);
- } else {
- reject(error);
- }
- });
- });
- .catch (error => ({
- msg: error.message,
- }));
- }
三、接口见代码(后端使用koa.js)
const host = 'https://oapi.dingtalk.com/';
- /*
- *发送工作通知消息
- */
- router.post('/api/dingtalkserve/asyncsend_v2', async ({ request, response, session }) => {
- try {
- let body = request.fields;
- if (!body['userid_list'] && !body['dept_id_list'] && !body['to_all_user']) {
- return response.fail({
- 'msg': "userid_list,dept_id_list, to_all_user必须有一个不能为空"
- });
- }
- if (!body['msg']) {
- return response.fail({
- 'msg': "msg不能为空"
- });
- }
- // 获取TOKEN
- let accessToken = await getAccessToken();
- let params = {
- agent_id: parseInt(agentId4EP),
- msg: {
- "msgtype": "text",
- "text": {
- "content": body['msg']
- }
- }
- };
- body['to_all_user'] ? params['to_all_user'] = true : false;
- body['dept_id_list'] ? params['dept_id_list'] = body['dept_id_list'] : "";
- body['userid_list'] ? params['userid_list'] = body['userid_list'] : "";
- let messageRes = await request(`${host}topapi/message/corpconversation/asyncsend_v2?access_token=${accessToken}`, 'POST', params);
- return response.success({ 'data': messageRes });
- } catch (e) {
- console.log(e);
- return response.fail({
- 'msg': e
- });
- }
- });
- /*
- * 获取工作通知消息的发送进度
- */
- router.post('/api/dingtalkserve/getsendprogress', async ({ request, response, session }) => {
- try {
- let body = request.fields;
- if (!body['task_id']) {
- return response.fail({
- 'msg': "task_id不能为空"
- });
- }
- // 获取TOKEN
- let accessToken = await getAccessToken();
- let params = {
- agent_id: parseInt(agentId4EP),
- task_id: body['task_id']
- };
- let messageRes = await request(`${host}topapi/message/corpconversation/getsendprogress?access_token=${accessToken}`, 'POST', params);
- return response.success({ 'data': messageRes });
- } catch (e) {
- console.log(e);
- return response.fail({
- 'msg': e
- });
- }
- });
- /*
- * 获取工作通知消息的发送结果
- */
- router.post('/api/dingtalkserve/getsendresult', async ({ request, response, session }) => {
- try {
- let body = request.fields;
- if (!body['task_id']) {
- return response.fail({
- 'msg': "task_id不能为空"
- });
- }
- // 获取TOKEN
- let accessToken = await getAccessToken();
- let params = {
- agent_id: parseInt(agentId4EP),
- task_id: body['task_id']
- };
- let messageRes = await request(`${host}topapi/message/corpconversation/getsendresult?access_token=${accessToken}`, 'POST', params);
- return response.success({ 'data': messageRes });
- } catch (e) {
- console.log(e);
- return response.fail({
- 'msg': e
- });
- }
- });
- /*
- * 获取子部门ID列表
- */
- router.post('/api/dingtalkserve/list_ids', async ({ request, response, session }) => {
- try {
- let body = request.fields;
- if (!body['id']) {
- return response.fail({
- 'msg': "父部门id不能为空"
- });
- }
- // 获取TOKEN
- let accessToken = await getAccessToken();
- let params = {
- access_token: accessToken,
- id: body['id']
- };
- let messageRes = await request(`${host}department/list_ids`, 'GET', params);
- console.log("messageRes", messageRes)
- return response.success({ 'data': messageRes });
- } catch (e) {
- console.log(e);
- return response.fail({
- 'msg': e
- });
- }
- });
- /*
- * 获取部门列表
- */
- router.post('/api/dingtalkserve/list', async ({ request, response, session }) => {
- try {
- let body = request.fields;
- if (!body['id']) {
- return response.fail({
- 'msg': "父部门id不能为空"
- });
- }
- // 获取TOKEN
- let accessToken = await getAccessToken();
- let params = {
- access_token: accessToken,
- id: body['id']
- };
- body['lang'] ? params['lang'] = body['lang'] : "";
- body['fetch_child'] ? params['fetch_child'] = true : false;
- let messageRes = await request(`${host}department/list`, 'GET', params);
- console.log("messageRes", messageRes)
- return response.success({ 'data': messageRes });
- } catch (e) {
- console.log(e);
- return response.fail({
- 'msg': e
- });
- }
- });
- /*
- * 获取部门详情
- */
- router.post('/api/dingtalkserve/departmentget', async ({ request, response, session }) => {
- try {
- let body = request.fields;
- if (!body['id']) {
- return response.fail({
- 'msg': "部门id不能为空"
- });
- }
- // 获取TOKEN
- let accessToken = await getAccessToken();
- let params = {
- access_token: accessToken,
- id: body['id']
- };
- body['lang'] ? params['lang'] = body['lang'] : "";
- let messageRes = await request(`${host}department/get`, 'GET', params);
- console.log("messageRes", messageRes)
- return response.success({ 'data': messageRes });
- } catch (e) {
- console.log(e);
- return response.fail({
- 'msg': e
- });
- }
- });
- /*
- * 查询部门的所有上级父部门路径
- */
- router.post('/api/dingtalkserve/list_parent_depts_by_dept', async ({ request, response, session }) => {
- try {
- let body = request.fields;
- if (!body['id']) {
- return response.fail({
- 'msg': "部门id不能为空"
- });
- }
- // 获取TOKEN
- let accessToken = await getAccessToken();
- let params = {
- access_token: accessToken,
- id: body['id']
- };
- let messageRes = await request(`${host}department/list_parent_depts_by_dept`, 'GET', params);
- console.log("messageRes", messageRes)
- return response.success({ 'data': messageRes });
- } catch (e) {
- console.log(e);
- return response.fail({
- 'msg': e
- });
- }
- });
- /*
- * 查询指定用户的所有上级父部门路径
- */
- router.post('/api/dingtalkserve/list_parent_depts', async ({ request, response, session }) => {
- try {
- let body = request.fields;
- if (!body['userId']) {
- return response.fail({
- 'msg': "用户id不能为空"
- });
- }
- // 获取TOKEN
- let accessToken = await getAccessToken();
- let params = {
- access_token: accessToken,
- userId: body['userId']
- };
- let messageRes = await request(`${host}department/list_parent_depts`, 'GET', params);
- console.log("messageRes", messageRes)
- return response.success({ 'data': messageRes });
- } catch (e) {
- console.log(e);
- return response.fail({
- 'msg': e
- });
- }
- });
- /*
- * 获取企业员工人数
- */
- router.post('/api/dingtalkserve/get_org_user_count', async ({ request, response, session }) => {
- try {
- let body = request.fields;
- if (!body['onlyActive']) {
- return response.fail({
- 'msg': "激活钉钉状态不能为空"
- });
- }
- // 获取TOKEN
- let accessToken = await getAccessToken();
- let params = {
- access_token: accessToken,
- onlyActive: body['onlyActive']
- };
- let messageRes = await request(`${host}user/get_org_user_count`, 'GET', params);
- console.log("messageRes", messageRes)
- return response.success({ 'data': messageRes });
- } catch (e) {
- console.log(e);
- return response.fail({
- 'msg': e
- });
- }
- });
- /*
- * 获取用户详情
- */
- router.post('/api/dingtalkserve/userinfo', async ({ request, response, session }) => {
- try {
- let body = request.fields;
- if (!body['userid']) {
- return response.fail({
- 'msg': "userid不能为空"
- });
- }
- // 获取TOKEN
- let accessToken = await getAccessToken();
- let params = {
- access_token: accessToken,
- userid: body['userid']
- };
- body['lang'] ? params['lang'] = body['lang'] : "";
- let messageRes = await request(`${host}user/get`, 'GET', params);
- console.log("messageRes", messageRes)
- return response.success({ 'data': messageRes });
- } catch (e) {
- console.log(e);
- return response.fail({
- 'msg': e
- });
- }
- });
- /*
- * 获取部门用户userid列表
- */
- router.post('/api/dingtalkserve/getDeptMember', async ({ request, response, session }) => {
- try {
- let body = request.fields;
- if (!body['deptId']) {
- return response.fail({
- 'msg': "部门id不能为空"
- });
- }
- // 获取TOKEN
- let accessToken = await getAccessToken();
- let params = {
- access_token: accessToken,
- deptId: body['deptId']
- };
- let messageRes = await request(`${host}user/getDeptMember`, 'GET', params);
- console.log("messageRes", messageRes)
- return response.success({ 'data': messageRes });
- } catch (e) {
- console.log(e);
- return response.fail({
- 'msg': e
- });
- }
- });
- /*
- * 获取部门用户(详情)
- */
- router.post('/api/dingtalkserve/listbypage', async ({ request, response, session }) => {
- try {
- let body = request.fields;
- if (!body['department_id']) {
- return response.fail({
- 'msg': "部门id不能为空"
- });
- }
- if (!body['offset']) {
- return response.fail({
- 'msg': "偏移量不能为空"
- });
- }
- if (!body['size']) {
- return response.fail({
- 'msg': "每页数量不能为空"
- });
- }
- // 获取TOKEN
- let accessToken = await getAccessToken();
- let params = {
- access_token: accessToken,
- department_id: body['department_id'],
- offset: parseInt(body['offset']),
- size: parseInt(body['size'])
- };
- let messageRes = await request(`${host}user/listbypage`, 'GET', params);
- console.log("messageRes", messageRes)
- return response.success({ 'data': messageRes });
- } catch (e) {
- console.log(e);
- return response.fail({
- 'msg': e
- });
- }
- });
- /*
- * 根据unionid获取userid
- */
- router.post('/api/dingtalkserve/getUseridByUnionid', async ({ request, response, session }) => {
- try {
- let body = request.fields;
- if (!body['unionid']) {
- return response.fail({
- 'msg': "unionid不能为空"
- });
- }
- // 获取TOKEN
- let accessToken = await getAccessToken();
- let params = {
- access_token: accessToken,
- unionid: body['unionid']
- };
- let messageRes = await request(`${host}user/getUseridByUnionid`, 'GET', params);
- console.log("messageRes", messageRes)
- return response.success({ 'data': messageRes });
- } catch (e) {
- console.log(e);
- return response.fail({
- 'msg': e
- });
- }
- });
- /*
- * 获取通讯录权限范围
- */
- router.post('/api/dingtalkserve/authScopes', async ({ request, response, session }) => {
- try {
- // 获取TOKEN
- let accessToken = await getAccessToken();
- let params = {
- access_token: accessToken
- };
- let messageRes = await request(`${host}/auth/scopes`, 'GET', params);
- console.log("messageRes", messageRes)
- return response.success({ 'data': messageRes });
- } catch (e) {
- console.log(e);
- return response.fail({
- 'msg': e
- });
- }
- });
- /*
- * 创建群
- */
- router.post('/api/dingtalkserve/createChat', async ({ request, response, session }) => {
- try {
- let body = request.fields;
- if (!body['name']) {
- return response.fail({
- 'msg': "群名称不能为空"
- });
- }
- if (!body['owner']) {
- return response.fail({
- 'msg': "群主userid不能为空"
- });
- }
- if (!body['useridlist']) {
- return response.fail({
- 'msg': "群成员不能为空"
- });
- }
- if (body['useridlist'].indexOf(body['owner']) < 0) {
- return response.fail({
- 'msg': "群主必须为群成员"
- });
- }
- // 获取TOKEN
- let accessToken = await getAccessToken();
- let params = {
- name: body['name'],
- owner: body['owner'],
- useridlist: body['useridlist'].split(",")
- };
- let messageRes = await request(`${host}chat/create?access_token=${accessToken}`, 'POST', params);
- console.log("messageRes", messageRes)
- return response.success({ 'data': messageRes });
- } catch (e) {
- console.log(e);
- return response.fail({
- 'msg': e
- });
- }
- });
- /*
- * 获取群聊会话信息
- */
- router.post('/api/dingtalkserve/chatInfo', async ({ request, response, session }) => {
- try {
- let body = request.fields;
- if (!body['chatid']) {
- return response.fail({
- 'msg': "群id不能为空"
- });
- }
- // 获取TOKEN
- let accessToken = await getAccessToken();
- let params = {
- access_token: accessToken,
- chatid: body['chatid']
- };
- let messageRes = await request(`${host}chat/get`, 'GET', params);
- console.log("messageRes", messageRes)
- return response.success({ 'data': messageRes });
- } catch (e) {
- console.log(e);
- return response.fail({
- 'msg': e
- });
- }
- });
- /*
- * 发送群消息
- */
- router.post('/api/dingtalkserve/chatSend', async ({ request, response, session }) => {
- try {
- let body = request.fields;
- if (!body['chatid']) {
- return response.fail({
- 'msg': "群id不能为空"
- });
- }
- if (!body['msg']) {
- return response.fail({
- 'msg': "群消息不能为空"
- });
- }
- // 获取TOKEN
- let accessToken = await getAccessToken();
- let params = {
- chatid: body['chatid'],
- msg: {
- "msgtype": "text",
- "text": {
- "content": body['msg']
- }
- }
- };
- let messageRes = await request(`${host}chat/send?access_token=${accessToken}`, 'POST', params);
- console.log("messageRes", messageRes)
- return response.success({ 'data': messageRes });
- } catch (e) {
- console.log(e);
- return response.fail({
- 'msg': e
- });
- }
- });
- /*
- * 查询群消息已读人员列表
- */
- router.post('/api/dingtalkserve/getReadList', async ({ request, response, session }) => {
- try {
- let body = request.fields;
- if (!body['messageId']) {
- return response.fail({
- 'msg': "messageId不能为空"
- });
- }
- if (!body['cursor']) {
- return response.fail({
- 'msg': "cursor不能为空"
- });
- }
- if (!body['size']) {
- return response.fail({
- 'msg': "每页数量不能为空"
- });
- }
- // 获取TOKEN
- let accessToken = await getAccessToken();
- let params = {
- access_token: accessToken,
- messageId: body['messageId'],
- cursor: body['cursor'],
- size: parseInt(body['size']),
- };
- let messageRes = await request(`${host}chat/getReadList`, 'GET', params);
- console.log("messageRes", messageRes)
- return response.success({ 'data': messageRes });
- } catch (e) {
- console.log(e);
- return response.fail({
- 'msg': e
- });
- }
- });
以上针对的是钉钉企业内部应用
如果是ISV开发者应用,则需要通过接口获取企业的基本信息
nodejs签名实现
- /*
- * 把timestamp + "\n" + suiteTicket当做签名字符串, suiteSecret做为签名秘钥,
- * 使用HmacSHA256算法计算签名, 然后进行Base64 encode获取最后结果。
- * 然后把签名参数再进行urlconde, 加到请求url后面。
- */
- const crypto = require('crypto');
- const accessKey = 'suiteqh0ljtdheuee****'; // suiteKey
- const suiteSecret = '******';
- const suiteTicket = 'TestSuiteTicket';
- const timestamp = Date.now();
- const stringToSign = timestamp + "\n" + suiteTicket;
- const hash = crypto.createHmac('sha256', suiteSecret)
- .update(stringToSign, 'utf8')
- .digest().toString('base64');
- console.log(hash);
- var request = require("request");
- var urlencode = require('urlencode');
- var options = {
- method: 'POST',
- url: 'https://oapi.dingtalk.com/service/get_auth_info',
- qs: {
- signature: hash,
- timestamp: timestamp,
- suiteTicket: suiteTicket,
- accessKey: accessKey
- },
- headers: {
- 'Cache-Control': 'no-cache',
- 'Content-Type': 'application/json'
- },
- body: { auth_corpid: 'dingd142a587da6ee21d35c2f4657eb6378f' },
- json: true
- };
- request(options, function (error, response, body) {
- if (error) throw new Error(error);
- console.log(body);
- });
钉钉文档开发者链接 :https://open-doc.dingtalk.com/microapp/serverapi2/isu6nk
转载于:https://www.cnblogs.com/xiaosongJiang/p/9991573.html
钉钉服务端api接口使用的更多相关文章
- 服务端调用接口API利器之HttpClient
前言 之前有介绍过HttpClient作为爬虫的简单使用,那么今天在简单的介绍一下它的另一个用途:在服务端调用接口API进行交互.之所以整理这个呢,是因为前几天在测试云之家待办消息接口的时候,有使用云 ...
- 安卓推送——个推服务端api使用误区
首先你需要在个推开放着平台上注册你的应用,以及获得以下几个必要的值APPID |APPKEY | MASTERSECRET,本文假设你已经完成上述步骤以及完成客户端SDK的集成. 原理 个推服务端ap ...
- C#开发BIMFACE系列4 服务端API之源上传文件
在注册成为BIMFACE的应用开发者后,要能在浏览器里浏览你的模型或者获取你模型内的BIM数据, 首先需要把你的模型文件上传到BIMFACE.根据不同场景,BIMFACE提供了丰富的文件相关的接口. ...
- C#开发BIMFACE系列3 服务端API之获取应用访问凭证AccessToken
系列目录 [已更新最新开发文章,点击查看详细] BIMFACE 平台为开发者提供了大量的服务器端 API 与 JavaScript API,用于二次开发 BIM 的相关应用. BIMFACE ...
- C#开发BIMFACE系列8 服务端API之获取文件上传状态信息
系列目录 [已更新最新开发文章,点击查看详细] 在BIMFACE控制台上传文件,上传过程及结束后它会自动告诉你文件的上传状态,目前有三种状态:uploading,success,failure ...
- C#开发BIMFACE系列10 服务端API之获取文件下载链接
系列目录 [已更新最新开发文章,点击查看详细] 通过BIMFACE控制台或者调用服务接口上传文件成功后,默认场景下需要下载该源文件,下载文件一般需要知道文件的下载链接即可.BIMACE平台提供 ...
- C#开发BIMFACE系列11 服务端API之源文件删除
系列目录 [已更新最新开发文章,点击查看详细] 通过BIMFACE控制台或者调用服务接口上传文件成功后,如果不再需要该文件,则可以通过BIMFACE平台提供的“源文件删除”服务接口删除具体的文 ...
- C#开发BIMFACE系列14 服务端API之批量获取转换状态详情
系列目录 [已更新最新开发文章,点击查看详细] 上一篇<C#开发BIMFACE系列13 服务端API之获取转换状态>中介绍了根据文件ID查询单个文件的转换状态. 本文介绍批量获取转 ...
- C#开发BIMFACE系列13 服务端API之获取转换状态
系列目录 [已更新最新开发文章,点击查看详细] 在<C#开发BIMFACE系列12 服务端API之文件转换>中详细介绍了7种文件转换的方法.发起源文件/模型转换后,转换过程可能成功 ...
随机推荐
- Spring Boot-初学01 -使用Spring Initializer快速创建Spring Boot项目 -@RestController+spEL -实现简单SpringBoot的Web页面
1.IDEA:使用 Spring Initializer快速创建项目 IDE都支持使用Spring的项目创建向导快速创建一个Spring Boot项目: 选择我们需要的模块:向导会联网创建Spring ...
- es6 字符串模板拼接和传统字符串拼接
字符串拼接是在日常开发中必不可少的一个环节. 注意:字符串可以用单引号'',或者""双引号,出于方便大家理解,文章以下内容统一使用单引号''! 如果只是一个字符串和一个变量拼接,使 ...
- 通俗理解word2vec的训练过程
https://www.leiphone.com/news/201706/eV8j3Nu8SMqGBnQB.html https://blog.csdn.net/dn_mug/article/deta ...
- HBase应用
太多column family的影响 每个 MemoryStore分配到的内存较少,进而导致过多的合并,影响性能 几个column family比较合适呢 推荐是:1-3个 划分column fa ...
- python - 对接微信支付(PC)和 注意点
注:本文仅提供 pc 端微信扫码支付(模式一)的示例代码. 关于对接过程中遇到的问题总结在本文最下方. 参考: 官方文档, https://blog.csdn.net/lm_is_dc/arti ...
- 详解如何在CentOS7中使用Nginx和PHP7-FPM安装Nextcloud
转载地址:https://www.jb51.net/article/109382.htm 这篇文章主要介绍了详解如何在CentOS7中使用Nginx和PHP7-FPM安装Nextcloud,会通过 N ...
- web 介绍
Web介绍: w3c:万维网联盟组织,用来制定web标准的机构(组织) web标准:制作网页遵循的规范 web准备规范的分类:结构标准.表现标准.行为标准. 结构:html.表示:css.行为:Jav ...
- 使用for循环签到嵌套制作直角三角形
注意代码的运行顺序: for(i = 0 ; i<9 ; i++){ for(j = 0 ; j<i-1 ; j++){ document.write("*")//** ...
- pgloader 学习(三)快速使用
pgloader 支持多种数据源数据的加载,以下列出简单的操作命令,后边会有详细的使用说明 csv 格式内容加载 预备说明 需要先在pg 数据库创建表 create table districts_l ...
- CF888G 【Xor-MST】
妙妙题-- 看到\(MST\),想到\(Kruskal\),看到异或,想到\(Trie\) 首先我们模拟一下\(Kruskal\)的流程:找到最小边,如果联通就忽略,未联通就加边 我们把所有点权值加入 ...