NAV Navbar
javascript
  • About
  • DD-CONFIG
  • DD-utils
  • DD-Service API
  • About

    由于钉钉未提供nodejs sdk,初次用nodejs对应相应接口时比较费时费力,所以将项目中的钉钉对接接口整理出来,以egg插件的方式提供呈现。

    本sdk的主要达到三个目的:

    1. config: 钉钉相关配置的约定
    2. utils: 将钉钉加解密之类的复杂方法抽象为工具类
    3. service: 将与钉钉相关的API接口进行封装,以service方式提供,方便调用

    另外,关于为什么基于egg插件,说明一下原因:

    1. egg框架本身在企业级应用框架中的分层非常清晰,扩展机制极其灵活,配套完整,极力推荐
    2. 通过egg插件的组织,能够非常方便的组织钉钉的配置文件管理、工具使用及service使用
      1. 提供了统一的配置管理
      2. 提供统一的工具调用方式
      3. 提供统一的service调用方式
      4. 统一的日志服务

    DD-CONFIG

    在config/config.default.js中

      exports.DD_CONFIG = {
        corpId: "dinge0e69ed313daa460",
        secret: "sH_JdRrkgRvmJ5B9_RPjAM51hgT9cXhxCl0-_kUDY5_VOuhPX_PbIoKsigoyEqLd",
        agentId: {
          'default': '103015601',
          'applyAndApprove': '84637933',
          'sso': '103015601'
        },
        aesKey: "1234567890123456789012345678901234567890abc",
        token: "abcdef",
        nonceStr: "123456",
        sso: {
          appId: "dingoakznbgimtvtwk49i1",
          appSecret: "dlDOTzrLsB5XV5aciVsgEu_76KatMgbWgsWJkxsE54fY64D22MIs2ccXkqH6k5gK"
        }
      };
    

    注意DD_CONFIG关键词

    钉钉通信中会涉及安全认证、加解密、签名验证等诸多操作,所以有各类key,token等用于上述过程:

    字段你 格式 说明
    coprId String 公司唯一标识
    secret String 认证密钥,非常重要,妥善保管,具有极高权限
    agentId Sring or Object 微应用的ID
    agentId(String) String 当只有一个微应用时
    agentId(Object) {key, value} = Object 其中 key 为 agentIdType, value为对应值
    aesKey String(43) AES加解密时需要的一个secretKey,长度43位,自己定义
    token String(6) aes加解密及签名时用到, len=6
    nonceStr String(6) aes加解密及签名时用到, len=6
    sso.appId String 钉钉扫码登陆的appId
    sso.appSecret String 钉钉扫码登陆的appSecret

    DD-utils

    钉钉通信加解密:

    // step1: createInstance
    let aes = this.helper.createDdEncrpt();
    // step2: encode(encodeString, timestamp, nonceString);
    let encoded = aes.encode('success', 1500957302881, 'KOHjp9ss');
    // console.log(encoded);
    // step3: decode(decodeString, timestamp, nonceString, decodeStringSignature)
    let parsed = aes.decode(encoded.encrypt, encoded.timeStamp, encoded.nonce, encoded.msg_signature);
    // console.log(parsed)
    

    使用钉钉的部分接口,需要进行加解密以及签名验证操作,签名相对简单,但加解密涉及大量编码转换以及算法知识,在缺乏相关知识背景的情况下,很难完成。官方仅提供了PHP,JAVA SDK,自己摸索了半天才搞定了Nodejs版的部分。

    我们提供了: this.helper.createDdEncrpt()方法

    官方文档:钉钉加解密及签名验证

    另外提供了非egg版本,参见:nodejs-dd-aes

    aes.encode()

    // step2: encode(encodeString, timestamp, nonceString);
    let encoded = aes.encode('success', 1500957302881, 'KOHjp9ss');
    // console.log(encoded);
    

    aes.decode()

    // step3: decode(decodeString, timestamp, nonceString, decodeStringSignature)
    let parsed = aes.decode(encoded.encrypt, encoded.timeStamp, encoded.nonce, encoded.msg_signature);
    // console.log(parsed)
    

    DD-Service API

    service是SDK的核心, 对常见的 dd api 进行了封装~

    General Service

    this.ctx.service.dd.getToken()

    this.ctx.service.dd.sendMessageByDdUserId(ddUserId, messageObj, agentIdType)

    this.ctx.service.dd.getJsApiConfig(originUrl, agentIdType)

    this.ctx.service.dd.getUserInfo(code)

    User Service

    this.ctx.service.ddUser.getUser(userId)

    this.ctx.service.ddUser.getUsers(departmentId, casade = true)

    钉钉官方api中无法递归获取部门中的员工数据,本接口封装了这部分,当casade=true时,递归后去,默认为true

    this.ctx.service.ddUser.getUsersByDepartment(departmentId)

    钉钉官方api获取部门用户时,会有分页概念,本接口屏蔽了分页逻辑,默认返回返回部门下的所有员工。

    this.ctx.service.ddUser.createUser(userInfo)

    this.ctx.service.ddUser.updateUser(userInfo)

    this.ctx.service.ddUser.deleteUser(userId)

    Department Service

    this.ctx.service.ddDepartment.getDepartment(departmentId)

    this.ctx.service.ddDepartment.getDepartments(parentId)

    this.ctx.service.ddDepartment.updateDepartment(departmentInfo)

    this.ctx.service.ddDepartment.deleteDepartment(departmentId)

    SNS Service

    this.ctx.service.ddSns.getToken()

    this.ctx.service.ddSns.getPersistentCode(tmpAuthCode)

    this.ctx.service.ddSns.getSnsToken(persistentCodeOptions)

    this.ctx.service.ddSns.getUserInfo(snsToken)

    this.ctx.service.ddSns.getUserByPersistentCode(persistentCode)

    Events Service

    this.ctx.service.ddEvents.eventsregisterEvents(callbackUrl, events, isUpdate = false)

    this.ctx.service.ddEvents.updateEvents(events)

    this.ctx.service.ddEvents.deleteEvents()

    this.ctx.service.ddEvents.queryEvents()

    Process Service

    this.ctx.service.ddProcess.createProcess(options)

    this.ctx.service.ddProcess.listProcess()

    Media Service

    this.ctx.service.ddMedia.upload(filePath)

    this.ctx.service.ddMedia.get(mediaId)

    Space Service

    this.ctx.service.ddSpace.upload(filePath)

    this.ctx.service.ddSpace.send(mediaId, userId, fileName)