¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.jeecg.modules.mes.job; |
| | | |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.jeecg.common.util.PasswordUtil; |
| | | import org.jeecg.common.util.RestUtil; |
| | | import org.jeecg.common.util.oConvertUtils; |
| | | import org.jeecg.modules.mes.entity.FeishuUser; |
| | | import org.jeecg.modules.system.entity.SysUser; |
| | | import org.jeecg.modules.system.service.ISysUserService; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.http.HttpEntity; |
| | | import org.springframework.http.HttpHeaders; |
| | | import org.springframework.http.HttpMethod; |
| | | import org.springframework.http.ResponseEntity; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.web.client.RestTemplate; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | @Service |
| | | @Slf4j |
| | | public class FeishuUserService { |
| | | |
| | | @Resource |
| | | private ISysUserService sysUserService; |
| | | |
| | | @Resource |
| | | private RestTemplate restTemplate; // æ°å¢RestTemplateä¾èµæ³¨å
¥ |
| | | |
| | | @Value("${feishu.appId:}") |
| | | private String appId; |
| | | |
| | | @Value("${feishu.appSecret:}") |
| | | private String appSecret; |
| | | |
| | | /** |
| | | * 忥é£ä¹¦é¨é¨ç¨æ·å°ç³»ç»ç¨æ·è¡¨ |
| | | * @param departmentId é£ä¹¦é¨é¨ID |
| | | */ |
| | | public void syncFeishuDepartmentUsers(String departmentId) { |
| | | try { |
| | | log.info("å¼å§åæ¥é£ä¹¦é¨é¨ç¨æ·ï¼é¨é¨ID: {}", departmentId); |
| | | |
| | | // 1. è·åé£ä¹¦è®¿é®ä»¤ç |
| | | String accessToken = getFeishuAccessToken(); |
| | | if (oConvertUtils.isEmpty(accessToken)) { |
| | | log.error("è·åé£ä¹¦è®¿é®ä»¤ç失败ï¼ç»æ¢åæ¥æµç¨"); |
| | | return; // 令çè·åå¤±è´¥ç´æ¥è¿åï¼é¿å
åç»æ ææä½ |
| | | } |
| | | |
| | | // 2. è·åé¨é¨ä¸çç¨æ·å表 |
| | | List<FeishuUser> feishuUsers = getDepartmentUsers(accessToken, departmentId); |
| | | log.info("è·åå°é£ä¹¦é¨é¨ç¨æ·æ°é: {}", feishuUsers.size()); |
| | | |
| | | // 3. 忥å°ç³»ç»ç¨æ·è¡¨ |
| | | int successCount = 0; |
| | | int updateCount = 0; |
| | | int addCount = 0; |
| | | |
| | | for (FeishuUser feishuUser : feishuUsers) { |
| | | try { |
| | | boolean isUpdated = syncFeishuUserToSystem(feishuUser); |
| | | successCount++; |
| | | if (isUpdated) { |
| | | updateCount++; |
| | | } else { |
| | | addCount++; |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("忥é£ä¹¦ç¨æ·å¤±è´¥ï¼ç¨æ·ID: {}", feishuUser.getUserId(), e); |
| | | } |
| | | } |
| | | |
| | | log.info("é£ä¹¦ç¨æ·åæ¥å®æï¼æ»å¤ç: {}ï¼æ°å¢: {}ï¼æ´æ°: {}", successCount, addCount, updateCount); |
| | | } catch (Exception e) { |
| | | log.error("忥é£ä¹¦é¨é¨ç¨æ·å¤±è´¥ï¼é¨é¨ID: {}", departmentId, e); |
| | | throw new RuntimeException("忥é£ä¹¦ç¨æ·å¤±è´¥: " + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | private String getFeishuAccessToken() { |
| | | try { |
| | | String url = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal"; |
| | | |
| | | log.info("å¼å§è·åé£ä¹¦è®¿é®ä»¤çï¼AppId: {}", |
| | | appId != null ? appId.substring(0, Math.min(appId.length(), 10)) + "..." : "null"); |
| | | |
| | | JSONObject params = new JSONObject(); |
| | | params.put("app_id", appId); |
| | | params.put("app_secret", appSecret); |
| | | |
| | | log.debug("è·å令ç请æ±åæ°: {}", params.toJSONString()); |
| | | |
| | | JSONObject result = RestUtil.post(url, params); |
| | | |
| | | log.info("è·åé£ä¹¦è®¿é®ä»¤çååº: {}", result != null ? result.toJSONString() : "null"); |
| | | |
| | | if (result != null && result.getInteger("code") == 0) { |
| | | String accessToken = result.getString("tenant_access_token"); |
| | | log.info("æåè·åé£ä¹¦è®¿é®ä»¤çï¼ä»¤çé¿åº¦: {}", accessToken != null ? accessToken.length() : 0); |
| | | return accessToken; |
| | | } else { |
| | | log.error("è·åé£ä¹¦è®¿é®ä»¤ç失败ï¼ååº: {}", result != null ? result.toJSONString() : "null"); |
| | | if (result != null) { |
| | | log.error("é误ç : {}, é误信æ¯: {}", result.getInteger("code"), result.getString("msg")); |
| | | } |
| | | return null; |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("è·åé£ä¹¦è®¿é®ä»¤çå¼å¸¸", e); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è·åé¨é¨ç¨æ·å表ï¼ç´å±åå·¥ï¼ |
| | | */ |
| | | private List<FeishuUser> getDepartmentUsers(String accessToken, String departmentId) { |
| | | List<FeishuUser> userList = new ArrayList<>(); |
| | | try { |
| | | log.info("å¼å§è·åé£ä¹¦é¨é¨ç¨æ·å表ï¼é¨é¨ID: {}", departmentId); |
| | | |
| | | // éªè¯è®¿é®ä»¤ç |
| | | if (accessToken == null || accessToken.isEmpty()) { |
| | | log.error("访é®ä»¤çä¸ºç©ºï¼æ æ³ç»§ç»æ§è¡"); |
| | | return userList; |
| | | } |
| | | log.info("使ç¨ç访é®ä»¤çåç¼: Bearer {}", accessToken.substring(0, Math.min(20, accessToken.length())) + "..."); |
| | | |
| | | // é£ä¹¦APIç«¯ç¹ |
| | | String url = "https://open.feishu.cn/open-apis/contact/v3/users/find_by_department"; |
| | | |
| | | String pageToken = null; |
| | | int pageNumber = 1; |
| | | |
| | | do { |
| | | // æå»ºè¯·æ±URLååæ° |
| | | StringBuilder urlBuilder = new StringBuilder(url); |
| | | urlBuilder.append("?department_id=").append(departmentId); |
| | | urlBuilder.append("&department_id_type=open_department_id"); |
| | | urlBuilder.append("&page_size=50"); |
| | | urlBuilder.append("&user_id_type=open_id"); |
| | | |
| | | if (pageToken != null && !pageToken.isEmpty()) { |
| | | urlBuilder.append("&page_token=").append(pageToken); |
| | | } |
| | | |
| | | log.info("请æ±ç¬¬{}é¡µæ°æ®ï¼URL: {}", pageNumber, urlBuilder.toString()); |
| | | |
| | | // 设置请æ±å¤´ - å
³é®ä¿®å¤ç¹ï¼ä½¿ç¨HttpHeadersç¡®ä¿å¤´ä¿¡æ¯æ£ç¡®è®¾ç½® |
| | | HttpHeaders headers = new HttpHeaders(); |
| | | String authHeader = "Bearer " + accessToken; |
| | | headers.add("Authorization", authHeader); |
| | | headers.add("Content-Type", "application/json; charset=utf-8"); |
| | | log.info("设置请æ±å¤´: Authorization = {}", authHeader.substring(0, Math.min(30, authHeader.length())) + "..."); |
| | | |
| | | // 使ç¨RestTemplateåé请æ±ï¼ç¡®ä¿å¤´ä¿¡æ¯è¢«æ£ç¡®ä¼ é |
| | | HttpEntity<String> requestEntity = new HttpEntity<>(headers); |
| | | ResponseEntity<String> response = restTemplate.exchange( |
| | | urlBuilder.toString(), |
| | | HttpMethod.GET, |
| | | requestEntity, |
| | | String.class |
| | | ); |
| | | |
| | | // è§£æååº |
| | | JSONObject result = JSONObject.parseObject(response.getBody()); |
| | | log.debug("第{}页APIååº: {}", pageNumber, result != null ? result.toJSONString() : "null"); |
| | | |
| | | if (result != null && result.getInteger("code") == 0) { |
| | | JSONObject data = result.getJSONObject("data"); |
| | | if (data != null) { |
| | | // è§£æç¨æ·å表 |
| | | Object items = data.get("items"); |
| | | log.info("第{}页åå§ç¨æ·æ°æ®æ°é: {}", pageNumber, items instanceof List ? ((List<?>) items).size() : 0); |
| | | |
| | | if (items != null) { |
| | | List<FeishuUser> pageUsers = parseUsers(items); |
| | | userList.addAll(pageUsers); |
| | | log.info("第{}页解æåç¨æ·æ°é: {}", pageNumber, pageUsers.size()); |
| | | } |
| | | |
| | | // æ£æ¥æ¯å¦æä¸ä¸é¡µ |
| | | pageToken = data.getString("page_token"); |
| | | boolean hasMore = data.getBooleanValue("has_more"); |
| | | log.info("第{}页has_more: {}, page_token: {}", pageNumber, hasMore, pageToken); |
| | | pageNumber++; |
| | | } else { |
| | | log.warn("第{}页data为空", pageNumber); |
| | | break; |
| | | } |
| | | } else { |
| | | log.error("è·åé£ä¹¦é¨é¨ç¨æ·å表失败ï¼ååº: {}", result != null ? result.toJSONString() : "null"); |
| | | if (result != null) { |
| | | log.error("é误ç : {}, é误信æ¯: {}", result.getInteger("code"), result.getString("msg")); |
| | | } |
| | | break; |
| | | } |
| | | } while (pageToken != null && !pageToken.isEmpty()); |
| | | |
| | | log.info("è·åé£ä¹¦é¨é¨ç¨æ·å®æï¼æ»ç¨æ·æ°é: {}", userList.size()); |
| | | |
| | | } catch (Exception e) { |
| | | log.error("è·åé£ä¹¦é¨é¨ç¨æ·å表å¼å¸¸", e); |
| | | } |
| | | return userList; |
| | | } |
| | | |
| | | /** |
| | | * è§£æç¨æ·æ°æ® |
| | | */ |
| | | /** |
| | | * è§£æç¨æ·æ°æ® |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | private List<FeishuUser> parseUsers(Object items) { |
| | | Logger log = LoggerFactory.getLogger(FeishuUserService.class); |
| | | List<FeishuUser> userList = new ArrayList<>(); |
| | | if (!(items instanceof List)) { |
| | | log.warn("è§£æç¨æ·æ°æ®å¤±è´¥ï¼items䏿¯å表类å: {}", items); |
| | | return userList; |
| | | } |
| | | List<?> userItems = (List<?>) items; |
| | | log.info("å¼å§è§£æé£ä¹¦ç¨æ·å表ï¼å
±{}æ¡è®°å½", userItems.size()); |
| | | for (Object item : userItems) { |
| | | if (item == null || !(item instanceof Map)) { |
| | | log.warn("è·³è¿æ æç¨æ·æ°æ®é¡¹ï¼ç±»åä¸å¹é
: {}", item != null ? item.getClass() : "null"); |
| | | continue; |
| | | } |
| | | Map<String, Object> userMap = (Map<String, Object>) item; |
| | | FeishuUser user = new FeishuUser(); |
| | | // è§£æopen_id |
| | | user.setOpenId((String) userMap.getOrDefault("open_id", "")); |
| | | // è§£ænameå¹¶æå |
| | | String name = (String) userMap.getOrDefault("name", ""); |
| | | if (name.contains(" ")) { |
| | | String[] parts = name.split(" "); |
| | | if (parts.length == 2) { |
| | | user.setUsername(parts[0].trim()); // å·¥å·é¨ååå°username |
| | | user.setRealname(parts[1].trim()); // å§åé¨ååå°realname |
| | | user.setWorkNo(parts[0].trim()); // å·¥å·ä¹åå°workNo |
| | | } else { |
| | | // æåå¼å¸¸æ¶ï¼é»è®¤å¤ç |
| | | user.setUsername(name); |
| | | user.setRealname(name); |
| | | user.setWorkNo(""); |
| | | log.warn("é£ä¹¦ç¨æ·nameåæ®µæ ¼å¼å¼å¸¸ï¼æ æ³æåï¼åå§å¼ï¼{}", name); |
| | | } |
| | | } else { |
| | | user.setUsername(name); |
| | | user.setRealname(name); |
| | | user.setWorkNo(""); |
| | | log.warn("é£ä¹¦ç¨æ·nameåæ®µæ ç©ºæ ¼åéï¼æ æ³æåï¼åå§å¼ï¼{}", name); |
| | | } |
| | | // è§£æå
¶ä»åºæ¬ä¿¡æ¯ |
| | | user.setEnName((String) userMap.getOrDefault("en_name", "")); |
| | | user.setDescription((String) userMap.getOrDefault("description", "")); |
| | | Object mobileVisibleObj = userMap.get("mobile_visible"); |
| | | user.setMobileVisible(mobileVisibleObj instanceof Boolean ? (Boolean) mobileVisibleObj : false); |
| | | // è§£æå¤´åä¿¡æ¯ |
| | | Object avatarObj = userMap.get("avatar"); |
| | | if (avatarObj instanceof Map) { |
| | | Map<String, Object> avatarMap = (Map<String, Object>) avatarObj; |
| | | user.setAvatar240((String) avatarMap.getOrDefault("avatar_240", "")); |
| | | user.setAvatar640((String) avatarMap.getOrDefault("avatar_640", "")); |
| | | user.setAvatar72((String) avatarMap.getOrDefault("avatar_72", "")); |
| | | user.setAvatarOrigin((String) avatarMap.getOrDefault("avatar_origin", "")); |
| | | } else { |
| | | log.info("ç¨æ·[{}]æªè®¾ç½®å¤´åæå¤´åæ ¼å¼å¼å¸¸", user.getRealname()); |
| | | } |
| | | // 设置é»è®¤å å¯å¯ç ï¼è¿éå设å¯ç æ¯ç®åå å¯åå¨ï¼å®é
å»ºè®®ç¨æ´å®å
¨çå 坿¹å¼ï¼ |
| | | user.setPassword("123456"); // ä½ è¦æ±çé»è®¤å¯ç |
| | | // å°open_idåå°å¯¹åºçåæ®µï¼æ ¹æ®ä½ çç¨æ·è¡¨ç»æï¼åè®¾ç¨æ·è¡¨æopen_idåæ®µï¼ |
| | | user.setOpenId((String) userMap.getOrDefault("open_id", "")); |
| | | userList.add(user); |
| | | } |
| | | |
| | | return userList; |
| | | } |
| | | |
| | | /** |
| | | * 忥å个é£ä¹¦ç¨æ·å°ç³»ç» |
| | | * @param feishuUser é£ä¹¦ç¨æ· |
| | | * @return trueè¡¨ç¤ºæ´æ°ï¼false表示æ°å¢ |
| | | * |
| | | * åæå¢å ï¼ ç¨æ·åæ¥å¯¹æ¯ï¼é£ä¹¦ç¦»èåå·¥éè¦å¨æ¬å°ç¨æ·è¡¨éé¢å°è¯¥ç¨æ·ç¶æç¦ç¨ |
| | | */ |
| | | private boolean syncFeishuUserToSystem(FeishuUser feishuUser) { |
| | | // è¿éæ ¹æ®æååçusernameï¼å·¥å·ï¼å»æ¥è¯¢ç³»ç»ç¨æ· |
| | | String username = feishuUser.getUsername(); |
| | | SysUser existUser = sysUserService.getUserByName(username); |
| | | SysUser sysUser = new SysUser(); |
| | | sysUser.setUsername(username); |
| | | sysUser.setStatus(1); |
| | | sysUser.setDelFlag(0); |
| | | sysUser.setAvatar(feishuUser.getAvatar640()); |
| | | sysUser.setRealname(feishuUser.getRealname()); |
| | | sysUser.setWorkNo(feishuUser.getWorkNo()); |
| | | String password = "123456", salt = oConvertUtils.randomGen(8); |
| | | String passwordEncode = PasswordUtil.encrypt(sysUser.getUsername(), password, salt); |
| | | sysUser.setSalt(salt); |
| | | sysUser.setPassword(passwordEncode); |
| | | sysUser.setOpenId(feishuUser.getOpenId()); |
| | | |
| | | if (existUser == null) { |
| | | |
| | | sysUserService.addUserWithRole(sysUser, "5"); |
| | | log.info("æ°å¢ç¨æ·: {}", username); |
| | | return false; |
| | | } else { |
| | | sysUser.setId(existUser.getId()); |
| | | sysUserService.editUser(sysUser); |
| | | log.info("æ´æ°ç¨æ·: {}", username); |
| | | return true; |
| | | } |
| | | } |
| | | } |