钉钉

  • 钉钉的接入和微信大众号根本时一起的,仅有不同的是微信很难拿到手机号切大众号接口的权限和账号自身特性有关,而钉钉拿到手机号还是很容易的,并且钉钉接口的权限只需求请求就能够了。

钉钉二次开发完美完爆消息通知

  • 首要咱们注册一个后台账号并登陆进去创立一个企业内部运用。我这儿便是创立的test运用。

钉钉二次开发完美完爆消息通知

  • 到这儿咱们就具有了CorpId,AgentId,AppKey,AppSecrect四个参数了。这四个参数在不同的当地分别被运用。都说了和微信是一个套路,那么剩余的自然是需求咱们装备权限办理。

钉钉二次开发完美完爆消息通知

  • 下面是我针对目前功用所注册的权限。假如你嫌麻烦那就一切权限悉数注册。
接口 权限点code 悉数状态筛选 操作
个人手机号信息 获取用户个人信息 Contact.User.mobile 已注册
通讯录个人信息读权限 获取用户通讯录个人信息 Contact.User.Read 已注册
调用SNS API时需求具有的根本权限 查询个人授权记载 snsapi_base 已注册
企业职工手机号信息 fieldMobile 已注册
通讯录部分信息读权限 获取部分概况;获取指定用户的一切父部分列表;获取部分列表;获取指定部分的一切父部分列表;查看更多 qyapi_get_department_list 已注册
成员信息读权限 获取用户高管模式设置;查询用户概况;获取部分用户userid列表;获取办理员列表;查看更多 qyapi_get_member 已注册
依据手机号名字获取成员信息的接口拜访权限 依据手机号获取userid qyapi_get_member_by_mobile 已注册
通讯录部分成员读权限 查询部分用户完好信息;获取部分用户根底信息;获取人物概况;获取指定人物的职工列表 qyapi_get_department_member 已注册
调用企业API根底权限 生成jsapi ticket;生成微运用办理后台accessToken;查询连接器主数据概况;分页拉取连接器主数据;查看更多 qyapi_base 已注册
待办运用中待办写权限 更新待办履行者状态;新增钉钉待办使命;更新钉钉待办使命;删去钉钉待办使命 Todo.Todo.Write 已注册
待办运用中待办读权限 查询企业下用户待办列表;依据sourceId获取钉钉待办使命概况;获取钉钉待办使命概况 Todo.Todo.Read 已注册

测验用例

获取部分列表

  • 钉钉和大众号不同的是,钉钉细分很多,树形结构一向递归下去。和微信大众号相同咱们也需求获取企业下(大众号)列表。
@Test
public void getDeptListTest() {
 final List<OapiV2DepartmentListsubResponse.DeptBaseResponse> deptBaseResponses = deptService.selectDeptList(null);
 for (OapiV2DepartmentListsubResponse.DeptBaseResponse deptBaseRespons : deptBaseResponses) {
  System.out.println(JSON.toJSONString(deptBaseRespons));
  }
}
  • 假如行获取跟部分下的用户列表咱们deptId=1或许不传。

钉钉二次开发完美完爆消息通知

{"autoAddUser":true,"createDeptGroup":true,"deptId":581377085,"name":"运营部","parentId":1}
{"autoAddUser":true,"createDeptGroup":true,"deptId":581377086,"name":"规划部","parentId":1}
{"autoAddUser":true,"createDeptGroup":true,"deptId":581377087,"name":"产品部","parentId":1}
{"autoAddUser":true,"createDeptGroup":true,"deptId":581377088,"name":"人事部","parentId":1}
{"autoAddUser":true,"createDeptGroup":true,"deptId":581377089,"name":"行政部","parentId":1}

获取部分用户列表

@Test
public void getUserInfo() {
 Long deptId = 1L;
 final List<AbstrctUser> userList = userInfoService.selectUserListBaseOnDeptId(deptId);
 for (AbstrctUser abstrctUser : userList) {
  System.out.println(JSON.toJSONString(abstrctUser));
  }
}

钉钉二次开发完美完爆消息通知

{"userId":"XXX","userName":"丁1"}
{"userId":"XXXX","userName":"张1"}

通过手机号获取用户信息

@Test
  public void getUsrDetailOnPhoneTest() {
    String phone = "phone";
    final List<AbstrctUser> userList = userInfoService.selectUserBaseOnPhone(phone);
    for (AbstrctUser abstrctUser : userList) {
      System.out.println(JSON.toJSONString(abstrctUser));
     }
   }

发送信息

@Test
  public void sendMsg() {
    for (int i = 0; i < 1; i++) {
      List<String> userIds = Arrays.asList(new String[]{"tet,ttttt"});
      List<Long> deptIds = Arrays.asList(new Long[]{1l});
      messageService.sendToDeptInUser(userIds,deptIds,false,new TextMessage("你们好,元旦放假了!!!,我正在测验音讯发送多人"+UUID.randomUUID()));
     }
   }

免登录

前端

  • 相同的钉钉中咱们也需求获取当时登陆用户信息,所以还需求咱们钉钉登陆授权。
  • 点我了解登陆认证钉钉
  • npm install dingtalk-jsapi --save进行装置。
dd.ready(function() {
  // dd.ready参数为回调函数,在环境准备就绪时触发,jsapi的调用需求保证在该回调函数触发后调用,否则无效。
  dd.runtime.permission.requestAuthCode({
    corpId: "corpid",
    onSuccess: function(result) {
    /*{
       code: 'hYLK98jkf0m' //string authCode
     }*/
     },
    onFail : function(err) {}
 
   });
});
​
  • 装置完结后就能够通过上面代码获取授权码code,其中需求咱们的参数corpId也是咱们在企业装备账号中的信息之一。

后端

  • 前端获取到code之后,后端就能够依据code获取到当时登陆用户了。
  • https://oapi.dingtalk.com/user/getuserinfo?access_token=%s&code=%s

文件上传

  • 相同咱们钉钉发送音讯也不仅仅局限于文本,https://oapi.dingtalk.com/media/upload

钉钉二次开发完美完爆消息通知

  • 通过和微信的比照咱们知道和微信支撑的类型有很大的交集。所以在微信章节中我提到音讯进行抽象化 , 现在咱们能够共用一套实体类,出现两者不一起的咱们在单独的创立特有的实体满足不同需求。
public MeterialResponse uploadPic(Meterial meterial, String fileName, InputStream inputStream) {
    DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/media/upload");
    OapiMediaUploadRequest req = new OapiMediaUploadRequest();
    req.setType(meterial.getType());
    // 要上传的媒体文件
    FileItem item = new FileItem(fileName,inputStream);
    req.setMedia(item);
    OapiMediaUploadResponse rsp=null;
    try {
      rsp = client.execute(req, tokenService.accessAndGetDingDingToken());
     } catch (ApiException e) {
      e.printStackTrace();
     }
    MeterialResponse response = new MeterialResponse();
    final Field[] declaredFields = rsp.getClass().getDeclaredFields();
    JSONObject jsonObject = new JSONObject();
    for (Field declaredField : declaredFields) {
      final ApiField annotation = declaredField.getAnnotation(ApiField.class);
      if (null == annotation) {
        continue;
       }
      final String value = annotation.value();
      declaredField.setAccessible(true);
      try {
        jsonObject.put(value, declaredField.get(rsp));
       } catch (IllegalAccessException e) {
        e.printStackTrace();
       }
     }
    BeanUtils.transBeanWithTranAnnotation(jsonObject, response);
    return response;
   }

发送音讯

  • 在上面咱们已经完结了上传文件了。返回的media_id便是咱们交互的载体。咱们发送信息只需求将media_id发送曩昔就行了。
@Test
  public void sendMultiTypeMessage() {
    String fileName = "/macpower.png";
    InputStream resourceAsStream = this.getClass().getResourceAsStream(fileName);
    final MeterialResponse response = uploadService.uploadPic(new ImageMeterial(), fileName, resourceAsStream);
    System.out.println(response);
    Message message = new ImageMessage(response.getMediaId());
    List<String> userIds = Arrays.asList(new String[]{"manager2239"});
    List<Long> deptIds = Arrays.asList(new Long[]{1l});
    messageService.sendToDeptInUser(userIds,deptIds,false,message);
   }
  • 这儿的发送实际上常识Message的不同罢了。

钉钉二次开发完美完爆消息通知

代码阐明

钉钉二次开发完美完爆消息通知

  • 首要我将包办理放在根目录办理。
  • message-api用于办理微信,钉钉通用部分,比方界说通用方法,微信,钉钉都需求完结发送信息功用,那么关于接口的界说便是放在message-api中的。还有便是关于音讯的抽象的界说也是在message-api中完结的。包括一些东西类放在message-api完结。
  • message-demo是针对钉钉,微信的测验用例。在demo中搭建好测验环境。编写测验用例。
  • 剩余的便是dingding-message-rootwechat-message-root两个模块了。顾名思义便是钉钉微信的处理业务。两个模块结构是相同的,内部会支撑message-api界说的骨架的根底上进行定制开发。比方wechat-message-root中会开发微信特有的上传图文的功用。假如咱们想运用该功用的话就不能仅仅用公共的MessageService 。 而是需求运用愈加清晰的WechatMessageService
  • 再者,咱们运用spring框架根本上是覆盖很广。所以每个message-root还需求在细分。即wechat-message-root下细分为spring-wechat-starterwechat-core 。 前者是对spring的开箱即用的支撑,后者才是真实对接微信大众号的服务功用。

钉钉二次开发完美完爆消息通知

  • 能够看到service.impl中主要都是完结message-api模块中界说好的接口。在完结主接口的根底上需求扩展封住的功用会在wechat-core中进行扩展开发。
  • 由于钉钉,微信都完结message-api模块的接口,且内部都有spring的开箱即用功用,而spring容器中beanName是仅有的。而且为了咱们自己能确定运用详细的模块的be an ,咱们需求在注册的时分拟定咱们beanName,这样咱们在运用的时分在通过名称查找。
  • 比方我这样界说了一个bean
@Bean("wechatMessageService")
public MessageService wechatMessageService(TokenService tokenService) {
 WechatMessageServiceImpl wechatMessageService = new WechatMessageServiceImpl();
 wechatMessageService.setTokenService(tokenService);
 return wechatMessageService;
}
  • 那么我在运用的时分需求这样装备
@Autowired
@Qualifier("wechatMessageService")
MessageService messageService;
  • 这样咱们在运用的时分在两者公共的功用时,只需求通过对应的service完结就能够了。比方群发功用。这个时分假如咱们微信钉钉都需求完结,那么咱们能够通过这样引入service
@Autowired
List<MessageService> messageServiceList ;
  • 履行的时分咱们只需求遍历履行就能够了

钉钉二次开发完美完爆消息通知

总结

  • 系统对接其实并没啥技术含量,只需咱们依据官网文档一步一步操作就能够了。咱们便是调用api 。 真实的高度时在平台的完结。比方咱们的接口调用的权限基于o a u t h2完结的登陆鉴权。这些在maltcloud中咱们都有去完结。后边有机会会结合实战去解读下oauth2和怎么规划完结接口权限调度
  • 除了微信的对接外,常见的还有付出宝的付出功用。这也是在掉接口核心的永远都是平台的功用。假如有需求咱们后边在看看付出宝的接入