飞书二开系列之开发流程解析与示例代码(二)

📖 飞书二次开发系列文章:

   飞书二开系列之创建测试企业与企业应用等准备工作(一)

   ➡️ 飞书二开系列之开发流程解析与示例代码(二)

  飞书二开系列之SpringBoot实现通讯录显示请假状态(三)

一、前言

  当准备工作做好后,我们就开始理解清楚飞书开发的流程,我们写的代码怎么和飞书进行交互,要遵守飞书哪些规则,当理解清楚了才有一个好的思路去进行二次开发,那么继续跟我一起深入下去吧。

二、开发流程

2.1 文字描述流程

# 开启了事件Encrypt Key,飞书所有请求都是加密的,所以获取飞书请求都要进行解密操作。
所以流程如下:
飞书发送challenge请求校验服务器真实性 -> 后端解密response -> 后端返回 {"challenge":"解析response的challenge值"} -> 服务器校验成功,成功保存请求地址 -> 飞书请假审批通过 -> 后端监听到审批请求 -> 后端解密审批response -> 读取json,post调用创建请假日历接口,传递对应参数 -> 成功显示请假状态

# 官方文档
##  配置 Encrypt Key文档
https://open.feishu.cn/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/event-subscription-configure-/request-url-configuration-case

## 解密encrypt文档
https://open.feishu.cn/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/event-subscription-configure-/encrypt-key-encryption-configuration-case
# 如果你配置了Encrypt Key,那么飞书发出来的请求的是进行过加密处理,数据如下:
{
    "encrypt": "FIAfJPGRmFZWkaxPQ1XrJZVbv2JwdjfLk4jx0k/U1deAqYK3AXOZ5zcHt/cC4ZNTqYwWUW/EoL+b2hW/C4zoAQQ5CeMtbxX2zHjm+E4nX/Aww+FHUL6iuIMaeL2KLxqdtbHRC50vgC2YI7xohnb3KuCNBMUzLiPeNIpVdnYaeteCmSaESb+AZpJB9PExzTpRDzCRv+T6o5vlzaE8UgIneC1sYu85BnPBEMTSuj1ZZzfdQi7ZW992Z4dmJxn9e8FL2VArNm99f5Io3c2O4AcNsQENNKtfAAxVjCqc3mg5jF0nKabA+u/5vrUD76flX1UOF5fzJ0sApG2OEn9wfyPDRBsApn9o+fceF9hNrYBGsdtZrZYyGG387CGOtKsuj8e2E8SNp+Pn4E9oYejOTR+ZNLNi+twxaXVlJhr6l+RXYwEiMGQE9zGFBD6h2dOhKh3W84p1GEYnSRIz1+9/Hp66arjC7RCrhuW5OjCj4QFEQJiwgL45XryxHtiZ7JdAlPmjVsL03CxxFZarzxzffryrWUG3VkRdHRHbTsC34+ScoL5MTDU1QAWdqUC1T7xT0lCvQELaIhBTXAYrznJl6PlA83oqlMxpHh0gZBB1jFbfoUr7OQbBs1xqzpYK6Yjux6diwpQB1zlZErYJUfCqK7G/zI9yK/60b4HW0k3M+AvzMcw=" 
}
# 这需要配合Encrypt Key进行解密处理就能获取正常的json数据。
# 没有配置Encrypt Key就是直接明文传输,为了安全性建议配置Encrypt Key。
# 没有配置Encrypt Key数据如下:
{ 
    "challenge": "ajls384kdjx98XX", // 应用需要在响应中原样返回的值 
    "token": "xxxxxx",              // 即 Verification Token
    "type": "url_verification"      // 表示这是一个验证请求 
}

在这里插入图片描述

2.2 流程图描述流程

  这里我用一个流程图来清晰展现整个飞书的开发流程。

在这里插入图片描述

2.3 请求地址配置

  这里给个示例图,具体实现会在飞书二开系列之SpringBoot实现通讯录显示请假状态(三)中呈现。

在这里插入图片描述

  当vps server 的web服务challenge响应了飞书就能绑定到请求地址,就可以添加事件了。

在这里插入图片描述

三、事件结构

  事件包括 v1.0 和 v2.0 两个版本,不同版本的事件结构不同。添加事件时,从页面上可以看出,添加的是哪个版本的事件,这里了解一下就好,你要监听什么事件,监听的事件是什么版本就接收数据进行处理就行了。

img

3.1 v1.0 版本事件结构

  下面列举了一个 v1.0 版本的事件示例。

  • ts 字段表示事件发送的时间,一般近似于事件发生的时间。
  • uuid 字段是事件的唯一标识。
  • token 字段即 Verification Token。
  • event 结构体记录的是事件的详细信息,不同事件的信息不同。其中,通过 event.type 字段,可以判断事件类型。
{ 
    "ts": "1502199207.7171419",
    "uuid": "bc447199585340d1f3728d26b1c0297a",
    "token": "41a9425ea7df4536a7623e38fa321bae",
    "type": "event_callback",
    "event": { 
        "app_id": "cli_9c8609450f78d102",
        "chat_id": "oc_26b66a5eb603162b849f91bcd8815b20",
        "operator": {
            "open_id": "ou_2d2c0399b53d06fd195bb393cd1e38f2",
            "user_id": "gfa21d92"
        },
        "tenant_key": "736588c9260f175c",
        "type": "p2p_chat_create",
        "user": {
            "name": "user_name",
            "open_id": "ou_7dede290d6a27698b969a7fd70ca53da",
            "user_id": "gfa21d92"
        }
    }
}

3.2 v2.0 版本事件结构

  下面列举了一个 v2.0 版本的事件示例。

  • schema 字段表示事件的版本。v1.0 版本的事件,无此字段。
  • header.event_id 字段是事件的唯一标识。
  • header.token 字段即 Verification Token。
  • header.create_time 字段表示事件发送的时间,一般近似于事件发生的时间。
  • header.event_type 字段表示事件类型。
  • event 结构体记录的是事件的详细信息,不同事件的信息不同。
{
    "schema": "2.0",
    "header": { 
        "event_id": "f7984f25108f8137722bb63cee927e66",
        "token": "066zT6pS4QCbgj5Do145GfDbbagCHGgF",
        "create_time": "1603977298000000",
        "event_type": "contact.user_group.created_v3",
        "tenant_key": "xxxxxxx",
        "app_id": "cli_xxxxxxxx",
    },
    "event":{
    }
}

四、API调试

  当我们知道开发流程后,就要看自己的需求要调用哪些接口,看这些接口传递什么参数,这就需要在API后台管理做调试,查看要传递的header和body。

# api调试页面
https://open.feishu.cn/api-explorer/

4.1 API调用获取用户user_id接口

  很多接口调用需要传递user_id ,那么我们在做接口测试的时候第一步就是先获取user_id,在API列表中的获取登录用户信息接口,在请求头Authorization填入user_access_token,点击开始调用即可。

在这里插入图片描述

4.2 API调用创建请假日历接口

  调用创建请假日历接口就可以看到创建请假标签效果和请假日历效果,如下。

在这里插入图片描述

  在API列表中的创建请假日程接口,在请求头Authorization填入tenant_access_token。

在这里插入图片描述

  在请求体中,user_id就填入前面获取的open_id,start_time、end_time填入请假的开始时间和结束时间即可。

在这里插入图片描述

  api接口调用成功后,就能在飞书app上看到请假标签,你的同事也能看到喔。

在这里插入图片描述

  在日历中也能清晰看到你的请假哪天到哪天。

在这里插入图片描述

五、示例代码

5.1 解密encrypt response

# 解密encrypt文档
https://open.feishu.cn/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/event-subscription-configure-/encrypt-key-encryption-configuration-case

  官方文档文档里有python3、java、golang、node.js、c#、php的解密encrypt的代码,之后在第三篇(飞书二开系列之SpringBoot实现通讯录显示请假状态(三))中会是用到java的解密代码,以下就是java的解密代码:

package com.larksuite.oapi.sample;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public class Decrypt {
    public static void main(String[] args) throws Exception {
        Decrypt d = new Decrypt("test key");
        System.out.println(d.decrypt("P37w+VZImNgPEO1RBhJ6RtKl7n6zymIbEG1pReEzghk=")); //hello world
    }
    private byte[] keyBs;
    public Decrypt(String key) {
        MessageDigest digest = null;
        try {
            digest = MessageDigest.getInstance("SHA-256");
        } catch (NoSuchAlgorithmException e) {
            // won't happen
        }
        keyBs = digest.digest(key.getBytes(StandardCharsets.UTF_8));
    }
    public String decrypt(String base64) throws Exception {
        byte[] decode = Base64.getDecoder().decode(base64);
        Cipher cipher = Cipher.getInstance("AES/CBC/NOPADDING");
        byte[] iv = new byte[16];
        System.arraycopy(decode, 0, iv, 0, 16);
        byte[] data = new byte[decode.length - 16];
        System.arraycopy(decode, 16, data, 0, data.length);
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyBs, "AES"), new IvParameterSpec(iv));
        byte[] r = cipher.doFinal(data);
        if (r.length > 0) {
            int p = r.length - 1;
            for (; p >= 0 && r[p] <= 16; p--) {
            }
            if (p != r.length - 1) {
                byte[] rr = new byte[p + 1];
                System.arraycopy(r, 0, rr, 0, p + 1);
                r = rr;
            }
        }
        return new String(r, StandardCharsets.UTF_8);
    }
}

5.2 创建请假日历接口

  在上面api调试页面的时候,我们就已经知道了要传递什么参数,所以我就对应api的写接口就行了

在这里插入图片描述

@Override
    public void leaveSchedule(String token, JSONObject data) {
        try {
            System.out.println(data);
            String employee_id = data.getJSONObject("event").getString("employee_id");
            String leave_type = data.getJSONObject("event").getString("leave_type");
            String start_time = data.getJSONObject("event").getString("start_time");
            String end_time = data.getJSONObject("event").getString("end_time");
            if (leave_type.equals("年假") || leave_type.equals("婚假")|| leave_type.equals("产假")|| leave_type.equals("陪产假")|| leave_type.equals("丧假")){
                start_time = formatDate(data.getJSONObject("event").getString("leave_start_time"));
                end_time = formatDate(data.getJSONObject("event").getString("leave_end_time"));
            }
            String jsonData = String.format("{\n" +
                    "    \"user_id\": \"%s\",\n" +
                    "    \"timezone\": \"Asia/Shanghai\",\n" +
                    "    \"start_time\": \"%s\",\n" +
                    "    \"end_time\": \"%s\",\n" +
                    "    \"title\": \"%s中\",\n" +
                    "    \"description\": \"若删除此日程,飞书中相应的“请假”标签将自动消失,而请假系统中的休假申请不会被撤销。\"\n" +
                    "}", employee_id, start_time, end_time, leave_type);
            System.out.println(jsonData);
            String requests = HttpRequests.requests(timeoff_events_url, jsonData, "Bearer " + token);
            System.out.println("请假同步日历:" + requests);
        } catch (Exception e) {
            System.out.println("请求创建请假日常接口: " + e);
        }
    }

六、总结

  本章节主要讲述在搭建测试环境后进行二次开发的一个流程,解密请求和api接口的测试调用的方法,第一章的内容是讲述创建测试企业与机器人等准备工作,没有看过的小伙伴可回顾观看,下一篇则是使用springboot实现通讯录显示请假状态的具体实现包含源码,没有飞书二开需求的同学也可以观看学习,扩展思路。微信公众号搜索关注艺说IT学习更多内容,对你有用的话请一键三连,感谢。

在这里插入图片描述

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
域名DNS解析系统是一种将域名转换为IP地址的系统。当我们输入一个域名时,DNS解析系统会根据配置的域名服务器进行查找,找到与该域名对应的IP地址,并将用户的请求转发到该IP地址上的服务器。这样就能实现在浏览器上输入域名后能够访问到网站的功能。 级域名分发系统是指在一个域名下又分配了多级子域名。例如,我们可以通过在域名后添加一个名称作为级域名来实现不同功能或部门的分发。级域名分发系统可以根据级域名的不同来将用户的请求转发到不同的服务器或处理逻辑上,这样能够更好地实现网站的功能划分和灵活配置。 二开UI分发系统是指二次开发用户界面分发系统的网站源码,并且该源码中的代码没有进行加密。一般来说,UI分发系统是为了方便网站管理员或开发人员对网站界面进行修改和定制而开发的。二开UI分发系统的源码如果没有加密,意味着我们可以自由地在源码的基础上进行二次开发、修改和定制,满足我们自己的需求。这样能够更好地适应不同网站的需求和风格,提供更好的用户体验。 总之,域名DNS解析系统、级域名分发系统和二开UI分发系统网站源码都是为了实现更好的域名管理、功能分发和用户界面定制而存在的。这些系统和源码的使用可以提高网站的性能、功能和用户体验,为网站的运营和发展提供支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值