目录
一、前言
审批是ERP或OA系统中经常会涉及到的一种业务流程,而且使用的频率会很高,对于企业、团队的实际业务价值也能够直接的体现,其实做过流程引擎开发的同学应该不陌生,涉及到审批流的开发,其复杂性和难度都是很高的。有了飞书的审批流之后,应用开发者或团队,只需要基于飞书自身的流程模板进行配置,而后在应用程序中与飞书的审批打通,即可实现业务自身的审批流程的全链路实现,本文将详细介绍下如何在java的微服务项目中对接飞书审批流程。
二、前置准备
2.1 开通企业飞书账户
默认情况下,你在公司的组织机构下,直接使用你的账号激活并登录的账户即可。
2.2 确保账户具备多维表操作权限
由于后文会对一些多维表做数据测试,因此再正式开始之前,选择你需要操作的多维表,并提前开通操作权限。
在审批流程节点中,通常会涉及到表单的操作,在飞书中,表单可能会涉及到对多维表的操作,所以建议开通一下多维表的权限。
2.3 获取飞书开放平台文档
百度搜索:飞书开放平台,地址:飞书开放平台,通过 ” 开发文档 ”进入
2.4 创建应用
应用程序对飞书提供的各类能力的操作,均以应用的维度为前提,所以在对接飞书API之前,需要结合实际业务需求进行应用的创建。应用创建操作文档入口:企业自建应用开发流程 - 开发指南 - 飞书开放平台
如下,点击创建应用
跳转链接来到下面的页面 :
按要求填写应用的信息,然后点击创建,创建成功后就可以在列表上看到刚刚创建的这个应用了
2.5 发布应用
应用必须要通过发布之后,应用具备的操作各类飞书文档、多维表格的能力才能生效
点击应用图标,跳转到下面的应用操作控制台,在这个页面,图中两个参数请妥善保管,后面在程序代码中会多处使用
点击 ”版本管理与发布”
点击创建版本,参照下面的格式要求填写,提交之后需要等待飞书管理员审核通过。
2.6 应用添加操作权限
这里的操作权限,可以理解为,对上述添加的这个应用能够做哪些事情,是操作多维表数据?修改/删除文档?还是获取组织机构的人员?定一个具体的操作范围。有点像你在阿里云控制台,或者一些SAAS的操作平台上面,根据自身的需求选择一些平台提供的各类操作能力。如下,在当前的应用页面,点击左侧 ” 权限管理”。
- 比如在本例中,我们需要对接飞书的审批相关的能力,这里就需要在API权限中找到与飞书审批流程相关的API添加到应用中。
2.7 获取SDK
在后文中,需要通过程序代码操作多维表、审批流程,因此需要在代码中导入飞书开放平台提供的SDK,官方给出了2种使用方式,通过SDK提供的API调用,或者通过传统的HTTP方式调用,以Java语言为例进行说明,git对应的SDK获取地址:https://github.com/larksuite/oapi-sdk-java/blob/v2_main/README.md#%E5%88%9B%E5%BB%BAapi-client
三、审批流程对接过程
上面的前置准备完成后,接下来就可以正式开始与审批相关的对接了,参考下面的完整步骤。
3.1 配置流程审批定义(流程审批模型)
即需要管理员身份登录到后台,配置一个审批流程,比如:
-
流程中涉及到几级审批;
-
各个审批节点上面的审批人是谁?是单个人审批?多人审批?
-
审批节点上面配置的表单是什么?
-
某个审批节点审批通过之后,是否需要发送消息通知等?
-
...
进入某个审批模型之后,进入到下面的一个可以拖拽的页面,在这个页面根据你的需要进行表单元素的配置。
配置审批节点,即流程中的具体节点信息,比如节点中的审批人,审批模式(是单签,会签,或签,是否发送通知等)
全部配置完成之后,注意发布这个审批定义的流程。
3.2 自定义应用添加审批API
找到前面的自定义应用,然后再在该应用的访问权限列表里面添加与审批相关的API
3.2.1 定位自定义应用
开发者后台 - 飞书开放平台 ,如果没有应用需要提前创建一个
3.2.2 为自定义应用添加审批API
进入自定义应用之后,在权限管理 ->开通权限 -> 审批,勾选审批相关的API ,添加进去,说明当前的app具备了调用权限相关的能力,比如开始一个流程审批
3.2.3 获取对接文档
下图是官方文档给出的完整的对接流程,正好符合目前我们使用的场景
3.3 核心审批流程API对接过程
接下来对照官方API文档,结合实际使用场景,在Java代码中进行集成和调用,首先在Maven依赖中添加API的SDK依赖
<dependency>
<groupId>com.larksuite.oapi</groupId>
<artifactId>oapi-sdk</artifactId>
<version>2.4.8</version>
</dependency>
3.3.1 根据手机号获取当前账户的飞书信息
接口文档地址:通过手机号或邮箱获取用户 ID - 服务端 API - 飞书开放平台
对接技巧:
-
填写必须的参数,在右侧的控制台上面先进行调用;
-
调用成功之后,再点开示例代码,切换查看Java SDK的代码即可;
完整演示代码:
-
APP_ID ,APP_SECRET 是与自定义的应用相关的,可以认为是常量进行维护即可;
-
调用这个API其核心是要拿到用户的user_id,以便在后面启动一个流程,或者获取流程实例的时候使用;
package com.congge.feishu;
import com.google.gson.JsonParser;
import com.lark.oapi.Client;
import com.lark.oapi.core.utils.Jsons;
import com.lark.oapi.service.contact.v3.model.*;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import com.lark.oapi.core.request.RequestOptions;
// SDK 使用文档:https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/server-side-sdk/java-sdk-guide/preparations
/**
* 根据手机号获取用户信息
* 响应结果:
* {"user_list":[{"user_id":"你的user_id","mobile":"测试手机号"}]}
*/
public class BatchGetIdUserSample {
private static final String APP_ID = "你的client_id";
private static final String APP_SECRET = "你的secret";
public static void main(String arg[]) throws Exception {
// 构建client
Client client = Client.newBuilder(APP_ID, APP_SECRET).build();
// 创建请求对象
BatchGetIdUserReq req = BatchGetIdUserReq.newBuilder()
.userIdType("open_id")
.batchGetIdUserReqBody(BatchGetIdUserReqBody.newBuilder()
.mobiles(new String[] {
"测试手机号"
})
.includeResigned(true)
.build())
.build();
// 发起请求
BatchGetIdUserResp resp = client.contact().v3().user().batchGetId(req);
// 处理服务端错误
if(!resp.success()) {
System.out.println(String.format("code:%s,msg:%s,reqId:%s, resp:%s",
resp.getCode(), resp.getMsg(), resp.getRequestId(),
Jsons.createGSON(true, false).toJson(JsonParser.parseString(new String(resp.getRawResponse().getBody(), StandardCharsets.UTF_8)))));
return;
}
// 业务数据处理
System.out.println(Jsons.DEFAULT.toJson(resp.getData()));
}
}
运行一下程序,返回结果中会输出user_id的信息,到时候只需要解析即可
3.3.2 启动一个流程审批
即基于自己前面配置的审批流程定义,启动一个流程,更通俗的来说,就是提交审批,API文档地址:
必填参数:
-
approval_code , 审批定义 code ;
-
form , 审批的表单信息;
-
其他参数均为可选,可以根据实际情况传入即可;
完整代码如下:
package com.congge.feishu;
import com.google.gson.JsonParser;
import com.lark.oapi.Client;
import com.lark.oapi.core.utils.Jsons;
import com.lark.oapi.service.approval.v4.model.*;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import com.lark.oapi.core.request.RequestOptions;
// SDK 使用文档:https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/server-side-sdk/java-sdk-guide/preparations
/**
* TODO 1、创建审批实例 【即开始一个流程】
* 返回的是流程实例信息 :
* {
* "code": 0,
* "data": {
* "instance_code": "86D1E67F-B3A5-4DB4-9818-63DC463DD9BF"
* },
* "msg": ""
* }
*
* 请求参数:
* {
* "approval_code": "05D6B8CB-3C6F-4F16-A8E6-014354ADFC3A",
* "open_id": "你的open_id",
* "form": "[]",
* "node_approver_open_id_list": [
* {
* "key": "bbbd2796ce3808095c5faa89bb8aed2d",
* "value": [
* "你的user_id"
* ]
* }
* ]
* }
*
*
*/
public class CreateInstanceSample {
private static final String APP_ID = "cli_XXX";
private static final String APP_SECRET = "你的secret";
private static final String APPROVAL_CODE = "05D6B8CB-3C6F-4F16-A8E6-014354ADFC3A";
public static void main(String arg[]) throws Exception {
// 构建client
Client client = Client.newBuilder(APP_ID, APP_SECRET).build();
// 创建请求对象
CreateInstanceReq req = CreateInstanceReq.newBuilder()
.instanceCreate(InstanceCreate.newBuilder()
.approvalCode(APPROVAL_CODE)
.openId("提交人自己的ID") //提交人自己的open_id
.form("[]")
.nodeApproverOpenIdList(new NodeApprover[] {
NodeApprover.newBuilder()
.key("bbbd2796ce3808095c5faa89bb8aed2d") //提交到下一个节点的node_id,通过流程定义可以查询到,如果没有,这里可以不填
.value(new String[] {
"提交人自己的open_id"
})
.build()
})
.build())
.build();
// 发起请求
CreateInstanceResp resp = client.approval().v4().instance().create(req);
// 处理服务端错误
if(!resp.success()) {
System.out.println(String.format("code:%s,msg:%s,reqId:%s, resp:%s",
resp.getCode(),
resp.getMsg(),
resp.getRequestId(),
Jsons.createGSON(true, false).toJson(JsonParser.parseString(new String(resp.getRawResponse().getBody(), StandardCharsets.UTF_8)))));
return;
}
// 业务数据处理
System.out.println(Jsons.DEFAULT.toJson(resp.getData()));
}
}
运行上面的代码,提交成功,返回本次的流程实例ID
3.3.3 撤销流程审批
如果管理员在后台设置了 允许撤销审批中的申请 或者 允许撤销 x 天内通过的审批,则在符合规则时,提交人可以调用该接口撤回审批实例。接口文档:撤回审批实例 - 服务端 API - 飞书开放平台
接口核心参数说明:
-
approval_code,即流程定义的唯一编码;
-
instance_code,提交审批之后,飞书接口返回的本次流程实例的唯一编码,可认为是taskId;
-
user_id,当前操作用户的ID;
控制台请求响应效果:
-
本地启动一个流程实例(提交一个审批任务),拿到飞书返回的流程实例的instance_code;
-
拿到当前提交人的user_id;
Java代码操作演示:
package com.congge.feishu;
import com.google.gson.JsonParser;
import com.lark.oapi.Client;
import com.lark.oapi.core.utils.Jsons;
import com.lark.oapi.service.approval.v4.model.*;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import com.lark.oapi.core.request.RequestOptions;
// SDK 使用文档:https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/server-side-sdk/java-sdk-guide/preparations
/**
* 流程撤回
*/
public class CancelInstanceSample {
private static final String APP_ID = "cli_XXX";
private static final String APP_SECRET = "XXX";
//流程定义的CODE
private static final String APPROVAL_CODE = "05D6B8CB-3C6F-4F16-A8E6-XXX";
public static void main(String arg[]) throws Exception {
// 构建client
Client client = Client.newBuilder(APP_ID, APP_SECRET).build();
// 创建请求对象
CancelInstanceReq req = CancelInstanceReq.newBuilder()
.instanceCancel(InstanceCancel.newBuilder()
.approvalCode(APPROVAL_CODE)
.instanceCode("869ACEBC-0D24-40ED-AF2A-XXX") //上一步启动了一个流程实例的实例ID
.userId("ou_XXX") //我的user_id
.build())
.build();
// 发起请求
CancelInstanceResp resp = client.approval().v4().instance().cancel(req);
// 处理服务端错误
if(!resp.success()) {
System.out.println(String.format("code:%s,msg:%s,reqId:%s, resp:%s",
resp.getCode(),
resp.getMsg(),
resp.getRequestId(),
Jsons.createGSON(true, false).toJson(JsonParser.parseString(new String(resp.getRawResponse().getBody(),
StandardCharsets.UTF_8)))));
return;
}
// 业务数据处理
System.out.println(Jsons.DEFAULT.toJson(resp.getData()));
}
}
响应结果,和控制台一样,msg为空,实际使用中可以使用code进行判断
3.3.4 监听审批流程事件
在应用后台配置订阅事件的方式
订阅方式有两种,第一种是官方推荐的,无需回调url地址,通过api的方式和飞书建立长连接(处理事件 - 服务端 API - 开发文档 - 飞书开放平台);第二种是将事件发送至 开发者服务器,需要配置开发者服务器地址。
添加订阅的事件
点击添加事件,勾选所需要监听的事件
勾选完,点击确认添加,之后需要重新发布应用才能生效
订阅需要监听的审批定义
在应用后台订阅审批事件后,仍需要再次通过审批开放接口订阅指定的审批定义,才会收到审批事件,参考文档如下
订阅审批事件 - 服务端 API - 开发文档 - 飞书开放平台
3.3.5 查看OA审批详情
开启一个流程审批之后,如何能够查看到这个流程的审批详情(审批进度)呢,飞书也提供了相应的对接流程,文档地址:打开飞书审批 - 开发指南 - 飞书开放平台
现在以我们上文定义的那个审批流程为例进行说明,详细的可以参考上面的链接文档,这里以PC端说明,只需要拼接一个完整的 url 链接,然后按照要求将参数传入到url中即可。完整的预览链接如下:
https://applink.feishu.cn/client/mini_program/open?mode=appCenter&appId=cli_XXX&path=pc%2Fpages%2Fin-process%2Findex%3FinstanceId%3DAD66D295-B79A-4338-A32E-835CE7BC0840
在实际使用的时候,只需要将你启动一个流程审批实例之后,接口返回的实例ID替换到上面这个url中最后那个参数即可,url中其他的地方均保持不变;
下面启动一个流程,拿到流程实例ID
拼接完整的预览流程详情的url:
https://applink.feishu.cn/client/mini_program/open?mode=appCenter&appId=cli_XXX&path=pc%2Fpages%2Fin-process%2Findex%3FinstanceId%3DAD66D295-B79A-4338-A32E-835CE7BC0840
浏览器打开这个链接
打开飞书,然后跳转到如下界面,即可看到当前的流程审批详情
四、写在文末
本文通过较大的篇幅详细介绍了飞书的审批流的对接和使用,实际在对接和使用过程中还会有一些自身业务的定制化问题需要注意,有兴趣的同学可以进一步深入研究,本篇到此结束,感谢观看。