钉钉服务端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种文件转换的方法.发起源文件/模型转换后,转换过程可能成功 ...
随机推荐
- Python +appium 封装desired_caps模块
使用python+appium做android的自动化测试时,首先需要启动appium服务,然后连接上手机,配置如下: desired_caps = {"platformName" ...
- admin端的教师管理功能测试
1 概述 1.1 测试范围 本次所测试的内容是admin端的教师管理功能. 1.2 测试方法 采用黑盒子方法进行集成测试. 1.3 测试环境 (1) 服务器l 操作系统:Windo ...
- jquery 表单对象属性筛选选择器
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-type" content ...
- UVA-439, Knight Moves(深度优先搜索)
#include<iostream> #include<queue> #include<cstring> #include<string> #inclu ...
- 日常SQL总结
THEN '理财帐户' ELSE '其他' end case后可以加入条件在写when,length(String) 为string的字符长度 length(),括号里不仅可以是string的字符串, ...
- java构建简单的HTTP服务器
使用Java技术构建Web应用时, 我们通常离不开tomcat和jetty之类的servlet容器,这些Web服务器功能强大,性能强劲,深受欢迎,是运行大型Web应用的必备神器. 虽然Java的设计初 ...
- if语句的嵌套:从键盘输入3个实数,利用条件表达式求其最大者。
#include<stdio.h>void main(){ float a,b,c,max; scanf("%f%f%f",&a,&b,&c); ...
- L3956棋盘
1,记得之前要复习.上次先写的题是数的划分. 虽然我不想说,估计全忘了.复习就当把上次的题写了把. 应该比较稳了. 2,题中的要求. 一,所在的位置必须是有颜色的.(很明显要用bool去涂一遍) 二, ...
- 对生成对抗网络GANs原理、实现过程、应用场景的理解(附代码),另附:深度学习大神文章列表
https://blog.csdn.net/love666666shen/article/details/75522489 https://blog.csdn.net/yangdelong/artic ...
- jar包更新
打包新的jar包 java -jar xx.jar 本地测试后 删除旧的jar包 然后要重启jar包