介绍

钉钉H5微应用接口对接,主要涉及以下几个方面:

  1. 模块Config
  2. 工作通知
  3. 网页登录
  4. 网页前端JSSDK
  5. 钉钉网页布局
  6. 钉钉API调用

1. 模块Config

我们可以通过在项目Config文件中覆盖模块Config中的参数,从而配置与钉钉有关的信息

关于如何覆盖模块Config,请参见:Config

a-dingtalk/backend/src/config/config.js

  // account.dingtalk
  config.account.dingtalk = {
    corpid: 'ww1fe9daaaa045aaaa',
    ssosecret: '02322323dsssw2',
    // apps
    apps: {
      selfBuilt: {
        agentid: '',
        appkey: '',
        appsecret: '',
        businessCallback: {
          host: 'yourdomain.com',
          token: appInfo.name,
          encodingAESKey: '',
        },
      },
    },
  };
名称 说明
apps 配置所有钉钉应用的参数,包括:钉钉内置应用、第三方应用,以及自建应用。如需访问其他应用提供的API接口,直接在apps添加新的配置即可
apps.selfBuilt 自建应用(H5微应用)
businessCallback 事件订阅,与管理后台事件订阅的配置保持一致。非常重要,比如通讯录的同步更新需要用到此配置

2. 工作通知

模块a-dingtalk已经对工作通知的推送机制进行了封装。比如,要向某个用户发送工作通知的消息,可以这样操作:

src/module/test-dingtalk/backend/src/service/test.js

async sendAppMessage({ message, user }) {
  const msg = {
    msgtype: 'text',
    text: {
      content: message.text,
    },
  };
  const content = {
    userIds: [ user.id ],
    data: { msg },
  };
  await this.ctx.bean.io.pushDirect({
    content,
    channel: { module: 'a-dingtalk', name: 'app' },
  });
}
名称 说明
content.userIds 推送的目标用户
content.msg 推送的消息内容,参考发送工作通知
channel 内置的推送通道

3. 网页登录

模块a-dingtalk自动判断,如果当前网页处于钉钉app中,会自动进行免登处理,然后自动进行用户认证

4. 网页前端JSSDK

模块a-dingtalk提供了便捷的组件,可以自动注入钉钉JSSDK,并且自动进行config配置

测试模块test-dingtalk演示了如何调用钉钉的二维码扫描操作:

src/module/test-dingtalk/front/src/pages/test/index.vue

  created() {
    const action = {
      actionModule: 'a-dingtalk',
      actionComponent: 'jssdk',
      name: 'config',
    };
    this.$meta.util.performAction({ ctx: this, action }).then(res => {
      this.dd = res && res.dd;
    }).catch(e => {
      this.$view.toast.show({ text: e.message });
    });
  },
  methods: {
    onPerformScanQRCode() {
      this.dd.biz.util.scan({
        type: 'all',
        onSuccess: res => {
          this.$view.toast.show({ text: res.text });
        },
        onFail: err => {
          this.$view.toast.show({ text: err.message });
        },
      });
    },
  }
  1. 先通过this.$meta.util.performAction调用模块a-dingtalk提供的组件,返回dd对象
  2. 调用dd对象执行扫描二维码的钉钉接口

5. 钉钉网页布局

CabloyJS可以一站式开发PC端和移动端的网页,此外,CabloyJS通过event机制可以灵活定制不同场景下前端页面的布局组合

测试模块test-dingtalk演示了如何定制Mobile场景下的前端布局:

5.1 meta

src/module/test-dingtalk/backend/src/meta.js

event: {
  implementations: {
    'a-base:loginInfo': 'loginInfo',
  },
},
名称 说明
a-base:loginInfo 模块名称:事件名称
loginInfo 响应事件的Bean组件

5.2 定义Bean组件

在本示例中,响应事件a-base:loginInfo,判断info.user.provider,如果是通过钉钉App登录的账户,就提供自定义的前端布局参数

src/module/test-dingtalk/backend/src/bean/event.loginInfo.js

const require3 = require('require3');
const extend = require3('extend2');

module.exports = ctx => {
  class eventBean {

    async execute(context, next) {
      const info = context.data.info;
      const provider = info.user && info.user.provider;
      if (provider && provider.module === 'a-dingtalk' && provider.providerName === 'dingtalk') {
        info.config = extend(true, info.config, {
          modules: {
            'a-layoutmobile': {
              layout: {
                login: '/a/login/login',
                loginOnStart: true,
                toolbar: {
                  tabbar: true, labels: true, bottomMd: true,
                },
                tabs: [
                  { name: 'Test', tabLinkActive: true, iconMaterial: 'group_work', url: '/test/dingtalk/test/index' },
                  { name: 'Home', tabLinkActive: false, iconMaterial: 'home', url: '/a/basefront/menu/list' },
                  { name: 'Mine', tabLinkActive: false, iconMaterial: 'person', url: '/a/user/user/mine' },
                ],
              },
            },
          },
        });
      }
      // next
      await next();
    }

  }

  return eventBean;
};
名称 说明
context.data 外部传入的参数
next event采用洋葱圈模型,调用next从而允许其他事件实现的执行

5.3 注册Bean组件

src/module/test-dingtalk/backend/src/beans.js

const eventLoginInfo = require('./bean/event.loginInfo.js');

module.exports = app => {
  const beans = {
    // event
    'event.loginInfo': {
      mode: 'ctx',
      bean: eventLoginInfo,
    },
  };
  return beans;
};
注册名称 场景 所属模块 global beanFullName
loginInfo event test-wxwork false test-wxwork.event.loginInfo

6. 钉钉API调用

模块a-dingtalk提供了全局Bean组件dingtalk,用于调用所有钉钉API,格式如下:

ctx.bean.dingtalk.app.{appName}

名称 说明
appName 应用名称,比如selfBuilt(自建应用)

钉钉API基于ali-sdk/node-dingtalk。为了便于更灵活的添加新API,CabloyJS对主仓库发起了一个新分支,详细的API清单请参见:node-dingtalk

下面以JSSDK Config为例:

src/module-system/a-dingtalk/backend/src/service/jssdk.js

async jsconfig({ url }) {
  // config
  const config = this.ctx.config.account.dingtalk;
  const configAppSelfBuilt = config.apps.selfBuilt;
  // jsconfig
  const res = await this.ctx.bean.dingtalk.app.selfBuilt.client.getJSApiConfig(url);
  return {
    ...res,
    agentId: configAppSelfBuilt.agentid,
    type: configAppSelfBuilt.jssdk.type,
    jsApiList: configAppSelfBuilt.jssdk.jsApiList,
  };

}

7. 如何判断是否在钉钉

由于CabloyJS后端架构的普适性,我们有时候需要判断当前是否在钉钉中,从而做出相应的处理

7.1 通过中间件判断

可以通过中间件inDingtalk来判断该api接口是否被钉钉调用,如果不是则自动阻止后续逻辑的执行

src/module/test-dingtalk/backend/src/routes.js

  { method: 'post', path: 'test/getMemberId', controller: test, middlewares: 'inDingtalk',
      meta: {
        inDingtalk: {
          scene: 'dingtalk,dingtalkweb,dingtalkadmin,dingtalkmini',
        },
      },
    },
名称 说明
meta.inDingtalk 中间件inDingtalk的参数
scene 如果指定dingtalk,表示该api只能被自建H5微应用调用

scene支持以下值:

名称 说明
空字符串 默认为dingtalk,代表自建H5微应用
dingtalkweb 代表钉钉Web扫码登录
dingtalkadmin 代表钉钉Web管理后台登录
dingtalkmini 代表钉钉小程序
dingtalkmini${scene} 指定更明确的某个小程序,如dingtalkminidefault
dingtalk,dingtalkweb,dingtalkadmin,dingtalkmini 该api可被任何一个指定的场景调用

7.2 通过代码判断

可以直接通过代码进行判断

ctx.bean.dingtalk.util.in(scene)

名称 说明
scene 场景名,如dingtalk