irpas技术客

飞书开放平台Java-Sdk_阿里加多

网络 3922

为简化开发者接入飞书开放平台的操作步骤,我们提供了服务端 SDK,开发者可使用 SDK,快捷地开发功能。

安装

运行环境:JDK 1.8及以上

最新版本 maven 坐标

<dependency> <groupId>com.larksuite.oapi</groupId> <artifactId>oapi-sdk</artifactId> <version>2.0.2-rc7</version> </dependency> API Client

开发者在调用 API 前,需要先创建一个 API Client,然后才可以基于 API Client 发起 API 调用。

创建API Client

对于自建应用,可使用下面代码来创建一个 API Client

// 默认配置为自建应用 Client client=Client.newBuilder("appId","appSecret").build();

对于商店应用,需在创建 API Client 时,使用 marketplaceApp() 方法指定 AppType 为商店应用

Client client = Client.newBuilder("appId", "appSecret") .marketplaceApp() // 设置App为商店应用 .build(); 配置API Client

创建 API Client 时,可对 API Client 进行一定的配置,比如我们可以在创建 API Client 时设置日志级别、设置 http 请求超时时间等等:

Client client=Client.newBuilder("appId","appSecret") .marketplaceApp() // 设置 app 类型为商店应用 .openBaseUrl(BaseUrlEnum.FeiShu) // 设置域名,默认为飞书 .helpDeskCredential("helpDeskId","helpDeskSecret") // 服务台应用才需要设置 .requestTimeout(3,TimeUnit.SECONDS) // 设置httpclient 超时时间,默认永不超时 .disableTokenCache() // 禁用token管理,禁用后需要开发者自己传递token .logReqAtDebug(true) // 在 debug 模式下会打印 http 请求和响应的 headers,body 等信息。 .build();

每个配置选项的具体含义,如下表格:??

API调用

创建完毕 API Client,我们可以使用?Client.业务域.资源.方法名称?来定位具体的 API 方法,然后对具体的 API 发起调用。

飞书开放平台开放的所有 API 列表,可点击这里查看

基本用法

如下示例我们通过 client 调用文档业务的 Create 方法,创建一个文档:

import com.lark.oapi.Client; import com.lark.oapi.core.utils.Jsons; import com.lark.oapi.service.docx.v1.model.CreateDocumentReq; import com.lark.oapi.service.docx.v1.model.CreateDocumentReqBody; import com.lark.oapi.service.docx.v1.model.CreateDocumentResp; public class DocxSample { public static void main(String arg[]) throws Exception { // 构建client Client client = Client.newBuilder("appId", "appSecret").build(); // 发起请求 CreateDocumentResp resp = client.docx().document() .create(CreateDocumentReq.newBuilder() .createDocumentReqBody(CreateDocumentReqBody.newBuilder() .title("title") .folderToken("fldcniHf40Vcv1DoEc8SXeuA0Zd") .build()) .build() ); // 处理服务端错误 if (!resp.success()) { System.out.println(String.format("code:%s,msg:%s,reqId:%s" , resp.getCode(), resp.getMsg(), resp.getRequestId())); return; } // 业务数据处理 System.out.println(Jsons.DEFAULT.toJson(resp.getData())); } }

更多 API 调用示例:ImSample.java

设置请求选项

开发者在每次发起 API 调用时,可以设置请求级别的一些参数,比如传递 userAccessToken ,自定义 headers 等:

import com.lark.oapi.Client; import com.lark.oapi.core.request.RequestOptions; import com.lark.oapi.core.utils.Jsons; import com.lark.oapi.core.utils.Lists; import com.lark.oapi.service.docx.v1.model.CreateDocumentReq; import com.lark.oapi.service.docx.v1.model.CreateDocumentReqBody; import com.lark.oapi.service.docx.v1.model.CreateDocumentResp; import java.util.HashMap; import java.util.List; import java.util.Map; public class DocxSample { public static void main(String arg[]) throws Exception { // 构建client Client client = Client.newBuilder("appId", "appSecret").build(); // 创建自定义 Headers Map<String, List<String>> headers = new HashMap<>(); headers.put("key1", Lists.newArrayList("value1")); headers.put("key2", Lists.newArrayList("value2")); // 发起请求 CreateDocumentResp resp = client.docx().document() .create(CreateDocumentReq.newBuilder() .createDocumentReqBody(CreateDocumentReqBody.newBuilder() .title("title") .folderToken("fldcniHf40Vcv1DoEc8SXeuA0Zd") .build()) .build() , RequestOptions.newBuilder() .userAccessToken("u-2GxFH7ysh8E9lj9UJp8XAG0k0gh1h5KzM800khEw2G6e") // 传递用户token .headers(headers) // 传递自定义 Headers .build()); // 处理服务端错误 if (!resp.success()) { System.out.println(String.format("code:%s,msg:%s,reqId:%s" , resp.getCode(), resp.getMsg(), resp.getRequestId())); return; } // 业务数据处理 System.out.println(Jsons.DEFAULT.toJson(resp.getData())); } }

如上使用 RequestOptions 的 Builder 模式构建请求级别的参数。如下表格,展示了所有请求级别可设置的选项:?

原生API调用方式

有些老版本的开放接口,不能生成结构化的 API, 导致 SDK 内无法提供结构化的使用方式,这时可使用原生模式进行调用:

package com.lark.oapi.sample.rawapi; import com.lark.oapi.Client; import com.lark.oapi.core.enums.AppType; import com.lark.oapi.core.response.RawResponse; import com.lark.oapi.core.token.AccessTokenType; import com.lark.oapi.core.utils.Jsons; import java.util.HashMap; import java.util.Map; /** * 原生http 调用方式 */ public class RawApiCall { public static void main(String arg[]) throws Exception { // 构建client Client client = Client.newBuilder("appId", "appSecret").build(); // 构建http body Map<String, Object> body = new HashMap<>(); body.put("receive_id", "ou_c245b0a7dff2725cfa2fb104f8b48b9d"); body.put("content", MessageText.newBuilder() .atUser("ou_155184d1e73cbfb8973e5a9e698e74f2", "Tom") .text("test content") .build()); body.put("msg_type", MsgTypeEnum.MSG_TYPE_TEXT); // 发起请求 RawResponse resp = client.post( "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id" , body , AccessTokenType.Tenant); // 处理结果 System.out.println(resp.getStatusCode()); System.out.println(Jsons.DEFAULT.toJson(resp.getHeaders())); System.out.println(new String(resp.getBody())); System.out.println(resp.getRequestID()); } }

更多 API 调用示例:RawApiCall.java

处理消息事件回调

关于消息订阅相关的知识,可以点击这里查看

飞书开放平台开放的所有事件列表,可点击这里查看

概要

要处理消息事件,开发者需要启动一个 Web 服务,然后把 Web 服务的 URL 注册到飞书开放平台。飞书开放平台则把事件推送到开发者配置的 URL地址。

在 Java 中,比如常见的 Tomcat 容器、Jboss 容器是基于 Servlet 技术栈实现的; 为方便开发者集成这两种常用的 Web 技术栈实现的 Web 服务,飞书开放平台提供了集成方案。

集成 Servlet 容器

本节我们介绍,如何集成基于 Servlet 技术栈实现的 SpringBoot Web 框架。

安装集成包

要想把 SDK 集成已有 SpringBoot 框架,开发者需要引入集成包?oapi-sdk-java-ext

需在项目 pom 文件中引入下面 maven 坐标

<dependency> <artifactId>oapi-sdk-servlet-ext</artifactId> <groupId>com.larksuite.oapi</groupId> <version>1.0.0-rc2</version> <exclusions> <exclusion> <artifactId>oapi-sdk</artifactId> <groupId>com.larksuite.oapi</groupId> </exclusion> </exclusions> </dependency> 集成示例

注入 ServletAdapter 实例到 IOC 容器

import com.lark.oapi.sdk.servlet.ext.ServletAdapter; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; @SpringBootApplication public class AppStartup { public static void main(String[] args) { SpringApplication.run(AppStartup.class, args); } // 注入扩展实例到 IOC 容器 @Bean public ServletAdapter getServletAdapter() { return new ServletAdapter(); } }

编写 Controller 注册事件处理器

import com.lark.oapi.core.utils.Jsons; import com.lark.oapi.event.EventDispatcher; import com.lark.oapi.service.contact.v3.ContactService; import com.lark.oapi.service.contact.v3.model.P2UserCreatedV3; import com.lark.oapi.service.im.v1.ImService; import com.lark.oapi.service.im.v1.model.P1MessageReadV1; import com.lark.oapi.service.im.v1.model.P2MessageReadV1; import com.lark.oapi.service.im.v1.model.P2MessageReceiveV1; import com.lark.oapi.sdk.servlet.ext.ServletAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class EventController { //1. 注册消息处理器 private final EventDispatcher EVENT_DISPATCHER = EventDispatcher.newBuilder("verificationToken", "encryptKey") .onP2MessageReceiveV1(new ImService.P2MessageReceiveV1Handler() { @Override public void handle(P2MessageReceiveV1 event) { System.out.println(Jsons.DEFAULT.toJson(event)); System.out.println(event.getRequestId()); } }).onP2UserCreatedV3(new ContactService.P2UserCreatedV3Handler() { @Override public void handle(P2UserCreatedV3 event) { System.out.println(Jsons.DEFAULT.toJson(event)); System.out.println(event.getRequestId()); } }) .onP2MessageReadV1(new ImService.P2MessageReadV1Handler() { @Override public void handle(P2MessageReadV1 event) { System.out.println(Jsons.DEFAULT.toJson(event)); System.out.println(event.getRequestId()); } }).onP1MessageReadV1(new ImService.P1MessageReadV1Handler() { @Override public void handle(P1MessageReadV1 event) { System.out.println(Jsons.DEFAULT.toJson(event)); System.out.println(event.getRequestId()); } }) .build(); //2. 注入 ServletAdapter 实例 @Autowired private ServletAdapter servletAdapter; //3. 创建路由处理器 @RequestMapping("/webhook/event") public void event(HttpServletRequest request, HttpServletResponse response) throws Throwable { //3.1 回调扩展包提供的事件回调处理器 servletAdapter.handleEvent(request, response, EVENT_DISPATCHER); } }

其中 EventDispatcher.newBuilder 方法的参数用于签名验证和消息解密使用,默认可以传递为空串;但是如果开发者的应用在?控制台?的【事件订阅】里面开启了加密,则必须传递控制台上提供的值。

需要注意的是注册处理器时,比如使用 onP2MessageReceiveV1 注册接受消息事件回调时,其中的P2为消息协议版本,当前飞书开放平台存在?两种消息协议?,分别为1.0和2.0。

如下图开发者在注册消息处理器时,需从?事件列表?中查看自己需要的是哪种协议的事件。 如果是1.0的消息协议,则注册处理器时,需要找以onP1xxxx开头的。如果是2.0的消息协议,则注册处理器时,需要找以OnP2xxxx开头的。

更多事件订阅示例:event.java

消息处理器内给对应租户发消息

针对 ISV 开发者,如果想在消息处理器内给对应租户的用户发送消息,则需先从消息事件内获取租户 key,然后使用下面方式调用消息 API 进行消息发送:

package com.lark.oapi.sample.event; import com.lark.oapi.core.request.RequestOptions; import com.lark.oapi.core.utils.Jsons; import com.lark.oapi.event.EventDispatcher; import com.lark.oapi.service.im.v1.ImService.P2MessageReceiveV1Handler; import com.lark.oapi.service.im.v1.enums.ReceiveIdTypeEnum; import com.lark.oapi.service.im.v1.model.CreateMessageReq; import com.lark.oapi.service.im.v1.model.CreateMessageReqBody; import com.lark.oapi.service.im.v1.model.P2MessageReceiveV1; import com.lark.oapi.sdk.servlet.ext.ServletAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class EventController { //1. 注册消息处理器 private final EventDispatcher EVENT_DISPATCHER = EventDispatcher.newBuilder("", "") .onP2MessageReceiveV1(new P2MessageReceiveV1Handler() { @Override public void handle(P2MessageReceiveV1 event) throws Exception { // 处理消息 System.out.println(Jsons.DEFAULT.toJson(event)); System.out.println(event.getRequestId()); // 获取租户 key String tenantKey = event.getTenantKey(); // 发送请求 client.im().message().create(CreateMessageReq.newBuilder() .receiveIdType(ReceiveIdTypeEnum.OPEN_ID) .createMessageReqBody(CreateMessageReqBody.newBuilder() .content("text") .build()) .build() , RequestOptions.newBuilder() .tenantKey(tenantKey) .build()); } }).build(); //2. 注入 ServletAdapter 实例 @Autowired private ServletAdapter servletAdapter; //3. 创建路由处理器 @RequestMapping("/webhook/event") public void event(HttpServletRequest request, HttpServletResponse response) throws Throwable { //3.1 回调扩展包提供的事件回调处理器 servletAdapter.handleEvent(request, response, EVENT_DISPATCHER); } }

更多事件订阅示例:event.java

处理卡片行为回调

关于卡片行为相关的知识,可点击这里查看

集成 Servlet 容器

本节我们介绍,如何集成基于 Servlet 技术栈实现的 SpringBoot Web框架。

安装集成包

需在项目 pom 文件中引入下面 maven 坐标

<dependency> <artifactId>oapi-sdk-servlet-ext</artifactId> <groupId>com.larksuite.oapi</groupId> <version>1.0.0-rc2</version> <exclusions> <exclusion> <artifactId>oapi-sdk</artifactId> <groupId>com.larksuite.oapi</groupId> </exclusion> </exclusions> </dependency> 集成示例

注入 ServletAdapter 实例到 IOC 容器

import com.lark.oapi.sdk.servlet.ext.ServletAdapter; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; @SpringBootApplication public class AppStartup { public static void main(String[] args) { SpringApplication.run(AppStartup.class, args); } // 注入扩展实例到 IOC 容器 @Bean public ServletAdapter getServletAdapter() { return new ServletAdapter(); } }

编写 Controller 注册卡片行为处理器

import com.lark.oapi.card.CardActionHandler; import com.lark.oapi.card.model.CardAction; import com.lark.oapi.core.utils.Jsons; import com.lark.oapi.sdk.servlet.ext.ServletAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class CardActionController { //1. 注册卡片处理器 private final CardActionHandler CARD_ACTION_HANDLER = CardActionHandler.newBuilder("v", "e", new CardActionHandler.ICardHandler() { @Override public Object handle(CardAction cardAction) { System.out.println(Jsons.DEFAULT.toJson(cardAction)); System.out.println(cardAction.getRequestId()); return null; } }).build(); // 2. 注入 ServletAdapter 示例 @Autowired private ServletAdapter servletAdapter; //3. 注册服务路由 @RequestMapping("/webhook/card") public void card(HttpServletRequest request, HttpServletResponse response) throws Throwable { //3.1 回调扩展包卡片行为处理回调 servletAdapter.handleCardAction(request, response, CARD_ACTION_HANDLER); } }

如上示例,如果不需要处理器内返回业务结果给飞书服务端,则直接在处理器内返回 null 。

更多卡片行为示例:CardActionController.java

返回卡片消息

如开发者需要卡片处理器内同步返回用于更新消息卡片的消息体,则可使用下面方法方式进行处理:

import com.lark.oapi.card.CardActionHandler; import com.lark.oapi.card.model.CardAction; import com.lark.oapi.card.model.MessageCard; import com.lark.oapi.card.model.MessageCardElement; import com.lark.oapi.core.utils.Jsons; import com.lark.oapi.sdk.servlet.ext.ServletAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class CardActionController { //1. 注册卡片处理器 private final CardActionHandler CARD_ACTION_HANDLER = CardActionHandler.newBuilder("v", "e", new CardActionHandler.ICardHandler() { @Override public Object handle(CardAction cardAction) { // 1.1 处理卡片行为 System.out.println(Jsons.DEFAULT.toJson(cardAction)); System.out.println(cardAction.getRequestId()); // 1.2 构建响应卡片内容 MessageCard card = MessageCard.newBuilder() .cardLink(cardURL) .config(config) .header(header) .elements(new MessageCardElement[]{div, note, image, cardAction, hr}) .build(); return card; } }).build(); // 2. 注入 ServletAdapter 示例 @Autowired private ServletAdapter servletAdapter; //3. 注册服务路由 @RequestMapping("/webhook/card") public void card(HttpServletRequest request, HttpServletResponse response) throws Throwable { //3.1 回调扩展包卡片行为处理回调 servletAdapter.handleCardAction(request, response, CARD_ACTION_HANDLER); } }

更多卡片行为示例:CardActionController.java

返回自定义消息

如开发者需卡片处理器内返回自定义内容,则可以使用下面方式进行处理:

import com.lark.oapi.card.CardActionHandler; import com.lark.oapi.card.model.CardAction; import com.lark.oapi.card.model.CustomResponse; import com.lark.oapi.core.utils.Jsons; import com.lark.oapi.sdk.servlet.ext.ServletAdapter; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class CardActionController { //1. 注册卡片处理器 private final CardActionHandler CARD_ACTION_HANDLER = CardActionHandler.newBuilder("v", "e", new CardActionHandler.ICardHandler() { @Override public Object handle(CardAction cardAction) { // 1.1 处理卡片行为 System.out.println(Jsons.DEFAULT.toJson(cardAction)); System.out.println(cardAction.getRequestId()); //1.2 返回自定义结果 Map<String, Object> map = new HashMap<>(); map.put("key1", "value1"); map.put("ke2", "value2"); CustomResponse customResponse = new CustomResponse(); customResponse.setStatusCode(0); customResponse.setBody(map); Map<String, List<String>> headers = new HashMap<String, List<String>>(); headers.put("key1", Arrays.asList("a", "b")); headers.put("key2", Arrays.asList("c", "d")); customResponse.setHeaders(headers); return customResponse; } }).build(); // 2. 注入 ServletAdapter 示例 @Autowired private ServletAdapter servletAdapter; //3. 注册服务路由 @RequestMapping("/webhook/card") public void card(HttpServletRequest request, HttpServletResponse response) throws Throwable { //3.1 回调扩展包卡片行为处理回调 servletAdapter.handleCardAction(request, response, CARD_ACTION_HANDLER); } }

更多卡片行为示例:CardActionController.java

卡片行为处理器内给对应租户发消息

针对 ISV 开发者,如果想在卡片行为处理器内给对应租户的用户发送消息,则需先从卡片行为内获取租户 key ,然后使用下面方式调用消息 API 进行消息发送:

import com.lark.oapi.card.CardActionHandler; import com.lark.oapi.card.model.CardAction; import com.lark.oapi.card.model.CustomResponse; import com.lark.oapi.core.utils.Jsons; import com.lark.oapi.sdk.servlet.ext.ServletAdapter; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class CardActionController { //1. 注册卡片处理器 private final CardActionHandler CARD_ACTION_HANDLER = CardActionHandler.newBuilder("v", "e", new CardActionHandler.ICardHandler() { @Override public Object handle(CardAction cardAction) { // 1.1 处理卡片行为 System.out.println(Jsons.DEFAULT.toJson(cardAction)); System.out.println(cardAction.getRequestId()); // 1.2 获取租户 key String tenantKey = cardAction.getTenantKey(); // 发送请求 client.im().message().create(CreateMessageReq.newBuilder() .receiveIdType(ReceiveIdTypeEnum.OPEN_ID) .createMessageReqBody(CreateMessageReqBody.newBuilder() .content("text") .build()) .build() , RequestOptions.newBuilder() .tenantKey(tenantKey) .build()); return null; } }).build(); // 2. 注入 ServletAdapter 示例 @Autowired private ServletAdapter servletAdapter; //3. 注册服务路由 @RequestMapping("/webhook/card") public void card(HttpServletRequest request, HttpServletResponse response) throws Throwable { //3.1 回调扩展包卡片行为处理回调 servletAdapter.handleCardAction(request, response, CARD_ACTION_HANDLER); } }

更多卡片行为示例:CardActionController.java

github地址

https://github.com/larksuite/oapi-sdk-java


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #飞书sdk #SDK开发者可使用 #SDK快捷地开发功能 #安装运行环境JDK #18及以上最新版本 #Maven