钉钉服务端api接口使用

第一步:注册钉钉企业账号

打开链接:https://oa.dingtalk.com/#/login,注册账号即可

第二步:创建应用

以创建e应用为例:

钉钉服务端api接口使用

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

钉钉服务端api接口使用

第三步:接入接口

一、获取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请求接口封装

  1.  
    function request(url, method, params, headers = {}) {
  2.  
    const options = {
  3.  
    url,
  4.  
    method,
  5.  
    // timeout: 3000,
  6.  
    headers: Object.assign(headers, {
  7.  
    'content-type': 'application/json',
  8.  
    }),
  9.  
    rejectUnauthorized: false, // https
  10.  
    json: true,
  11.  
    };
  12.  
    switch (method) {
  13.  
    case 'POST':
  14.  
    case 'PUT':
  15.  
    options.body = params;
  16.  
    break;
  17.  
    case 'GET':
  18.  
    case 'DELETE':
  19.  
    options.qs = params;
  20.  
    break;
  21.  
    default:
  22.  
    break;
  23.  
    }
  24.  
    return new Promise((resolve, reject) => {
  25.  
    request(options, (error, response, body) => {
  26.  
    if (!error) {
  27.  
    resolve(body);
  28.  
    } else {
  29.  
    reject(error);
  30.  
    }
  31.  
    });
  32.  
    });
  33.  
    .catch (error => ({
  34.  
     
  35.  
    msg: error.message,
  36.  
    }));
  37.  
    }

  

三、接口见代码(后端使用koa.js)

const host = 'https://oapi.dingtalk.com/';
  1.  
    /*
  2.  
    *发送工作通知消息
  3.  
    */
  4.  
    router.post('/api/dingtalkserve/asyncsend_v2', async ({ request, response, session }) => {
  5.  
    try {
  6.  
     
  7.  
    let body = request.fields;
  8.  
    if (!body['userid_list'] && !body['dept_id_list'] && !body['to_all_user']) {
  9.  
    return response.fail({
  10.  
    'msg': "userid_list,dept_id_list, to_all_user必须有一个不能为空"
  11.  
    });
  12.  
    }
  13.  
    if (!body['msg']) {
  14.  
    return response.fail({
  15.  
    'msg': "msg不能为空"
  16.  
    });
  17.  
    }
  18.  
     
  19.  
    // 获取TOKEN
  20.  
    let accessToken = await getAccessToken();
  21.  
    let params = {
  22.  
    agent_id: parseInt(agentId4EP),
  23.  
    msg: {
  24.  
    "msgtype": "text",
  25.  
    "text": {
  26.  
    "content": body['msg']
  27.  
    }
  28.  
    }
  29.  
    };
  30.  
    body['to_all_user'] ? params['to_all_user'] = true : false;
  31.  
    body['dept_id_list'] ? params['dept_id_list'] = body['dept_id_list'] : "";
  32.  
    body['userid_list'] ? params['userid_list'] = body['userid_list'] : "";
  33.  
    let messageRes = await request(`${host}topapi/message/corpconversation/asyncsend_v2?access_token=${accessToken}`, 'POST', params);
  34.  
    return response.success({ 'data': messageRes });
  35.  
    } catch (e) {
  36.  
    console.log(e);
  37.  
    return response.fail({
  38.  
    'msg': e
  39.  
    });
  40.  
    }
  41.  
    });
  42.  
     
  43.  
    /*
  44.  
    * 获取工作通知消息的发送进度
  45.  
    */
  46.  
    router.post('/api/dingtalkserve/getsendprogress', async ({ request, response, session }) => {
  47.  
    try {
  48.  
     
  49.  
    let body = request.fields;
  50.  
    if (!body['task_id']) {
  51.  
    return response.fail({
  52.  
    'msg': "task_id不能为空"
  53.  
    });
  54.  
    }
  55.  
    // 获取TOKEN
  56.  
    let accessToken = await getAccessToken();
  57.  
    let params = {
  58.  
    agent_id: parseInt(agentId4EP),
  59.  
    task_id: body['task_id']
  60.  
    };
  61.  
    let messageRes = await request(`${host}topapi/message/corpconversation/getsendprogress?access_token=${accessToken}`, 'POST', params);
  62.  
    return response.success({ 'data': messageRes });
  63.  
    } catch (e) {
  64.  
    console.log(e);
  65.  
    return response.fail({
  66.  
    'msg': e
  67.  
    });
  68.  
    }
  69.  
    });
  70.  
     
  71.  
    /*
  72.  
    * 获取工作通知消息的发送结果
  73.  
    */
  74.  
    router.post('/api/dingtalkserve/getsendresult', async ({ request, response, session }) => {
  75.  
    try {
  76.  
     
  77.  
    let body = request.fields;
  78.  
    if (!body['task_id']) {
  79.  
    return response.fail({
  80.  
    'msg': "task_id不能为空"
  81.  
    });
  82.  
    }
  83.  
    // 获取TOKEN
  84.  
    let accessToken = await getAccessToken();
  85.  
    let params = {
  86.  
    agent_id: parseInt(agentId4EP),
  87.  
    task_id: body['task_id']
  88.  
    };
  89.  
    let messageRes = await request(`${host}topapi/message/corpconversation/getsendresult?access_token=${accessToken}`, 'POST', params);
  90.  
    return response.success({ 'data': messageRes });
  91.  
    } catch (e) {
  92.  
    console.log(e);
  93.  
    return response.fail({
  94.  
    'msg': e
  95.  
    });
  96.  
    }
  97.  
    });
  98.  
     
  99.  
    /*
  100.  
    * 获取子部门ID列表
  101.  
    */
  102.  
    router.post('/api/dingtalkserve/list_ids', async ({ request, response, session }) => {
  103.  
    try {
  104.  
     
  105.  
    let body = request.fields;
  106.  
    if (!body['id']) {
  107.  
    return response.fail({
  108.  
    'msg': "父部门id不能为空"
  109.  
    });
  110.  
    }
  111.  
    // 获取TOKEN
  112.  
    let accessToken = await getAccessToken();
  113.  
    let params = {
  114.  
    access_token: accessToken,
  115.  
    id: body['id']
  116.  
    };
  117.  
    let messageRes = await request(`${host}department/list_ids`, 'GET', params);
  118.  
    console.log("messageRes", messageRes)
  119.  
    return response.success({ 'data': messageRes });
  120.  
    } catch (e) {
  121.  
    console.log(e);
  122.  
    return response.fail({
  123.  
    'msg': e
  124.  
    });
  125.  
    }
  126.  
    });
  127.  
     
  128.  
    /*
  129.  
    * 获取部门列表
  130.  
    */
  131.  
    router.post('/api/dingtalkserve/list', async ({ request, response, session }) => {
  132.  
    try {
  133.  
     
  134.  
    let body = request.fields;
  135.  
    if (!body['id']) {
  136.  
    return response.fail({
  137.  
    'msg': "父部门id不能为空"
  138.  
    });
  139.  
    }
  140.  
    // 获取TOKEN
  141.  
    let accessToken = await getAccessToken();
  142.  
    let params = {
  143.  
    access_token: accessToken,
  144.  
    id: body['id']
  145.  
    };
  146.  
    body['lang'] ? params['lang'] = body['lang'] : "";
  147.  
    body['fetch_child'] ? params['fetch_child'] = true : false;
  148.  
    let messageRes = await request(`${host}department/list`, 'GET', params);
  149.  
    console.log("messageRes", messageRes)
  150.  
    return response.success({ 'data': messageRes });
  151.  
    } catch (e) {
  152.  
    console.log(e);
  153.  
    return response.fail({
  154.  
    'msg': e
  155.  
    });
  156.  
    }
  157.  
    });
  158.  
     
  159.  
    /*
  160.  
    * 获取部门详情
  161.  
    */
  162.  
    router.post('/api/dingtalkserve/departmentget', async ({ request, response, session }) => {
  163.  
    try {
  164.  
     
  165.  
    let body = request.fields;
  166.  
    if (!body['id']) {
  167.  
    return response.fail({
  168.  
    'msg': "部门id不能为空"
  169.  
    });
  170.  
    }
  171.  
    // 获取TOKEN
  172.  
    let accessToken = await getAccessToken();
  173.  
    let params = {
  174.  
    access_token: accessToken,
  175.  
    id: body['id']
  176.  
    };
  177.  
    body['lang'] ? params['lang'] = body['lang'] : "";
  178.  
    let messageRes = await request(`${host}department/get`, 'GET', params);
  179.  
    console.log("messageRes", messageRes)
  180.  
    return response.success({ 'data': messageRes });
  181.  
    } catch (e) {
  182.  
    console.log(e);
  183.  
    return response.fail({
  184.  
    'msg': e
  185.  
    });
  186.  
    }
  187.  
    });
  188.  
     
  189.  
    /*
  190.  
    * 查询部门的所有上级父部门路径
  191.  
    */
  192.  
    router.post('/api/dingtalkserve/list_parent_depts_by_dept', async ({ request, response, session }) => {
  193.  
    try {
  194.  
     
  195.  
    let body = request.fields;
  196.  
    if (!body['id']) {
  197.  
    return response.fail({
  198.  
    'msg': "部门id不能为空"
  199.  
    });
  200.  
    }
  201.  
    // 获取TOKEN
  202.  
    let accessToken = await getAccessToken();
  203.  
    let params = {
  204.  
    access_token: accessToken,
  205.  
    id: body['id']
  206.  
    };
  207.  
    let messageRes = await request(`${host}department/list_parent_depts_by_dept`, 'GET', params);
  208.  
    console.log("messageRes", messageRes)
  209.  
    return response.success({ 'data': messageRes });
  210.  
    } catch (e) {
  211.  
    console.log(e);
  212.  
    return response.fail({
  213.  
    'msg': e
  214.  
    });
  215.  
    }
  216.  
    });
  217.  
    /*
  218.  
    * 查询指定用户的所有上级父部门路径
  219.  
    */
  220.  
    router.post('/api/dingtalkserve/list_parent_depts', async ({ request, response, session }) => {
  221.  
    try {
  222.  
     
  223.  
    let body = request.fields;
  224.  
    if (!body['userId']) {
  225.  
    return response.fail({
  226.  
    'msg': "用户id不能为空"
  227.  
    });
  228.  
    }
  229.  
    // 获取TOKEN
  230.  
    let accessToken = await getAccessToken();
  231.  
    let params = {
  232.  
    access_token: accessToken,
  233.  
    userId: body['userId']
  234.  
    };
  235.  
    let messageRes = await request(`${host}department/list_parent_depts`, 'GET', params);
  236.  
    console.log("messageRes", messageRes)
  237.  
    return response.success({ 'data': messageRes });
  238.  
    } catch (e) {
  239.  
    console.log(e);
  240.  
    return response.fail({
  241.  
    'msg': e
  242.  
    });
  243.  
    }
  244.  
    });
  245.  
     
  246.  
    /*
  247.  
    * 获取企业员工人数
  248.  
    */
  249.  
    router.post('/api/dingtalkserve/get_org_user_count', async ({ request, response, session }) => {
  250.  
    try {
  251.  
     
  252.  
    let body = request.fields;
  253.  
    if (!body['onlyActive']) {
  254.  
    return response.fail({
  255.  
    'msg': "激活钉钉状态不能为空"
  256.  
    });
  257.  
    }
  258.  
    // 获取TOKEN
  259.  
    let accessToken = await getAccessToken();
  260.  
    let params = {
  261.  
    access_token: accessToken,
  262.  
    onlyActive: body['onlyActive']
  263.  
    };
  264.  
    let messageRes = await request(`${host}user/get_org_user_count`, 'GET', params);
  265.  
    console.log("messageRes", messageRes)
  266.  
    return response.success({ 'data': messageRes });
  267.  
    } catch (e) {
  268.  
    console.log(e);
  269.  
    return response.fail({
  270.  
    'msg': e
  271.  
    });
  272.  
    }
  273.  
    });
  274.  
     
  275.  
    /*
  276.  
    * 获取用户详情
  277.  
    */
  278.  
    router.post('/api/dingtalkserve/userinfo', async ({ request, response, session }) => {
  279.  
    try {
  280.  
     
  281.  
    let body = request.fields;
  282.  
    if (!body['userid']) {
  283.  
    return response.fail({
  284.  
    'msg': "userid不能为空"
  285.  
    });
  286.  
    }
  287.  
    // 获取TOKEN
  288.  
    let accessToken = await getAccessToken();
  289.  
    let params = {
  290.  
    access_token: accessToken,
  291.  
    userid: body['userid']
  292.  
    };
  293.  
    body['lang'] ? params['lang'] = body['lang'] : "";
  294.  
    let messageRes = await request(`${host}user/get`, 'GET', params);
  295.  
    console.log("messageRes", messageRes)
  296.  
    return response.success({ 'data': messageRes });
  297.  
    } catch (e) {
  298.  
    console.log(e);
  299.  
    return response.fail({
  300.  
    'msg': e
  301.  
    });
  302.  
    }
  303.  
    });
  304.  
     
  305.  
    /*
  306.  
    * 获取部门用户userid列表
  307.  
    */
  308.  
    router.post('/api/dingtalkserve/getDeptMember', async ({ request, response, session }) => {
  309.  
    try {
  310.  
    let body = request.fields;
  311.  
    if (!body['deptId']) {
  312.  
    return response.fail({
  313.  
    'msg': "部门id不能为空"
  314.  
    });
  315.  
    }
  316.  
    // 获取TOKEN
  317.  
    let accessToken = await getAccessToken();
  318.  
    let params = {
  319.  
    access_token: accessToken,
  320.  
    deptId: body['deptId']
  321.  
    };
  322.  
    let messageRes = await request(`${host}user/getDeptMember`, 'GET', params);
  323.  
    console.log("messageRes", messageRes)
  324.  
    return response.success({ 'data': messageRes });
  325.  
    } catch (e) {
  326.  
    console.log(e);
  327.  
    return response.fail({
  328.  
    'msg': e
  329.  
    });
  330.  
    }
  331.  
    });
  332.  
     
  333.  
    /*
  334.  
    * 获取部门用户(详情)
  335.  
    */
  336.  
    router.post('/api/dingtalkserve/listbypage', async ({ request, response, session }) => {
  337.  
    try {
  338.  
     
  339.  
    let body = request.fields;
  340.  
    if (!body['department_id']) {
  341.  
    return response.fail({
  342.  
    'msg': "部门id不能为空"
  343.  
    });
  344.  
    }
  345.  
    if (!body['offset']) {
  346.  
    return response.fail({
  347.  
    'msg': "偏移量不能为空"
  348.  
    });
  349.  
    }
  350.  
    if (!body['size']) {
  351.  
    return response.fail({
  352.  
    'msg': "每页数量不能为空"
  353.  
    });
  354.  
    }
  355.  
    // 获取TOKEN
  356.  
    let accessToken = await getAccessToken();
  357.  
    let params = {
  358.  
    access_token: accessToken,
  359.  
    department_id: body['department_id'],
  360.  
    offset: parseInt(body['offset']),
  361.  
    size: parseInt(body['size'])
  362.  
    };
  363.  
    let messageRes = await request(`${host}user/listbypage`, 'GET', params);
  364.  
    console.log("messageRes", messageRes)
  365.  
    return response.success({ 'data': messageRes });
  366.  
    } catch (e) {
  367.  
    console.log(e);
  368.  
    return response.fail({
  369.  
    'msg': e
  370.  
    });
  371.  
    }
  372.  
    });
  373.  
     
  374.  
    /*
  375.  
    * 根据unionid获取userid
  376.  
    */
  377.  
    router.post('/api/dingtalkserve/getUseridByUnionid', async ({ request, response, session }) => {
  378.  
    try {
  379.  
     
  380.  
    let body = request.fields;
  381.  
    if (!body['unionid']) {
  382.  
    return response.fail({
  383.  
    'msg': "unionid不能为空"
  384.  
    });
  385.  
    }
  386.  
    // 获取TOKEN
  387.  
    let accessToken = await getAccessToken();
  388.  
    let params = {
  389.  
    access_token: accessToken,
  390.  
    unionid: body['unionid']
  391.  
    };
  392.  
    let messageRes = await request(`${host}user/getUseridByUnionid`, 'GET', params);
  393.  
    console.log("messageRes", messageRes)
  394.  
    return response.success({ 'data': messageRes });
  395.  
    } catch (e) {
  396.  
    console.log(e);
  397.  
    return response.fail({
  398.  
    'msg': e
  399.  
    });
  400.  
    }
  401.  
    });
  402.  
     
  403.  
    /*
  404.  
    * 获取通讯录权限范围
  405.  
    */
  406.  
    router.post('/api/dingtalkserve/authScopes', async ({ request, response, session }) => {
  407.  
    try {
  408.  
    // 获取TOKEN
  409.  
    let accessToken = await getAccessToken();
  410.  
    let params = {
  411.  
    access_token: accessToken
  412.  
    };
  413.  
    let messageRes = await request(`${host}/auth/scopes`, 'GET', params);
  414.  
    console.log("messageRes", messageRes)
  415.  
    return response.success({ 'data': messageRes });
  416.  
    } catch (e) {
  417.  
    console.log(e);
  418.  
    return response.fail({
  419.  
    'msg': e
  420.  
    });
  421.  
    }
  422.  
    });
  423.  
     
  424.  
    /*
  425.  
    * 创建群
  426.  
    */
  427.  
    router.post('/api/dingtalkserve/createChat', async ({ request, response, session }) => {
  428.  
    try {
  429.  
     
  430.  
    let body = request.fields;
  431.  
    if (!body['name']) {
  432.  
    return response.fail({
  433.  
    'msg': "群名称不能为空"
  434.  
    });
  435.  
    }
  436.  
    if (!body['owner']) {
  437.  
    return response.fail({
  438.  
    'msg': "群主userid不能为空"
  439.  
    });
  440.  
    }
  441.  
    if (!body['useridlist']) {
  442.  
    return response.fail({
  443.  
    'msg': "群成员不能为空"
  444.  
    });
  445.  
    }
  446.  
    if (body['useridlist'].indexOf(body['owner']) < 0) {
  447.  
    return response.fail({
  448.  
    'msg': "群主必须为群成员"
  449.  
    });
  450.  
    }
  451.  
    // 获取TOKEN
  452.  
    let accessToken = await getAccessToken();
  453.  
    let params = {
  454.  
    name: body['name'],
  455.  
    owner: body['owner'],
  456.  
    useridlist: body['useridlist'].split(",")
  457.  
    };
  458.  
    let messageRes = await request(`${host}chat/create?access_token=${accessToken}`, 'POST', params);
  459.  
    console.log("messageRes", messageRes)
  460.  
    return response.success({ 'data': messageRes });
  461.  
    } catch (e) {
  462.  
    console.log(e);
  463.  
    return response.fail({
  464.  
    'msg': e
  465.  
    });
  466.  
    }
  467.  
    });
  468.  
     
  469.  
    /*
  470.  
    * 获取群聊会话信息
  471.  
    */
  472.  
    router.post('/api/dingtalkserve/chatInfo', async ({ request, response, session }) => {
  473.  
    try {
  474.  
     
  475.  
    let body = request.fields;
  476.  
    if (!body['chatid']) {
  477.  
    return response.fail({
  478.  
    'msg': "群id不能为空"
  479.  
    });
  480.  
    }
  481.  
    // 获取TOKEN
  482.  
    let accessToken = await getAccessToken();
  483.  
    let params = {
  484.  
    access_token: accessToken,
  485.  
    chatid: body['chatid']
  486.  
    };
  487.  
    let messageRes = await request(`${host}chat/get`, 'GET', params);
  488.  
    console.log("messageRes", messageRes)
  489.  
    return response.success({ 'data': messageRes });
  490.  
    } catch (e) {
  491.  
    console.log(e);
  492.  
    return response.fail({
  493.  
    'msg': e
  494.  
    });
  495.  
    }
  496.  
    });
  497.  
     
  498.  
    /*
  499.  
    * 发送群消息
  500.  
    */
  501.  
    router.post('/api/dingtalkserve/chatSend', async ({ request, response, session }) => {
  502.  
    try {
  503.  
     
  504.  
    let body = request.fields;
  505.  
    if (!body['chatid']) {
  506.  
    return response.fail({
  507.  
    'msg': "群id不能为空"
  508.  
    });
  509.  
    }
  510.  
    if (!body['msg']) {
  511.  
    return response.fail({
  512.  
    'msg': "群消息不能为空"
  513.  
    });
  514.  
    }
  515.  
    // 获取TOKEN
  516.  
    let accessToken = await getAccessToken();
  517.  
    let params = {
  518.  
    chatid: body['chatid'],
  519.  
    msg: {
  520.  
    "msgtype": "text",
  521.  
    "text": {
  522.  
    "content": body['msg']
  523.  
    }
  524.  
    }
  525.  
    };
  526.  
    let messageRes = await request(`${host}chat/send?access_token=${accessToken}`, 'POST', params);
  527.  
    console.log("messageRes", messageRes)
  528.  
    return response.success({ 'data': messageRes });
  529.  
    } catch (e) {
  530.  
    console.log(e);
  531.  
    return response.fail({
  532.  
    'msg': e
  533.  
    });
  534.  
    }
  535.  
    });
  536.  
     
  537.  
    /*
  538.  
    * 查询群消息已读人员列表
  539.  
    */
  540.  
    router.post('/api/dingtalkserve/getReadList', async ({ request, response, session }) => {
  541.  
    try {
  542.  
     
  543.  
    let body = request.fields;
  544.  
    if (!body['messageId']) {
  545.  
    return response.fail({
  546.  
    'msg': "messageId不能为空"
  547.  
    });
  548.  
    }
  549.  
    if (!body['cursor']) {
  550.  
    return response.fail({
  551.  
    'msg': "cursor不能为空"
  552.  
    });
  553.  
    }
  554.  
    if (!body['size']) {
  555.  
    return response.fail({
  556.  
    'msg': "每页数量不能为空"
  557.  
    });
  558.  
    }
  559.  
    // 获取TOKEN
  560.  
    let accessToken = await getAccessToken();
  561.  
    let params = {
  562.  
    access_token: accessToken,
  563.  
    messageId: body['messageId'],
  564.  
    cursor: body['cursor'],
  565.  
    size: parseInt(body['size']),
  566.  
    };
  567.  
    let messageRes = await request(`${host}chat/getReadList`, 'GET', params);
  568.  
    console.log("messageRes", messageRes)
  569.  
    return response.success({ 'data': messageRes });
  570.  
    } catch (e) {
  571.  
    console.log(e);
  572.  
    return response.fail({
  573.  
    'msg': e
  574.  
    });
  575.  
    }
  576.  
    });

以上针对的是钉钉企业内部应用

如果是ISV开发者应用,则需要通过接口获取企业的基本信息

nodejs签名实现

  1.  
    /*
  2.  
    * 把timestamp + "\n" + suiteTicket当做签名字符串, suiteSecret做为签名秘钥,
  3.  
    * 使用HmacSHA256算法计算签名, 然后进行Base64 encode获取最后结果。
  4.  
    * 然后把签名参数再进行urlconde, 加到请求url后面。
  5.  
    */
  6.  
    const crypto = require('crypto');
  7.  
    const accessKey = 'suiteqh0ljtdheuee****'; // suiteKey
  8.  
    const suiteSecret = '******';
  9.  
    const suiteTicket = 'TestSuiteTicket';
  10.  
    const timestamp = Date.now();
  11.  
    const stringToSign = timestamp + "\n" + suiteTicket;
  12.  
     
  13.  
    const hash = crypto.createHmac('sha256', suiteSecret)
  14.  
    .update(stringToSign, 'utf8')
  15.  
    .digest().toString('base64');
  16.  
    console.log(hash);
  17.  
    var request = require("request");
  18.  
    var urlencode = require('urlencode');
  19.  
     
  20.  
    var options = {
  21.  
    method: 'POST',
  22.  
    url: 'https://oapi.dingtalk.com/service/get_auth_info',
  23.  
    qs: {
  24.  
    signature: hash,
  25.  
    timestamp: timestamp,
  26.  
    suiteTicket: suiteTicket,
  27.  
    accessKey: accessKey
  28.  
    },
  29.  
    headers: {
  30.  
    'Cache-Control': 'no-cache',
  31.  
    'Content-Type': 'application/json'
  32.  
    },
  33.  
    body: { auth_corpid: 'dingd142a587da6ee21d35c2f4657eb6378f' },
  34.  
    json: true
  35.  
    };
  36.  
     
  37.  
    request(options, function (error, response, body) {
  38.  
    if (error) throw new Error(error);
  39.  
     
  40.  
    console.log(body);
  41.  
    });

  

钉钉文档开发者链接 :https://open-doc.dingtalk.com/microapp/serverapi2/isu6nk

转载于:https://www.cnblogs.com/xiaosongJiang/p/9991573.html

上一篇:对比《动手学深度学习》 PDF代码+《神经网络与深度学习 》PDF


下一篇:美秒快报 移动端API接口后台制作总结