• 飞书开放平台Java-Sdk


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

    安装

    • 运行环境:JDK 1.8及以上

    • 最新版本 maven 坐标

    1. com.larksuite.oapi
    2. oapi-sdk
    3. 2.0.2-rc7

    API Client

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

    创建API Client

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

    1. // 默认配置为自建应用
    2. Client client=Client.newBuilder("appId","appSecret").build();
    • 对于商店应用,需在创建 API Client 时,使用 marketplaceApp() 方法指定 AppType 为商店应用

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

    配置API Client

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

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

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

    4dae4d77aed0511cb2565387bd92531c.png

    8c6727e97ba94af09b637025003f9751.png

    API调用

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

    0a8a6d014fd1e4723a13f84216946608.png

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

    基本用法

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

    1. import com.lark.oapi.Client;
    2. import com.lark.oapi.core.utils.Jsons;
    3. import com.lark.oapi.service.docx.v1.model.CreateDocumentReq;
    4. import com.lark.oapi.service.docx.v1.model.CreateDocumentReqBody;
    5. import com.lark.oapi.service.docx.v1.model.CreateDocumentResp;
    6. public class DocxSample {
    7. public static void main(String arg[]) throws Exception {
    8. // 构建client
    9. Client client = Client.newBuilder("appId", "appSecret").build();
    10. // 发起请求
    11. CreateDocumentResp resp = client.docx().document()
    12. .create(CreateDocumentReq.newBuilder()
    13. .createDocumentReqBody(CreateDocumentReqBody.newBuilder()
    14. .title("title")
    15. .folderToken("fldcniHf40Vcv1DoEc8SXeuA0Zd")
    16. .build())
    17. .build()
    18. );
    19. // 处理服务端错误
    20. if (!resp.success()) {
    21. System.out.println(String.format("code:%s,msg:%s,reqId:%s"
    22. , resp.getCode(), resp.getMsg(), resp.getRequestId()));
    23. return;
    24. }
    25. // 业务数据处理
    26. System.out.println(Jsons.DEFAULT.toJson(resp.getData()));
    27. }
    28. }

    更多 API 调用示例:ImSample.java

    设置请求选项

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

    1. import com.lark.oapi.Client;
    2. import com.lark.oapi.core.request.RequestOptions;
    3. import com.lark.oapi.core.utils.Jsons;
    4. import com.lark.oapi.core.utils.Lists;
    5. import com.lark.oapi.service.docx.v1.model.CreateDocumentReq;
    6. import com.lark.oapi.service.docx.v1.model.CreateDocumentReqBody;
    7. import com.lark.oapi.service.docx.v1.model.CreateDocumentResp;
    8. import java.util.HashMap;
    9. import java.util.List;
    10. import java.util.Map;
    11. public class DocxSample {
    12. public static void main(String arg[]) throws Exception {
    13. // 构建client
    14. Client client = Client.newBuilder("appId", "appSecret").build();
    15. // 创建自定义 Headers
    16. Map> headers = new HashMap<>();
    17. headers.put("key1", Lists.newArrayList("value1"));
    18. headers.put("key2", Lists.newArrayList("value2"));
    19. // 发起请求
    20. CreateDocumentResp resp = client.docx().document()
    21. .create(CreateDocumentReq.newBuilder()
    22. .createDocumentReqBody(CreateDocumentReqBody.newBuilder()
    23. .title("title")
    24. .folderToken("fldcniHf40Vcv1DoEc8SXeuA0Zd")
    25. .build())
    26. .build()
    27. , RequestOptions.newBuilder()
    28. .userAccessToken("u-2GxFH7ysh8E9lj9UJp8XAG0k0gh1h5KzM800khEw2G6e") // 传递用户token
    29. .headers(headers) // 传递自定义 Headers
    30. .build());
    31. // 处理服务端错误
    32. if (!resp.success()) {
    33. System.out.println(String.format("code:%s,msg:%s,reqId:%s"
    34. , resp.getCode(), resp.getMsg(), resp.getRequestId()));
    35. return;
    36. }
    37. // 业务数据处理
    38. System.out.println(Jsons.DEFAULT.toJson(resp.getData()));
    39. }
    40. }

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

    f32135b2038613ec9c9fb6b26ad46fa0.png

    原生API调用方式

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

    1. package com.lark.oapi.sample.rawapi;
    2. import com.lark.oapi.Client;
    3. import com.lark.oapi.core.enums.AppType;
    4. import com.lark.oapi.core.response.RawResponse;
    5. import com.lark.oapi.core.token.AccessTokenType;
    6. import com.lark.oapi.core.utils.Jsons;
    7. import java.util.HashMap;
    8. import java.util.Map;
    9. /**
    10. * 原生http 调用方式
    11. */
    12. public class RawApiCall {
    13. public static void main(String arg[]) throws Exception {
    14. // 构建client
    15. Client client = Client.newBuilder("appId", "appSecret").build();
    16. // 构建http body
    17. Map body = new HashMap<>();
    18. body.put("receive_id", "ou_c245b0a7dff2725cfa2fb104f8b48b9d");
    19. body.put("content", MessageText.newBuilder()
    20. .atUser("ou_155184d1e73cbfb8973e5a9e698e74f2", "Tom")
    21. .text("test content")
    22. .build());
    23. body.put("msg_type", MsgTypeEnum.MSG_TYPE_TEXT);
    24. // 发起请求
    25. RawResponse resp = client.post(
    26. "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id"
    27. , body
    28. , AccessTokenType.Tenant);
    29. // 处理结果
    30. System.out.println(resp.getStatusCode());
    31. System.out.println(Jsons.DEFAULT.toJson(resp.getHeaders()));
    32. System.out.println(new String(resp.getBody()));
    33. System.out.println(resp.getRequestID());
    34. }
    35. }

    更多 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 坐标

    1. oapi-sdk-servlet-ext
    2. com.larksuite.oapi
    3. 1.0.0-rc2
    4. oapi-sdk
    5. com.larksuite.oapi
    集成示例
    • 注入 ServletAdapter 实例到 IOC 容器

    1. import com.lark.oapi.sdk.servlet.ext.ServletAdapter;
    2. import org.springframework.boot.SpringApplication;
    3. import org.springframework.boot.autoconfigure.SpringBootApplication;
    4. import org.springframework.context.annotation.Bean;
    5. @SpringBootApplication
    6. public class AppStartup {
    7. public static void main(String[] args) {
    8. SpringApplication.run(AppStartup.class, args);
    9. }
    10. // 注入扩展实例到 IOC 容器
    11. @Bean
    12. public ServletAdapter getServletAdapter() {
    13. return new ServletAdapter();
    14. }
    15. }
    • 编写 Controller 注册事件处理器

    1. import com.lark.oapi.core.utils.Jsons;
    2. import com.lark.oapi.event.EventDispatcher;
    3. import com.lark.oapi.service.contact.v3.ContactService;
    4. import com.lark.oapi.service.contact.v3.model.P2UserCreatedV3;
    5. import com.lark.oapi.service.im.v1.ImService;
    6. import com.lark.oapi.service.im.v1.model.P1MessageReadV1;
    7. import com.lark.oapi.service.im.v1.model.P2MessageReadV1;
    8. import com.lark.oapi.service.im.v1.model.P2MessageReceiveV1;
    9. import com.lark.oapi.sdk.servlet.ext.ServletAdapter;
    10. import javax.servlet.http.HttpServletRequest;
    11. import javax.servlet.http.HttpServletResponse;
    12. import org.springframework.beans.factory.annotation.Autowired;
    13. import org.springframework.web.bind.annotation.RequestMapping;
    14. import org.springframework.web.bind.annotation.RestController;
    15. @RestController
    16. public class EventController {
    17. //1. 注册消息处理器
    18. private final EventDispatcher EVENT_DISPATCHER = EventDispatcher.newBuilder("verificationToken",
    19. "encryptKey")
    20. .onP2MessageReceiveV1(new ImService.P2MessageReceiveV1Handler() {
    21. @Override
    22. public void handle(P2MessageReceiveV1 event) {
    23. System.out.println(Jsons.DEFAULT.toJson(event));
    24. System.out.println(event.getRequestId());
    25. }
    26. }).onP2UserCreatedV3(new ContactService.P2UserCreatedV3Handler() {
    27. @Override
    28. public void handle(P2UserCreatedV3 event) {
    29. System.out.println(Jsons.DEFAULT.toJson(event));
    30. System.out.println(event.getRequestId());
    31. }
    32. })
    33. .onP2MessageReadV1(new ImService.P2MessageReadV1Handler() {
    34. @Override
    35. public void handle(P2MessageReadV1 event) {
    36. System.out.println(Jsons.DEFAULT.toJson(event));
    37. System.out.println(event.getRequestId());
    38. }
    39. }).onP1MessageReadV1(new ImService.P1MessageReadV1Handler() {
    40. @Override
    41. public void handle(P1MessageReadV1 event) {
    42. System.out.println(Jsons.DEFAULT.toJson(event));
    43. System.out.println(event.getRequestId());
    44. }
    45. })
    46. .build();
    47. //2. 注入 ServletAdapter 实例
    48. @Autowired
    49. private ServletAdapter servletAdapter;
    50. //3. 创建路由处理器
    51. @RequestMapping("/webhook/event")
    52. public void event(HttpServletRequest request, HttpServletResponse response)
    53. throws Throwable {
    54. //3.1 回调扩展包提供的事件回调处理器
    55. servletAdapter.handleEvent(request, response, EVENT_DISPATCHER);
    56. }
    57. }

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

    4ad6741ad93218ca6fb299b2a3c097ba.png

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

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

    29e6dbfe26410853a9017163a4112fe1.png

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

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

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

    1. package com.lark.oapi.sample.event;
    2. import com.lark.oapi.core.request.RequestOptions;
    3. import com.lark.oapi.core.utils.Jsons;
    4. import com.lark.oapi.event.EventDispatcher;
    5. import com.lark.oapi.service.im.v1.ImService.P2MessageReceiveV1Handler;
    6. import com.lark.oapi.service.im.v1.enums.ReceiveIdTypeEnum;
    7. import com.lark.oapi.service.im.v1.model.CreateMessageReq;
    8. import com.lark.oapi.service.im.v1.model.CreateMessageReqBody;
    9. import com.lark.oapi.service.im.v1.model.P2MessageReceiveV1;
    10. import com.lark.oapi.sdk.servlet.ext.ServletAdapter;
    11. import javax.servlet.http.HttpServletRequest;
    12. import javax.servlet.http.HttpServletResponse;
    13. import org.springframework.beans.factory.annotation.Autowired;
    14. import org.springframework.web.bind.annotation.RequestMapping;
    15. import org.springframework.web.bind.annotation.RestController;
    16. @RestController
    17. public class EventController {
    18. //1. 注册消息处理器
    19. private final EventDispatcher EVENT_DISPATCHER = EventDispatcher.newBuilder("", "")
    20. .onP2MessageReceiveV1(new P2MessageReceiveV1Handler() {
    21. @Override
    22. public void handle(P2MessageReceiveV1 event) throws Exception {
    23. // 处理消息
    24. System.out.println(Jsons.DEFAULT.toJson(event));
    25. System.out.println(event.getRequestId());
    26. // 获取租户 key
    27. String tenantKey = event.getTenantKey();
    28. // 发送请求
    29. client.im().message().create(CreateMessageReq.newBuilder()
    30. .receiveIdType(ReceiveIdTypeEnum.OPEN_ID)
    31. .createMessageReqBody(CreateMessageReqBody.newBuilder()
    32. .content("text")
    33. .build())
    34. .build()
    35. , RequestOptions.newBuilder()
    36. .tenantKey(tenantKey)
    37. .build());
    38. }
    39. }).build();
    40. //2. 注入 ServletAdapter 实例
    41. @Autowired
    42. private ServletAdapter servletAdapter;
    43. //3. 创建路由处理器
    44. @RequestMapping("/webhook/event")
    45. public void event(HttpServletRequest request, HttpServletResponse response)
    46. throws Throwable {
    47. //3.1 回调扩展包提供的事件回调处理器
    48. servletAdapter.handleEvent(request, response, EVENT_DISPATCHER);
    49. }
    50. }

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

    处理卡片行为回调

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

    集成 Servlet 容器

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

    安装集成包

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

    1. oapi-sdk-servlet-ext
    2. com.larksuite.oapi
    3. 1.0.0-rc2
    4. oapi-sdk
    5. com.larksuite.oapi
    集成示例
    • 注入 ServletAdapter 实例到 IOC 容器

    1. import com.lark.oapi.sdk.servlet.ext.ServletAdapter;
    2. import org.springframework.boot.SpringApplication;
    3. import org.springframework.boot.autoconfigure.SpringBootApplication;
    4. import org.springframework.context.annotation.Bean;
    5. @SpringBootApplication
    6. public class AppStartup {
    7. public static void main(String[] args) {
    8. SpringApplication.run(AppStartup.class, args);
    9. }
    10. // 注入扩展实例到 IOC 容器
    11. @Bean
    12. public ServletAdapter getServletAdapter() {
    13. return new ServletAdapter();
    14. }
    15. }
    • 编写 Controller 注册卡片行为处理器

    1. import com.lark.oapi.card.CardActionHandler;
    2. import com.lark.oapi.card.model.CardAction;
    3. import com.lark.oapi.core.utils.Jsons;
    4. import com.lark.oapi.sdk.servlet.ext.ServletAdapter;
    5. import javax.servlet.http.HttpServletRequest;
    6. import javax.servlet.http.HttpServletResponse;
    7. import org.springframework.beans.factory.annotation.Autowired;
    8. import org.springframework.web.bind.annotation.RequestMapping;
    9. import org.springframework.web.bind.annotation.RestController;
    10. @RestController
    11. public class CardActionController {
    12. //1. 注册卡片处理器
    13. private final CardActionHandler CARD_ACTION_HANDLER = CardActionHandler.newBuilder("v", "e",
    14. new CardActionHandler.ICardHandler() {
    15. @Override
    16. public Object handle(CardAction cardAction) {
    17. System.out.println(Jsons.DEFAULT.toJson(cardAction));
    18. System.out.println(cardAction.getRequestId());
    19. return null;
    20. }
    21. }).build();
    22. // 2. 注入 ServletAdapter 示例
    23. @Autowired
    24. private ServletAdapter servletAdapter;
    25. //3. 注册服务路由
    26. @RequestMapping("/webhook/card")
    27. public void card(HttpServletRequest request, HttpServletResponse response)
    28. throws Throwable {
    29. //3.1 回调扩展包卡片行为处理回调
    30. servletAdapter.handleCardAction(request, response, CARD_ACTION_HANDLER);
    31. }
    32. }

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

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

    返回卡片消息

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

    1. import com.lark.oapi.card.CardActionHandler;
    2. import com.lark.oapi.card.model.CardAction;
    3. import com.lark.oapi.card.model.MessageCard;
    4. import com.lark.oapi.card.model.MessageCardElement;
    5. import com.lark.oapi.core.utils.Jsons;
    6. import com.lark.oapi.sdk.servlet.ext.ServletAdapter;
    7. import javax.servlet.http.HttpServletRequest;
    8. import javax.servlet.http.HttpServletResponse;
    9. import org.springframework.beans.factory.annotation.Autowired;
    10. import org.springframework.web.bind.annotation.RequestMapping;
    11. import org.springframework.web.bind.annotation.RestController;
    12. @RestController
    13. public class CardActionController {
    14. //1. 注册卡片处理器
    15. private final CardActionHandler CARD_ACTION_HANDLER = CardActionHandler.newBuilder("v", "e",
    16. new CardActionHandler.ICardHandler() {
    17. @Override
    18. public Object handle(CardAction cardAction) {
    19. // 1.1 处理卡片行为
    20. System.out.println(Jsons.DEFAULT.toJson(cardAction));
    21. System.out.println(cardAction.getRequestId());
    22. // 1.2 构建响应卡片内容
    23. MessageCard card = MessageCard.newBuilder()
    24. .cardLink(cardURL)
    25. .config(config)
    26. .header(header)
    27. .elements(new MessageCardElement[]{div, note, image, cardAction, hr})
    28. .build();
    29. return card;
    30. }
    31. }).build();
    32. // 2. 注入 ServletAdapter 示例
    33. @Autowired
    34. private ServletAdapter servletAdapter;
    35. //3. 注册服务路由
    36. @RequestMapping("/webhook/card")
    37. public void card(HttpServletRequest request, HttpServletResponse response)
    38. throws Throwable {
    39. //3.1 回调扩展包卡片行为处理回调
    40. servletAdapter.handleCardAction(request, response, CARD_ACTION_HANDLER);
    41. }
    42. }

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

    返回自定义消息

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

    1. import com.lark.oapi.card.CardActionHandler;
    2. import com.lark.oapi.card.model.CardAction;
    3. import com.lark.oapi.card.model.CustomResponse;
    4. import com.lark.oapi.core.utils.Jsons;
    5. import com.lark.oapi.sdk.servlet.ext.ServletAdapter;
    6. import java.util.Arrays;
    7. import java.util.HashMap;
    8. import java.util.List;
    9. import java.util.Map;
    10. import javax.servlet.http.HttpServletRequest;
    11. import javax.servlet.http.HttpServletResponse;
    12. import org.springframework.beans.factory.annotation.Autowired;
    13. import org.springframework.web.bind.annotation.RequestMapping;
    14. import org.springframework.web.bind.annotation.RestController;
    15. @RestController
    16. public class CardActionController {
    17. //1. 注册卡片处理器
    18. private final CardActionHandler CARD_ACTION_HANDLER = CardActionHandler.newBuilder("v", "e",
    19. new CardActionHandler.ICardHandler() {
    20. @Override
    21. public Object handle(CardAction cardAction) {
    22. // 1.1 处理卡片行为
    23. System.out.println(Jsons.DEFAULT.toJson(cardAction));
    24. System.out.println(cardAction.getRequestId());
    25. //1.2 返回自定义结果
    26. Map map = new HashMap<>();
    27. map.put("key1", "value1");
    28. map.put("ke2", "value2");
    29. CustomResponse customResponse = new CustomResponse();
    30. customResponse.setStatusCode(0);
    31. customResponse.setBody(map);
    32. Map> headers = new HashMap>();
    33. headers.put("key1", Arrays.asList("a", "b"));
    34. headers.put("key2", Arrays.asList("c", "d"));
    35. customResponse.setHeaders(headers);
    36. return customResponse;
    37. }
    38. }).build();
    39. // 2. 注入 ServletAdapter 示例
    40. @Autowired
    41. private ServletAdapter servletAdapter;
    42. //3. 注册服务路由
    43. @RequestMapping("/webhook/card")
    44. public void card(HttpServletRequest request, HttpServletResponse response)
    45. throws Throwable {
    46. //3.1 回调扩展包卡片行为处理回调
    47. servletAdapter.handleCardAction(request, response, CARD_ACTION_HANDLER);
    48. }
    49. }

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

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

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

    1. import com.lark.oapi.card.CardActionHandler;
    2. import com.lark.oapi.card.model.CardAction;
    3. import com.lark.oapi.card.model.CustomResponse;
    4. import com.lark.oapi.core.utils.Jsons;
    5. import com.lark.oapi.sdk.servlet.ext.ServletAdapter;
    6. import java.util.Arrays;
    7. import java.util.HashMap;
    8. import java.util.List;
    9. import java.util.Map;
    10. import javax.servlet.http.HttpServletRequest;
    11. import javax.servlet.http.HttpServletResponse;
    12. import org.springframework.beans.factory.annotation.Autowired;
    13. import org.springframework.web.bind.annotation.RequestMapping;
    14. import org.springframework.web.bind.annotation.RestController;
    15. @RestController
    16. public class CardActionController {
    17. //1. 注册卡片处理器
    18. private final CardActionHandler CARD_ACTION_HANDLER = CardActionHandler.newBuilder("v", "e",
    19. new CardActionHandler.ICardHandler() {
    20. @Override
    21. public Object handle(CardAction cardAction) {
    22. // 1.1 处理卡片行为
    23. System.out.println(Jsons.DEFAULT.toJson(cardAction));
    24. System.out.println(cardAction.getRequestId());
    25. // 1.2 获取租户 key
    26. String tenantKey = cardAction.getTenantKey();
    27. // 发送请求
    28. client.im().message().create(CreateMessageReq.newBuilder()
    29. .receiveIdType(ReceiveIdTypeEnum.OPEN_ID)
    30. .createMessageReqBody(CreateMessageReqBody.newBuilder()
    31. .content("text")
    32. .build())
    33. .build()
    34. , RequestOptions.newBuilder()
    35. .tenantKey(tenantKey)
    36. .build());
    37. return null;
    38. }
    39. }).build();
    40. // 2. 注入 ServletAdapter 示例
    41. @Autowired
    42. private ServletAdapter servletAdapter;
    43. //3. 注册服务路由
    44. @RequestMapping("/webhook/card")
    45. public void card(HttpServletRequest request, HttpServletResponse response)
    46. throws Throwable {
    47. //3.1 回调扩展包卡片行为处理回调
    48. servletAdapter.handleCardAction(request, response, CARD_ACTION_HANDLER);
    49. }
    50. }

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

    github地址

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

  • 相关阅读:
    python快速构建http服务
    如何利用腾讯云轻量应用服务器五分钟搭建一个WordPress博客?
    2023 版 Java和python开发线性代数探索
    日常工作报告生成器微信小程序源码 支持日报,周报,月报,年终终结
    【Unity3D热更新】Unity3D 零成本、高性能的C#的热更新框架:HybridCLR
    [SQLServer]NetCore中将SQLServer数据库备份为Sql脚本
    【Vue】路由与Node.js下载安装及环境配置教程
    初识java——jdk?环境变量?及关于安装jdk的步骤
    文心一言与GPT-4全面对比——人工智能语言模型的新纪元
    Codeforces Round #803 (Div. 2) VP补题
  • 原文地址:https://blog.csdn.net/m0_37055174/article/details/127130817