Java集成飞书实现预约飞书视频会议功能

📅 2026/7/23 16:45:47
Java集成飞书实现预约飞书视频会议功能
1. 背景与需求在企业办公场景中经常需要根据员工的工号自动创建或拉起飞书视频会议。本文介绍如何通过 Java 集成飞书开放平台的视频会议 API实现根据工号批量邀请参会人、创建并启动视频会议的功能。2. 前置准备2.1 飞书应用配置在飞书开放平台open.feishu.cn创建企业自建应用获取以下凭证App ID应用的唯一标识App Secret应用的密钥用于获取 tenant_access_token同时需要在应用权限中开启以下权限vc:meeting视频会议权限contact:user.employee_id:readonly通过工号查询用户信息2.2 Maven 依赖在项目的pom.xml中添加以下依赖dependency groupIdcom.larksuite.oapi/groupId artifactIdoapi-sdk/artifactId version2.5.3/version /dependency版本说明2.5.3 是飞书官方 SDK 的最新稳定版本相比 2.0.12 有更好的稳定性和更多功能支持。3. 核心实现Java集成飞书实现预约飞书视频会议功能实现步骤分1.获取自建应用token2.根据工号获取到用户id (userId)3.获取主日历信息4.创建对应日程-需要开启对应会议5.日程关联对应参会人员之后对应参会人员的日历里面就有对应的日程3.1 获取租户访问令牌-自建应用获取 tenant_access_token参考飞书文档自建应用获取 tenant_access_token - 服务端 API - 飞书开放平台权限要求无调用飞书接口都需要token: token又分应用token 和 用户token 现在介绍的是应用token在飞书开放平台open.feishu.cn创建企业自建应用获取以下凭证App ID应用的唯一标识App Secret应用的密钥用于获取 tenant_access_token/** * 获取 tenant_access_token */ public static String getTenantAccessToken() throws Exception { String url https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal; JSONObject reqBody new JSONObject(); reqBody.put(app_id, APP_ID); reqBody.put(app_secret, APP_SECRET); try (CloseableHttpClient httpClient HttpClients.createDefault()) { HttpPost post new HttpPost(url); post.setHeader(Content-Type, application/json;charsetutf-8); post.setEntity(new StringEntity(reqBody.toString(), StandardCharsets.UTF_8)); try (CloseableHttpResponse response httpClient.execute(post)) { String respText EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); JSONObject respJson JSON.parseObject(respText); int code respJson.getIntValue(code); if (code ! 0) { throw new RuntimeException(获取token失败 code: code msg: respJson.getString(msg)); } return respJson.getString(tenant_access_token); } } }3.2 批量获取员工列表参考飞书文档批量获取员工列表 - 服务端 API - 飞书开放平台权限要求directory:employee:list调用 API 获取员工列表/** * 根据工号数组批量查询 user_id */ public static ListString getUserIdsByJobNumbers(String tenantToken, ListString jobNumbers) throws Exception { ListString userIdList new ArrayList(); String url https://open.feishu.cn/open-apis/directory/v1/employees/filter; try (CloseableHttpClient httpClient HttpClients.createDefault()) { HttpPost post new HttpPost(url); post.setHeader(Authorization, Bearer tenantToken); post.setHeader(Content-Type, application/json;charsetutf-8); JSONObject reqBody new JSONObject(); JSONObject filter new JSONObject(); JSONArray conditions new JSONArray(); for (String jobNo : jobNumbers) { JSONObject cond new JSONObject(); cond.put(field, work_info.job_number); cond.put(operator, eq); cond.put(value, \jobNo\); conditions.add(cond); } filter.put(conditions, conditions); reqBody.put(filter, filter); JSONArray requiredFields new JSONArray(); requiredFields.add(base_info.user_id); reqBody.put(required_fields, requiredFields); JSONObject pageReq new JSONObject(); pageReq.put(page_size, 20); reqBody.put(page_request, pageReq); post.setEntity(new StringEntity(reqBody.toString(), StandardCharsets.UTF_8)); try (CloseableHttpResponse response httpClient.execute(post)) { String respText EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); JSONObject respJson JSON.parseObject(respText); int code respJson.getIntValue(code); if (code ! 0) { throw new RuntimeException(工号查用户失败 code: code msg: respJson.getString(msg)); } JSONObject data respJson.getJSONObject(data); JSONArray employees data.getJSONArray(abnormals); for (int i 0; i employees.size(); i) { JSONObject emp employees.getJSONObject(i); userIdList.add(emp.getString(id)); } return userIdList; } } }3.3 查询主日历信息参考飞书文档查询主日历信息 - 服务端 API - 飞书开放平台权限要求calendar:calendar:read(读取日历信息) 和 calendar:calendar:readonly获取日历、日程及忙闲信息/** * 获取个人主日历ID */ public static String getPrimaryCalendarId(String tenantToken, String hostUserId) throws Exception { String url https://open.feishu.cn/open-apis/calendar/v4/calendars/primary; try (CloseableHttpClient httpClient HttpClients.createDefault()) { HttpPost post new HttpPost(url); post.setHeader(Authorization, Bearer tenantToken); post.setHeader(Content-Type, application/json;charsetutf-8); JSONObject param new JSONObject(); param.put(user_id, hostUserId); post.setEntity(new StringEntity(param.toString(), StandardCharsets.UTF_8)); try (CloseableHttpResponse response httpClient.execute(post)) { String respText EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); JSONObject respJson JSON.parseObject(respText); int code respJson.getIntValue(code); if (code ! 0) { throw new RuntimeException(获取日历ID失败 code: code msg: respJson.getString(msg)); } JSONObject data respJson.getJSONObject(data); JSONArray calendarsArr data.getJSONArray(calendars); JSONObject itemObj calendarsArr.getJSONObject(0); JSONObject calendarObj itemObj.getJSONObject(calendar); return calendarObj.getString(calendar_id); } } }3.4 创建日程-默认创建会议参考飞书文档创建日程 - 服务端 API - 飞书开放平台权限要求calendar:calendar(更新日历及日程信息)和calendar:calendar.event:create创建日程/** * 核心创建日程方法入参统一 CalendarEventDTO */ public static JSONObject createEvent(String tenantToken, String calendarId, SentViaFeiShuConferenceDTO dto) throws Exception { String url https://open.feishu.cn/open-apis/calendar/v4/calendars/ calendarId /events; try (CloseableHttpClient httpClient HttpClients.createDefault()) { HttpPost post new HttpPost(url); post.setHeader(Authorization, Bearer tenantToken); post.setHeader(Content-Type, application/json;charsetutf-8); JSONObject event new JSONObject(); // 从DTO读取会议名称、备注 event.put(summary, dto.getSummary()); event.put(description, dto.getDescription()); event.put(timezone, Asia/Shanghai); // 从DTO读取起止时间并转时间戳 long startTs getTimeStamp(dto.getStartTime()); JSONObject startTime new JSONObject(); startTime.put(timestamp, String.valueOf(startTs)); startTime.put(timezone, Asia/Shanghai); event.put(start_time, startTime); long endTs getTimeStamp(dto.getEndTime()); JSONObject endTime new JSONObject(); endTime.put(timestamp, String.valueOf(endTs)); endTime.put(timezone, Asia/Shanghai); event.put(end_time, endTime); // 视频会议配置无assign_hosts消除193101报错 JSONObject vchat new JSONObject(); vchat.put(vc_type, vc); JSONObject meeting_settings new JSONObject(); // 主持人user_id作为视频owner String hostJob dto.getHostJobNumber(); // 这里先占位后面替换成查询后的hostUserId meeting_settings.put(owner_id, ); meeting_settings.put(join_meeting_permission, only_event_attendees); meeting_settings.put(allow_attendees_start, true); vchat.put(meeting_settings, meeting_settings); event.put(vchat, vchat); // 先查询全部user_id ListString allUserIdList dto.getAttendeeJobNumbersIds(); dto.setAttendeeJobNumbersIds(allUserIdList); // 拆分主持人、参会人ID String hostUserId dto.getHostUserId(); ListString memberIds allUserIdList.subList(1, allUserIdList.size()); // 修正视频owner_id为主持人真实user_id vchat.getJSONObject(meeting_settings).put(owner_id, hostUserId); // 组装参会人 JSONArray attendees buildAttendeeList(hostUserId, memberIds); event.put(attendees, attendees); // 参会人互相可见参与者列表 event.put(attendee_ability, can_see_others); event.put(visibility, default); post.setEntity(new StringEntity(event.toString(), StandardCharsets.UTF_8)); try (CloseableHttpResponse response httpClient.execute(post)) { String respText EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); JSONObject respJson JSON.parseObject(respText); System.out.println( 创建日程完整返回 ); System.out.println(respJson.toJSONString()); int code respJson.getIntValue(code); if (code ! 0) { throw new RuntimeException(创建日程失败 code: code msg: respJson.getString(msg)); } return respJson.getJSONObject(data); } } }3.35 关联参会人员参考飞书文档​​​​​​​添加日程参与人 - 服务端 API - 飞书开放平台权限要求calendar:calendar(更新日历及日程信息)和calendar:calendar.event:update更新日程/** * 给已存在的日程新增参会人 */ public static JSONObject addEventAttendees(String calendar_id, String event_id, String tenantToken,SentViaFeiShuConferenceDTO eventDTO) throws Exception { String url https://open.feishu.cn/open-apis/calendar/v4/calendars/ calendar_id /events/ event_id /attendees; try (CloseableHttpClient httpClient HttpClients.createDefault()) { HttpPost post new HttpPost(url); post.setHeader(Authorization, Bearer tenantToken); post.setHeader(Content-Type, application/json;charsetutf-8); JSONObject reqBody new JSONObject(); JSONArray attendeesArr new JSONArray(); JSONObject host new JSONObject(); host.put(type, user); host.put(user_id, eventDTO.getHostUserId()); attendeesArr.add(host); for (String userId : eventDTO.getAttendeeJobNumbersIds()) { JSONObject attendee new JSONObject(); attendee.put(type, user); attendee.put(user_id, userId); attendeesArr.add(attendee); } reqBody.put(attendees, attendeesArr); post.setEntity(new StringEntity(reqBody.toString(), StandardCharsets.UTF_8)); try (CloseableHttpResponse response httpClient.execute(post)) { String respText EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); JSONObject respJson JSON.parseObject(respText); System.out.println( 新增参会人返回完整响应 ); System.out.println(respJson.toJSONString()); int code respJson.getIntValue(code); if (code ! 0) { throw new RuntimeException(新增参会人失败 code: code msg: respJson.getString(msg)); } return respJson.getJSONObject(data); } } }