package com.takai.system.service.impl; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.auth0.jwt.JWTCreator; import com.auth0.jwt.algorithms.Algorithm; import com.takai.common.enums.UserTypeEnum; import com.takai.common.utils.DateUtils; import com.takai.common.utils.SecurityUtils; import com.takai.common.utils.StringUtils; import com.takai.system.domain.SysProject; import com.takai.system.domain.SysProjectStaff; import com.takai.system.domain.vo.Member; import com.takai.system.domain.vo.ProjectWebApiBo; import com.takai.system.service.*; import com.takai.common.annotation.DataSource; import com.takai.common.config.JkConfig; import com.takai.common.core.domain.entity.SysDept; import com.takai.common.core.domain.entity.SysUser; import com.takai.common.core.redis.RedisCache; import com.takai.common.enums.DataSourceType; import com.takai.system.domain.SysPost; import lombok.extern.slf4j.Slf4j; import okhttp3.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import java.io.IOException; import java.util.*; import java.util.concurrent.TimeUnit; import com.auth0.jwt.JWT; /** * 高井 业务层处理 * * @author takai */ @Slf4j @Service @DataSource(DataSourceType.MASTER) public class JkApiServiceImpl implements IJkApiService { private static final Logger logger = LoggerFactory.getLogger(JkApiServiceImpl.class); @Autowired private ISysUserService sysUserService; @Autowired private ISysDeptService sysDeptService; @Autowired private ISysPostService sysPostService; @Autowired private RedisCache redisCache; @Autowired public RedisTemplate redisTemplate; @Autowired JkConfig jkConfig; @Autowired private ISysProjectService projectService; @Autowired private ISysProjectStaffService projectStaffService; public static final String BEARER = "Bearer"; public static final String PARAM_ST = "startTime"; public static final String PARAM_PAGE = "page"; public static final String PARAM_SIZE = "size"; public static final String PARAM_GRANT_TYPE = "grant_type"; public static final String PARAM_CLIENT_ID = "client_id"; public static final String PARAM_CLIENT_SECRET = "client_secret"; public static final String PARAM_CODE = "code"; public static final String PARAM_REDIRECT_URI = "redirect_uri"; public static final String PARAM_ACCESS_TOKEN = "access_token"; public static final String PARAM_IDS = "ids"; public static final String PARAM_ERRORS = "errors"; public static final int DEFAULT_SIZE = 100; public static final String CODE_SUCCESS = "0"; public static final String DATA = "data"; public static final String TOTAL = "total"; public static final String LIST = "list"; public static final String INTERFACE_USER = "用户"; public static final String GRANT_TYPE_AC = "authorization_code"; public static final int BEFORE_DAYS = 7; private static final MediaType JSON_UTF8 = MediaType.get("application/json; charset=utf-8"); private static final OkHttpClient client = new OkHttpClient(); public static final String HXG_PROJECT_AND_STAFF = "用户"; public static final String HJL_PROJECT_AND_STAFF = "用户"; public static final String HXG = "f47ac10b58cc4372a5670e06f141669d"; public static final String HJL = "a34851c530ee0d07d1154beb47bb93dd"; /** * 通过建科接口获取建科用户信息 */ @Override public List getJkUsers() throws IOException { List userList = new ArrayList<>(); List dataList = getApiData(jkConfig.getIamUserUrl(),INTERFACE_USER); for(JSONObject jsonObject : dataList) { List users = buildSysUserList(jsonObject.getJSONArray(LIST)); //保存用户到用户表 sysUserService.batchUser(users); userList.addAll(users); } return userList; } private List buildSysUserList(JSONArray jsonArray) { List userList = new ArrayList<>(); for(int i = 0; i < jsonArray.size(); i++) { SysUser sysUser = new SysUser(); JSONObject json = jsonArray.getJSONObject(i); sysUser.setUserId(json.getString("app_account__id")); sysUser.setUserName(json.getString("app_account__account_no")); sysUser.setNickName(json.getString("app_account__account_name")); //建科用户状态,启用:1,停用:0,删除:-1 String status = json.getString("app_account__status"); status = status.equals("1") ? "0" : "1"; sysUser.setStatus(status); sysUser.setPhonenumber(json.getString("idt_user__mobile")); sysUser.setWorkNo(json.getString("idt_user__work_no")); sysUser.setEmail(json.getString("idt_user__email")); sysUser.setUserType(UserTypeEnum.JK_USER.getCode());//建科用户 sysUser.setPassword(SecurityUtils.encryptPassword(jkConfig.getJkPsw())); JSONArray orgs = json.getJSONArray("orgs"); if(orgs.size() > 0) { sysUser.setDeptId(orgs.getJSONObject(0).getLong("idt_org__id")); } userList.add(sysUser); } return userList; } /** * 通过建科接口获取建科部门信息 */ @Override public List getJkDepts() throws IOException { List deptList = new ArrayList<>(); List dataList = getApiData(jkConfig.getIamDeptUrl(),"部门"); for(JSONObject jsonObject : dataList) { List depts = buildSysDeptList(jsonObject.getJSONArray(LIST)); //保存用户到用户表 sysDeptService.batchDept(depts); deptList.addAll(depts); } return deptList; } private List buildSysDeptList(JSONArray jsonArray) { List deptList = new ArrayList<>(); for(int i = 0; i < jsonArray.size(); i++) { SysDept sysDept = new SysDept(); JSONObject json = jsonArray.getJSONObject(i); sysDept.setDeptId(json.getString("idt_org__id")); sysDept.setDeptName(json.getString("idt_org__name")); sysDept.setParentId(json.getString("idt_org__parent_id")); sysDept.setAncestors(json.getString("idt_org__org_path").substring(1).replaceAll("/",",")); //部门状态,启用:1,停用:0 String status = json.getString("idt_org__status"); status = status.equals("1") ? "0" : "1"; sysDept.setStatus(status); deptList.add(sysDept); } return deptList; } /** * 通过建科接口获取建科岗位信息 */ @Override public List getJkPosts() throws IOException { List postList = new ArrayList<>(); List dataList = getApiData(jkConfig.getIamPostUrl(),"岗位"); for(JSONObject jsonObject : dataList) { List posts = buildSysPostList(jsonObject.getJSONArray(LIST)); //保存用户到用户表 sysPostService.batchPost(posts); postList.addAll(posts); } return postList; } private List buildSysPostList(JSONArray jsonArray) { List postList = new ArrayList<>(); for(int i = 0; i < jsonArray.size(); i++) { SysPost sysPost = new SysPost(); JSONObject json = jsonArray.getJSONObject(i); sysPost.setPostCode(json.getString("idt_job__code")); sysPost.setPostName(json.getString("idt_job__name")); //部门状态,启用:1,停用:0 String status = json.getString("idt_job__status"); status = status.equals("1") ? "0" : "1"; sysPost.setStatus(status); postList.add(sysPost); } return postList; } @Override public void getHxgProjectAndStaff() throws IOException { JSONArray dataList = getProjectApiData(jkConfig.getHxgProjectAndStaff(),HXG_PROJECT_AND_STAFF); buildAndSaveSysProjectAndStaff(dataList,HXG); } @Override public void getHjlProjectAndStaff() throws IOException { JSONArray dataList = getProjectApiData(jkConfig.getHjlProjectAndStaff(),HJL_PROJECT_AND_STAFF); buildAndSaveSysProjectAndStaff(dataList,HJL); } private void buildAndSaveSysProjectAndStaff(JSONArray jsonArray,String sourceFrom) { try { // ========== 核心解析:JSON数组 → List ========== List projectList = JSON.parseArray(String.valueOf(jsonArray), ProjectWebApiBo.class); int projectNum = 0; int projectStaffNum = 0; // 遍历解析结果,验证数据 for (ProjectWebApiBo project : projectList) { SysProject sysProject = new SysProject(); sysProject.setProjectPid(project.getProCode()); sysProject.setProjectName(project.getProName()); sysProject.setSourceFrom(sourceFrom); SysProject dbProject = projectService.selectSysProjectByProjectPid(project.getProCode()); if(null == dbProject) { projectService.insertSysProject(sysProject); projectNum++; } for (Member member : project.getMemberList()) { SysProjectStaff sysProjectStaff = new SysProjectStaff(); SysUser sysUser = sysUserService.selectUserByUserName(member.getAccountNo()); if(sysUser != null) { sysProjectStaff.setProjectPid(project.getProCode()); sysProjectStaff.setProjectName(project.getProName()); sysProjectStaff.setUserId(null != sysUser ? sysUser.getUserId() : null); sysProjectStaff.setRoleId(null != sysUser ? sysUser.getRoleId() : null); SysProjectStaff dbStaff = projectStaffService.selectSysProjectStaff(sysProjectStaff); if(null == dbStaff) { projectStaffService.insertSysProjectStaff(sysProjectStaff); projectStaffNum++; } } } } if(sourceFrom.equals(HJL)){ logger.info("项目同步任务同步慧监理项目数据"+projectNum+"条"); logger.info("项目同步任务同步慧监理项目成员数据"+projectStaffNum+"条"); } else { logger.info("项目同步任务同步慧项管项目数据"+projectNum+"条"); logger.info("项目同步任务同步慧项管项目成员数据"+projectStaffNum+"条"); } } catch (Exception e) { System.err.println("FastJSON2 解析失败:" + e.getMessage()); e.printStackTrace(); } } public List getApiData(String url,String objectName) throws IOException { List objectList = new ArrayList<>(); int page = 1; int total = 1; logger.info("获取建科"+objectName+"请求url:" + url); while(total >= page){ Request request = buildRequest(url,page); // 执行请求并获取响应 // OkHttpClient client = buildOkHttpClient(); try { Response response = client.newCall(request).execute(); String responseBody = response.body().string(); logger.info("获取建科"+objectName+"返回:" + responseBody); if (!response.isSuccessful()) { throw new IOException("获取建科"+objectName+"信息失败 " + responseBody); } JSONObject jsonObject =JSON.parseObject(responseBody); logger.info("获取建科"+objectName+"返回信息:" + jsonObject.toJSONString()); //“0”为成功其余均为失败 String code = jsonObject.getString("code"); if (CODE_SUCCESS.equals(code)) { JSONObject dataObject = jsonObject.getJSONObject(DATA); //如果是用户接口,调用回调函数 if(INTERFACE_USER.equals(objectName)) { doUserCallback(dataObject); } objectList.add(dataObject); total = dataObject.getInteger(TOTAL); page++; continue; } else { } } catch (IOException e) { throw new IOException("获取建科用"+objectName+"信息失败 ", e); } } return objectList; } public JSONArray getProjectApiData(String url,String objectName) throws IOException { JSONArray jsonArray = new JSONArray(); logger.info("获取建科"+objectName+"请求url:" + url); Request request = buildPostRequest(url); try { OkHttpClient okHttpClient = buildOkHttpClient(); Response response = okHttpClient.newCall(request).execute(); String responseBody = response.body().string(); logger.info("获取建科项目"+objectName+"返回:" + responseBody); if (!response.isSuccessful()) { throw new IOException("获取建科项目"+objectName+"信息失败 " + responseBody); } JSONObject jsonObject =JSON.parseObject(responseBody); logger.info("获取建科项目"+objectName+"返回信息:" + jsonObject.toJSONString()); //“0”为成功其余均为失败 String code = jsonObject.getString("code"); if (code == null) { code = jsonObject.getString("statusCode"); } if (CODE_SUCCESS.equals(code) ||"200".equals(code)) { jsonArray = jsonObject.getJSONArray(DATA); } } catch (IOException e) { throw new IOException("获取建科用项目"+objectName+"信息失败 ", e); } return jsonArray; } private boolean doUserCallback(JSONObject dataObject) { String ids = ""; JSONArray jsonArray = dataObject.getJSONArray(LIST); for(int i = 0; i < jsonArray.size(); i++) { SysUser sysUser = new SysUser(); JSONObject json = jsonArray.getJSONObject(i); if(!"".equals(ids)) { ids += ","; } ids += json.getString("request_log__id"); } Request request = buildCallbackRequest(ids); int i = 0; while(i < 3) {//重试3次 try { if(i > 0) { Thread.sleep(i*1000); } // OkHttpClient client = buildOkHttpClient(); Response response = client.newCall(request).execute(); String responseBody = response.body().string(); logger.info("回调建科用户接口返回:" + responseBody); if (!response.isSuccessful()) { logger.error("回调建科用户接口失败 " + responseBody); i++; continue; } JSONObject jsonObject =JSON.parseObject(responseBody); //“0”为成功其余均为失败 String code = jsonObject.getString("code"); if (CODE_SUCCESS.equals(code)) { return true; } } catch (Exception e) { logger.error("回调建科用户接口息失败 ", e); i++; } } return false; } public Map getJkToken(String code, String redirectUrl) throws IOException { String token = ""; JSONObject userJson = null; try { Request request = buildTokenRequest(code, redirectUrl); Response response = client.newCall(request).execute(); String responseBody = response.body().string(); logger.info("获取建科token返回信息:{}", responseBody); if (!response.isSuccessful()) { throw new IOException("获取建科token信息失败 " + responseBody); } JSONObject jsonObject = JSON.parseObject(responseBody); token = jsonObject.getString("access_token"); if (!StringUtils.isEmpty(token)) { // token 换取用户信息 Request pReq = buildProfileRequest(token); Response pResp = client.newCall(pReq).execute(); String pRespBody = pResp.body().string(); if (!pResp.isSuccessful()) { throw new IOException("token换取建科用户信息失败 " + pRespBody); } userJson = JSON.parseObject(pRespBody); logger.info("获取建科用户返回信息:{}", userJson.toJSONString()); } } catch (IOException e) { logger.error("获取建科token失败,code:{}", code, e); throw new IOException("获取建科token信息失败 ", e); } if (userJson == null) { return null; } JSONObject attrs = userJson.getJSONObject("attributes"); Map map = new HashMap<>(); map.put("userId", attrs.getString("account_no")); map.put("nickName", attrs.getString("account_no")); map.put("token", token); return map; } private String createJkToken() { JWTCreator.Builder builder = JWT.create().withIssuer(jkConfig.getIamAppid()); String sign = builder.withIssuedAt(new Date()).withJWTId(UUID.randomUUID().toString()).sign(Algorithm.HMAC256(jkConfig.getIamAppsecret())); String token = String.join(" ", BEARER, sign); return token; } private Request buildRequest(String url,int page) { Map requestBodyMap = new HashMap<>(); requestBodyMap.put(PARAM_ST, getStartTimeBeforeDays(BEFORE_DAYS)); requestBodyMap.put(PARAM_PAGE, page); requestBodyMap.put(PARAM_SIZE, DEFAULT_SIZE); // 将 Map 转换为 JSON 字符串 String requestBodyJson = JSON.toJSONString(requestBodyMap); // 构建请求体 RequestBody body = RequestBody.create(JSON_UTF8,requestBodyJson); Request request = new Request.Builder() .addHeader("accept", "*/*") .addHeader("Authorization", createJkToken()) .addHeader("Content-Type", "application/json") .post(body) .url(url).build(); logger.info("请求head:{}", request.headers().toString()); logger.info("请求body:{}", requestBodyJson); return request; } private Request buildPostRequest(String url) { Map requestBodyMap = new HashMap<>(); requestBodyMap.put("projectCode", ""); // 将 Map 转换为 JSON 字符串 String requestBodyJson = JSON.toJSONString(requestBodyMap); // 构建请求体 RequestBody body = RequestBody.create(JSON_UTF8,requestBodyJson); Request request = new Request.Builder() .addHeader("accept", "*/*") .addHeader("Content-Type", "application/json") .post(body) .url(url).build(); logger.info("请求head:{}", request.headers().toString()); logger.info("请求body:{}", requestBodyJson); return request; } private Request buildTokenRequest(String code, String redirectUrl) { String completeUrl = jkConfig.getIamTokenUrl() + "?" +PARAM_GRANT_TYPE + "=" + GRANT_TYPE_AC + "&" +PARAM_CLIENT_ID + "=" + jkConfig.getIamClientID() + "&" +PARAM_CLIENT_SECRET + "=" + jkConfig.getIamClientSecret() + "&" +PARAM_CODE + "=" + code + "&" +PARAM_REDIRECT_URI + "=" + redirectUrl; // 构建请求体 RequestBody body = RequestBody.create(JSON_UTF8,""); Request request = new Request.Builder() .addHeader("accept", "*/*") .addHeader("Content-Type", "application/json") .post(body) .url(completeUrl).build(); logger.info("code换取token接口请求head:{}", request.headers().toString()); logger.info("code换取token接口请求url:{}", completeUrl); return request; } private Request buildCallbackRequest(String ids) { Map requestBodyMap = new HashMap<>(); requestBodyMap.put(PARAM_IDS, ids); requestBodyMap.put(PARAM_ERRORS, new ArrayList<>()); // 将 Map 转换为 JSON 字符串 String requestBodyJson = JSON.toJSONString(requestBodyMap); // 构建请求体 RequestBody body = RequestBody.create(JSON_UTF8,requestBodyJson); Request request = new Request.Builder() .addHeader("accept", "*/*") .addHeader("Authorization", createJkToken()) .addHeader("Content-Type", "application/json") .post(body) .url(jkConfig.getIamCallbackUrl()).build(); logger.info("回调接口请求head:{}", request.headers().toString()); logger.info("回调接口请求body:{}", requestBodyJson); return request; } private Request buildProfileRequest(String token) { // 构建带参数的 URL HttpUrl.Builder urlBuilder = HttpUrl.parse(jkConfig.getIamProfileUrl()).newBuilder(); urlBuilder.addQueryParameter(PARAM_ACCESS_TOKEN, token); String url = urlBuilder.build().toString(); Request request = new Request.Builder() .url(url) .get() .build(); logger.info("token获取用户信息请求url", url); return request; } private String getStartTimeBeforeDays(int days) { //7天内数据 return String.valueOf(DateUtils.getTimeBeforeDays(days)); } private boolean isJsonObject(String data) { try { JSON.parseObject(data); return true; } catch (Exception e) { return false; } } private OkHttpClient buildOkHttpClient() { return new OkHttpClient.Builder() .connectTimeout(60, TimeUnit.SECONDS) .writeTimeout(50, TimeUnit.SECONDS) .readTimeout(60, TimeUnit.MINUTES) .build(); } }