釘釘服務端api介面使用
阿新 • • 發佈:2018-11-20
第一步:註冊釘釘企業賬號
開啟連結: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