diff --git a/larksuite-oapi/src/main/java/com/lark/oapi/service/im/v1/ImService.java b/larksuite-oapi/src/main/java/com/lark/oapi/service/im/v1/ImService.java index 3e4617c75..d1e7b2517 100644 --- a/larksuite-oapi/src/main/java/com/lark/oapi/service/im/v1/ImService.java +++ b/larksuite-oapi/src/main/java/com/lark/oapi/service/im/v1/ImService.java @@ -240,6 +240,39 @@ public BatchMessage(Config config) { this.config = config; } + /** + * 批量发送消息 + *

注意事项:;- 应用需要启用[机器人能力](https://open.feishu.cn/document/uAjLw4CM/ugTN1YjL4UTN24CO1UjN/trouble-shooting/how-to-enable-bot-ability) ;- 接口权限说明:; - 必须拥有获取与发送单聊、群组消息权限,或者以应用的身份发消息权限; - 至少拥有一个批量发送消息权限:; - 给用户发送需要拥有 给多个用户批量发消息 权限; - 给部门成员发送需要拥有 给一个或多个部门的成员批量发消息 权限;- 应用需要拥有对所发送用户或部门的[可用性](https://open.feishu.cn/document/home/introduction-to-scope-and-authorization/availability);- 通过该接口发送的消息 不支持更新以及回复等操作;- 只能发送给用户,无法发送给群组;- 异步接口,会有一定延迟,每个应用待发送的消息按顺序处理,请合理安排批量发送范围和顺序。发送消息给单个用户的场景请使用[发送消息](https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/im-v1/message/create)接口;- 单个应用每天通过该接口发送的总消息条数不超过50万 + *

官网API文档链接:https://open.feishu.cn/document/ukTMukTMukTM/ucDO1EjL3gTNx4yN4UTM ; + *

使用Demo链接: https://github.com/larksuite/oapi-sdk-java/tree/v2_main/sample/src/main/java/com/lark/oapi/sample/apiall/imv1/CreateBatchMessageSample.java ; + */ + public BatchMessageResp batchSendMessage(BatchMessageReq req) throws Exception { + // 请求参数选项 + RequestOptions reqOptions = new RequestOptions(); + + // 发起请求 + RawResponse httpResponse = Transport.send(config, reqOptions, "POST" + , "/open-apis/message/v4/batch_send" + , Sets.newHashSet(AccessTokenType.Tenant) + , req); + + // 反序列化 + BatchMessageResp resp = UnmarshalRespUtil.unmarshalResp(httpResponse, BatchMessageResp.class); + if (resp == null) { + log.error(String.format( + "%s,callError,req=%s,respHeader=%s,respStatusCode=%s,respBody=%s,", "/open-apis/message/v4/batch_send" + , Jsons.DEFAULT.toJson(req), Jsons.DEFAULT.toJson(httpResponse.getHeaders()), + httpResponse.getStatusCode(), new String(httpResponse.getBody(), + StandardCharsets.UTF_8))); + throw new IllegalArgumentException("The result returned by the server is illegal"); + } + + resp.setRawResponse(httpResponse); + resp.setRequest(req); + + return resp; + } + /** * 批量撤回消息,批量撤回通过[批量发送消息](https://open.feishu.cn/document/ukTMukTMukTM/ucDO1EjL3gTNx4yN4UTM)接口发送的消息。 *

注意事项:;- 应用需要启用[机器人能力](https://open.feishu.cn/document/uAjLw4CM/ugTN1YjL4UTN24CO1UjN/trouble-shooting/how-to-enable-bot-ability) ;- 撤回单条发送的消息请使用[撤回消息](https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/im-v1/message/delete)接口;- 不支持撤回发出时间超过1天的消息;- 一次调用涉及大量消息,所以为异步接口,会有一定延迟。 ; diff --git a/larksuite-oapi/src/main/java/com/lark/oapi/service/im/v1/model/BatchMessageReq.java b/larksuite-oapi/src/main/java/com/lark/oapi/service/im/v1/model/BatchMessageReq.java new file mode 100644 index 000000000..378a996d8 --- /dev/null +++ b/larksuite-oapi/src/main/java/com/lark/oapi/service/im/v1/model/BatchMessageReq.java @@ -0,0 +1,138 @@ +package com.lark.oapi.service.im.v1.model; + +import com.google.gson.annotations.SerializedName; +import com.lark.oapi.card.model.MessageCard; + +public class BatchMessageReq { + + /** + * 消息类型 text post card image等等 + *

示例值:text + */ + @SerializedName("msg_type") + private String messageType; + + /** + * 消息内容 + *

示例值:{\"text\":\"Tom test content\"} + */ + @SerializedName("content") + private String content; + + /** + * 卡片消息内容 注意:card和content字段必须二选一 + *

示例值: + */ + @SerializedName("card") + private MessageCard card; + + /** + * 支持[自定义部门ID](https://open.feishu.cn/document/ukTMukTMukTM/uYTM5UjL2ETO14iNxkTN/terminology#3c3e6267)和open_department_id,列表长度小于等于 200 + *

示例值:["3dceba33a33226","d502aaa9514059", "od-5b91c9affb665451a16b90b4be367efa"] + */ + @SerializedName("department_ids") + private String[] departmentIds; + + /** + * 用户 open_id 列表,长度小于等于 200 + *

示例值:["ou_18eac85d35a26f989317ad4f02e8bbbb","ou_461cf042d9eedaa60d445f26dc747d5e"] + */ + @SerializedName("open_ids") + private String[] openIds; + + /** + * 用户 user_id 列表,长度小于等于 200 + *

示例值:["7cdcc7c2","ca51d83b"] + */ + @SerializedName("user_ids") + private String[] userIds; + + /** + * 用户 union_ids 列表,长度小于等于 200 + *

示例值:["on_cad4860e7af114fb4ff6c5d496d1dd76","on_gdcq860e7af114fb4ff6c5d496dabcet"] + */ + @SerializedName("union_ids") + private String[] unionIds; + + /** + * 由开发者生成的唯一字符串序列,用于发送消息请求去重;持有相同uuid的请求1小时内至多成功执行一次 + *

示例值:a0d69e20-1dd1-458b-k525-dfeca4015204 + */ + @SerializedName("uuid") + private String uuid; + + public BatchMessageReq() { + } + + public BatchMessageReq(BatchMessageReq.Builder builder) { + this.messageType = builder.messageType; + this.content = builder.content; + this.card = builder.card; + this.departmentIds = builder.departmentIds; + this.openIds = builder.openIds; + this.userIds = builder.userIds; + this.unionIds = builder.unionIds; + this.uuid = builder.uuid; + } + + public static Builder newBuilder() { + return new Builder(); + } + + public static class Builder { + + private String messageType; + private String content; + private MessageCard card; + private String[] departmentIds; + private String[] openIds; + private String[] userIds; + private String[] unionIds; + private String uuid; + + public Builder messageType(String messageType) { + this.messageType = messageType; + return this; + } + + public Builder content(String content) { + this.content = content; + return this; + } + + public Builder card(MessageCard card) { + this.card = card; + return this; + } + + public Builder departmentIds(String[] departmentIds) { + this.departmentIds = departmentIds; + return this; + } + + public Builder openIds(String[] openIds) { + this.openIds = openIds; + return this; + } + + public Builder userIds(String[] userIds) { + this.userIds = userIds; + return this; + } + + public Builder unionIds(String[] unionIds) { + this.unionIds = unionIds; + return this; + } + + public Builder uuid(String uuid) { + this.uuid = uuid; + return this; + } + + public BatchMessageReq build() { + return new BatchMessageReq(this); + } + } + +} diff --git a/larksuite-oapi/src/main/java/com/lark/oapi/service/im/v1/model/BatchMessageResp.java b/larksuite-oapi/src/main/java/com/lark/oapi/service/im/v1/model/BatchMessageResp.java new file mode 100644 index 000000000..aa0943954 --- /dev/null +++ b/larksuite-oapi/src/main/java/com/lark/oapi/service/im/v1/model/BatchMessageResp.java @@ -0,0 +1,6 @@ +package com.lark.oapi.service.im.v1.model; + +import com.lark.oapi.core.response.BaseResponse; + +public class BatchMessageResp extends BaseResponse { +} diff --git a/larksuite-oapi/src/main/java/com/lark/oapi/service/im/v1/model/BatchMessageRespBody.java b/larksuite-oapi/src/main/java/com/lark/oapi/service/im/v1/model/BatchMessageRespBody.java new file mode 100644 index 000000000..fdb853365 --- /dev/null +++ b/larksuite-oapi/src/main/java/com/lark/oapi/service/im/v1/model/BatchMessageRespBody.java @@ -0,0 +1,81 @@ +package com.lark.oapi.service.im.v1.model; + +import com.google.gson.annotations.SerializedName; + +public class BatchMessageRespBody { + + /** + * 批量消息 ID + *

示例值:om_dc13264520392913993dd051dba21dcf + */ + @SerializedName("message_id") + private String messageId; + + /** + * 不合法的部门 ID 列表 + *

示例值:["3dceba33a33226","d502aaa9514059", "od-5b91c9affb665451a16b90b4be367efa"] + */ + @SerializedName("invalid_department_ids") + private String[] invalidDepartmentIds; + + /** + * 不合法的 open_id 列表 + *

示例值:["ou_18eac85d35a26f989317ad4f02e8bbbb","ou_461cf042d9eedaa60d445f26dc747d5e"] + */ + @SerializedName("invalid_open_ids") + private String[] invalidOpenIds; + + /** + * 不合法的 user_id 列表(对应V3接口的invalid_employee_ids) + *

示例值:["7cdcc7c2","ca51d83b"] + */ + @SerializedName("invalid_user_ids") + private String[] invalidUserIds; + + /** + * 不合法的 union_id 列表 + *

示例值:["on_cad4860e7af114fb4ff6c5d496d1dd76","on_gdcq860e7af114fb4ff6c5d496dabcet"] + */ + @SerializedName("invalid_union_ids") + private String[] invalidUnionIds; + + public String getMessageId() { + return messageId; + } + + public void setMessageId(String messageId) { + this.messageId = messageId; + } + + public String[] getInvalidDepartmentIds() { + return invalidDepartmentIds; + } + + public void setInvalidDepartmentIds(String[] invalidDepartmentIds) { + this.invalidDepartmentIds = invalidDepartmentIds; + } + + public String[] getInvalidOpenIds() { + return invalidOpenIds; + } + + public void setInvalidOpenIds(String[] invalidOpenIds) { + this.invalidOpenIds = invalidOpenIds; + } + + public String[] getInvalidUserIds() { + return invalidUserIds; + } + + public void setInvalidUserIds(String[] invalidUserIds) { + this.invalidUserIds = invalidUserIds; + } + + public String[] getInvalidUnionIds() { + return invalidUnionIds; + } + + public void setInvalidUnionIds(String[] invalidUnionIds) { + this.invalidUnionIds = invalidUnionIds; + } +} diff --git a/sample/src/main/java/com/lark/oapi/sample/apiall/imv1/CreateBatchMessageSample.java b/sample/src/main/java/com/lark/oapi/sample/apiall/imv1/CreateBatchMessageSample.java new file mode 100644 index 000000000..63e804650 --- /dev/null +++ b/sample/src/main/java/com/lark/oapi/sample/apiall/imv1/CreateBatchMessageSample.java @@ -0,0 +1,36 @@ +package com.lark.oapi.sample.apiall.imv1; + +import com.lark.oapi.Client; +import com.lark.oapi.core.utils.Jsons; +import com.lark.oapi.service.im.v1.model.BatchMessageReq; +import com.lark.oapi.service.im.v1.model.BatchMessageResp; + +// POST /message/v4/batch_send +public class CreateBatchMessageSample { + + public static void main(String arg[]) throws Exception { + // 构建client + Client client = Client.newBuilder("appId", "appSecret").build(); + + // 创建请求对象 + BatchMessageReq req = BatchMessageReq.newBuilder() + .messageType("text") + .content("{ \"text\": \"要发送的文本消息\" }") + .unionIds(new String[] {"on_cad4860e7af114fb4ff6c5d496d1dd76", "on_gdcq860e7af114fb4ff6c5d496dabcet"}) + .uuid("a0d69e20-1dd1-458b-k525-dfeca4015204") + .build(); + + // 发起请求 + BatchMessageResp resp = client.im().batchMessage().batchSendMessage(req); + + // 处理服务端错误 + 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())); + } +}