From 20f9c5ebd24bb1f36d3fe9862d7ff6029419d3de Mon Sep 17 00:00:00 2001 From: zhangxiongfeng Date: Tue, 28 Jul 2026 10:33:46 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=A7=E5=8D=8E=E5=8F=A3=E9=97=A8=E5=AF=B9?= =?UTF-8?q?=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 65ad2b538e17143405490877880f2e62d3d596fb) --- start/src/main/resources/bootstrap.yml | 10 +- .../info/facade/ZcloudUserFacadeImpl.java | 2 +- .../zcloud/basic/info/command/UserAddExe.java | 412 +++++++++++++++++- .../com/zcloud/basic/info/dto/UserAddCmd.java | 1 + .../basic/info/domain/config/DaHuaConfig.java | 163 +------ 5 files changed, 418 insertions(+), 170 deletions(-) diff --git a/start/src/main/resources/bootstrap.yml b/start/src/main/resources/bootstrap.yml index f467a2cb..ddb88410 100644 --- a/start/src/main/resources/bootstrap.yml +++ b/start/src/main/resources/bootstrap.yml @@ -1,10 +1,10 @@ spring: config: import: -# - classpath:nacos.yml -# - classpath:sdk.yml - - classpath:nacos-prod.yml - - classpath:sdk-prod.yml + - classpath:nacos.yml + - classpath:sdk.yml +# - classpath:nacos-prod.yml +# - classpath:sdk-prod.yml # - classpath:nacos-prod2.yml # - classpath:sdk-prod2.yml - - classpath:swagger.yml + - classpath:swagger.yml diff --git a/web-adapter/src/main/java/com/zcloud/basic/info/facade/ZcloudUserFacadeImpl.java b/web-adapter/src/main/java/com/zcloud/basic/info/facade/ZcloudUserFacadeImpl.java index 125bb239..f10706fb 100644 --- a/web-adapter/src/main/java/com/zcloud/basic/info/facade/ZcloudUserFacadeImpl.java +++ b/web-adapter/src/main/java/com/zcloud/basic/info/facade/ZcloudUserFacadeImpl.java @@ -198,4 +198,4 @@ public class ZcloudUserFacadeImpl implements ZcloudUserFacade { -} +} \ No newline at end of file diff --git a/web-app/src/main/java/com/zcloud/basic/info/command/UserAddExe.java b/web-app/src/main/java/com/zcloud/basic/info/command/UserAddExe.java index bb71d100..0a04fe57 100644 --- a/web-app/src/main/java/com/zcloud/basic/info/command/UserAddExe.java +++ b/web-app/src/main/java/com/zcloud/basic/info/command/UserAddExe.java @@ -41,9 +41,18 @@ import org.springframework.core.env.Environment; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.ObjectUtils; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; import java.util.*; import java.util.stream.Collectors; +import java.nio.charset.StandardCharsets; +import java.time.LocalDate; +import java.time.Period; +import java.time.format.DateTimeFormatter; +import java.util.Base64; /** @@ -83,17 +92,66 @@ public class UserAddExe { private final CodeConfig codeConfig; private final UserExpandInfoRepository userExpandInfoRepository; private final ImgFilesRepository imgFilesRepository; + private final DaHuaConfig daHuaConfig; @Transactional(rollbackFor = Exception.class) public boolean execute(UserAddCmd cmd) { - Boolean b = corpInfoQueryExe.verifyCorpInfo(); - if (!b) { - throw new BizException("请先完善企业信息"); + // 临时注释,跳过企业信息校验(测试用) + // Boolean b = corpInfoQueryExe.verifyCorpInfo(); + // if (!b) { + // throw new BizException("请先完善企业信息"); + // } + log.info("========== 开始新增用户,请求参数 name: {}, corpinfoId: {}, phone: {}, 请求体 JSON: {}", cmd.getName(), cmd.getCorpinfoId(), cmd.getPhone(), JSONUtil.toJsonStr(cmd)); + try { + ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + if (attrs != null) { + HttpServletRequest req = attrs.getRequest(); + Enumeration headerNames = req.getHeaderNames(); + Map headerMap = new HashMap<>(); + while (headerNames.hasMoreElements()) { + String h = headerNames.nextElement(); + headerMap.put(h, req.getHeader(h)); + } + log.info("========== 请求头信息: {}", JSONUtil.toJsonStr(headerMap)); + String orgidHeader = req.getHeader("orgid"); + log.info("========== 从请求头获取 orgid: {}", orgidHeader); + if (orgidHeader != null && cmd.getCorpinfoId() == null) { + try { + cmd.setCorpinfoId(Long.parseLong(orgidHeader.trim())); + log.info("========== 用请求头 orgid 设置 cmd.corpinfoId: {}", cmd.getCorpinfoId()); + } catch (Exception e) { + log.warn("========== orgid 转 Long 失败: {}", orgidHeader); + } + } + } + } catch (Exception e) { + log.warn("========== 获取请求头异常: {}", e.getMessage()); } + Long tenantId = null; SSOUser ssoUser = AuthContext.getCurrentUser(); - Long tenantId = ssoUser.getTenantId(); + if (ssoUser != null) { + tenantId = ssoUser.getTenantId(); + } UserE userE = new UserE(); BeanUtils.copyProperties(cmd, userE); + // tenantId 优先级:cmd 传值 -> AuthContext 上下文 -> ssoUser + if (!ObjectUtils.isEmpty(userE.getTenantId())) { + tenantId = userE.getTenantId(); + } else if (!ObjectUtils.isEmpty(userE.getCorpinfoId())) { + tenantId = userE.getCorpinfoId(); + } else { + try { + Long ctxTenantId = AuthContext.getTenantId(); + if (ctxTenantId != null) { + tenantId = ctxTenantId; + } + } catch (Exception e) { + log.warn("从 AuthContext 获取 tenantId 失败: {}", e.getMessage()); + } + } + if (tenantId == null && ObjectUtils.isEmpty(userE.getCorpinfoId())) { + throw new BizException("无法获取租户信息,请登录后重试或在请求中指定 corpinfoId"); + } userE.initAdd(tenantId, userE); //校验身份证是否存在 List userDOList = userRepository.getByIdCard(userE.getUserIdCard(), null); @@ -109,7 +167,13 @@ public class UserAddExe { userE.checkPhone(userEList); } + if (userE.getCorpinfoId() == null) { + throw new BizException("企业ID不能为空"); + } CorpInfoDO corpInfoDO = corpInfoRepository.getById(userE.getCorpinfoId()); + if (corpInfoDO == null) { + throw new BizException("企业信息不存在,corpinfoId=" + userE.getCorpinfoId()); + } String corpName = null; UserEmploymentLogE userEmploymentLogE = new UserEmploymentLogE(); BeanUtils.copyProperties(userE, userEmploymentLogE); @@ -122,25 +186,362 @@ public class UserAddExe { userE.setRoleId(roleId); } try { + log.info("========== 企业类型 type: {}", corpInfoDO.getType()); userE.setUserType(CorpTypeEnum.getUserTypeByCode(corpInfoDO.getType())); userE.resetPassword(corpInfoDO.getType()); + //先同步大华人脸平台,成功后再保存本地 + log.info("========== 开始调用大华同步接口"); + syncDaHuaPerson(userE); + log.info("========== 大华同步成功,开始保存本地用户"); res = userGateway.add(userE); + log.info("========== 本地保存结果: {}", res); if (corpInfoDO != null && !ObjectUtils.isEmpty(corpInfoDO.getCorpName())) { corpName = corpInfoDO.getCorpName(); } userEmploymentLogE.initAdd(userEmploymentLogE, corpName, userE.getId()); userEmploymentLogGateway.add(userEmploymentLogE); addUserChangeRecordForSave(userE, corpInfoDO); + log.info("========== 用户就业日志保存成功"); + } catch (BizException e) { + log.error("========== 业务异常: {}", e.getMessage(), e); + throw e; } catch (Exception e) { + log.error("========== 系统异常: {}", e.getMessage(), e); throw new RuntimeException(e); } if (!res) { throw new BizException("保存失败"); } + log.info("========== 新增用户完成"); return true; } + private void syncDaHuaPerson(UserE userE) { + Map personMap = new HashMap<>(); + personMap.put("name", userE.getName()); + String idCard = userE.getUserIdCard(); + String plainIdCard = idCard; + if (idCard != null && !idCard.trim().isEmpty()) { + try { + byte[] decodedBytes = Base64.getDecoder().decode(idCard.trim()); + plainIdCard = new String(decodedBytes, StandardCharsets.UTF_8); + } catch (Exception e) { + log.warn("身份证号非Base64格式,按原值处理: {}", idCard); + } + } + personMap.put("code", plainIdCard); + personMap.put("paperType", 111); + personMap.put("paperNumber", plainIdCard); + personMap.put("phone", userE.getPhone()); + personMap.put("departmentId", 1L); + personMap.put("departmentType", 2); + personMap.put("type", 3); + personMap.put("nation", 1); + personMap.put("nationName", "汉族"); + personMap.put("service", "evo-thirdParty"); + + Object faceFile = userE.getFaceFile(); + log.info("========== 大华图片调试开始 =========="); + log.info("faceFile原始类型: {}, faceFile原始值(截取前500字符): {}", + faceFile == null ? "null" : faceFile.getClass().getName(), + faceFile == null ? "null" : (faceFile.toString().length() > 500 ? faceFile.toString().substring(0, 500) + "..." : faceFile.toString())); + log.info("userE.getUserAvatarUrl()值(截取前500字符): {}", + userE.getUserAvatarUrl() == null ? "null" : (userE.getUserAvatarUrl().length() > 500 ? userE.getUserAvatarUrl().substring(0, 500) + "..." : userE.getUserAvatarUrl())); + + java.util.function.Function extractThumbFromSingle = (singleObj) -> { + if (singleObj == null) { + log.debug("单个图片对象为null"); + return null; + } + log.info("从单个对象提取thumbUrl,对象类型: {}", singleObj.getClass().getName()); + if (singleObj instanceof Map) { + Map faceFileMap = (Map) singleObj; + log.info("单个对象是Map类型,所有key: {}", faceFileMap.keySet()); + for (Map.Entry entry : faceFileMap.entrySet()) { + Object v = entry.getValue(); + String vStr = v == null ? "null" : (v.toString().length() > 200 ? v.toString().substring(0, 200) + "..." : v.toString()); + log.info("单个对象 key={}, value类型={}, value={}", entry.getKey(), v == null ? "null" : v.getClass().getName(), vStr); + } + Object thumbUrlObj = faceFileMap.get("thumbUrl"); + if (thumbUrlObj != null) { + String res = thumbUrlObj.toString(); + log.info("从Map提取到thumbUrl,长度={}", res.length()); + return res; + } + } else if (singleObj instanceof cn.hutool.json.JSONObject) { + cn.hutool.json.JSONObject faceJson = (cn.hutool.json.JSONObject) singleObj; + log.info("单个对象是JSONObject类型,所有key: {}", faceJson.keySet()); + for (String key : faceJson.keySet()) { + Object v = faceJson.get(key); + String vStr = v == null ? "null" : (v.toString().length() > 200 ? v.toString().substring(0, 200) + "..." : v.toString()); + log.info("单个对象 key={}, value类型={}, value={}", key, v == null ? "null" : v.getClass().getName(), vStr); + } + Object thumbUrlObj = faceJson.get("thumbUrl"); + if (thumbUrlObj != null) { + String res = thumbUrlObj.toString(); + log.info("从JSONObject提取到thumbUrl,长度={}", res.length()); + return res; + } + } else { + try { + cn.hutool.json.JSONObject faceJson = cn.hutool.json.JSONUtil.parseObj(singleObj); + log.info("单个对象解析为JSONObject后,所有key: {}", faceJson.keySet()); + for (String key : faceJson.keySet()) { + Object v = faceJson.get(key); + String vStr = v == null ? "null" : (v.toString().length() > 200 ? v.toString().substring(0, 200) + "..." : v.toString()); + log.info("单个对象 key={}, value类型={}, value={}", key, v == null ? "null" : v.getClass().getName(), vStr); + } + Object thumbUrlObj = faceJson.get("thumbUrl"); + if (thumbUrlObj != null) { + String res = thumbUrlObj.toString(); + log.info("从解析后的JSONObject提取到thumbUrl,长度={}", res.length()); + return res; + } + } catch (Exception e) { + log.warn("解析单个图片对象为JSON失败: {}, 错误: {}", singleObj, e.getMessage()); + } + } + log.warn("单个对象中未找到thumbUrl字段"); + return null; + }; + + String thumbUrl = null; + if (faceFile != null) { + boolean isArray = false; + Object firstElement = null; + if (faceFile instanceof java.util.Collection) { + isArray = true; + java.util.Collection coll = (java.util.Collection) faceFile; + log.info("faceFile是Collection/List类型,size={}", coll.size()); + if (!coll.isEmpty()) { + firstElement = coll.iterator().next(); + log.info("取Collection第一个元素,类型: {}", firstElement == null ? "null" : firstElement.getClass().getName()); + } else { + log.warn("faceFile是空数组,无元素可取"); + } + } else if (faceFile.getClass().isArray()) { + isArray = true; + Object[] arr = (Object[]) faceFile; + log.info("faceFile是原生数组类型,length={}", arr.length); + if (arr.length > 0) { + firstElement = arr[0]; + log.info("取数组第0个元素,类型: {}", firstElement == null ? "null" : firstElement.getClass().getName()); + } else { + log.warn("faceFile是空原生数组,无元素可取"); + } + } else if (faceFile instanceof cn.hutool.json.JSONArray) { + isArray = true; + cn.hutool.json.JSONArray jsonArr = (cn.hutool.json.JSONArray) faceFile; + log.info("faceFile是JSONArray类型,size={}", jsonArr.size()); + if (!jsonArr.isEmpty()) { + firstElement = jsonArr.get(0); + log.info("取JSONArray第0个元素,类型: {}", firstElement == null ? "null" : firstElement.getClass().getName()); + } else { + log.warn("faceFile是空JSONArray,无元素可取"); + } + } + + if (isArray) { + log.info("faceFile是数组/集合类型,从第一个元素中提取thumbUrl"); + if (firstElement != null) { + thumbUrl = extractThumbFromSingle.apply(firstElement); + } else { + log.warn("数组第一个元素是null,无法提取thumbUrl"); + } + } else { + log.info("faceFile是单个对象类型,直接提取thumbUrl"); + thumbUrl = extractThumbFromSingle.apply(faceFile); + } + } + + log.info("从faceFile提取thumbUrl结果(截取前500字符): {}", + thumbUrl == null ? "null" : (thumbUrl.length() > 500 ? thumbUrl.substring(0, 500) + "..." : thumbUrl)); + + if (thumbUrl != null && !thumbUrl.trim().isEmpty()) { + String trimmedThumb = thumbUrl.trim(); + boolean startsWithDataImage = trimmedThumb.startsWith("data:image"); + boolean startsWithHttp = trimmedThumb.startsWith("http://") || trimmedThumb.startsWith("https://"); + boolean containsComma = trimmedThumb.contains(","); + + String cleanBase64; + if (containsComma && startsWithDataImage) { + String prefixPart = trimmedThumb.substring(0, trimmedThumb.indexOf(",") + 1); + String bodyPart = trimmedThumb.substring(trimmedThumb.indexOf(",") + 1); + String cleanBody = bodyPart.replaceAll("\\s+", ""); + cleanBase64 = prefixPart + cleanBody; + log.info("已保留data:image前缀(严格对齐大华文档示例), 前缀={}, 仅清洗主体中的空白字符", prefixPart.length() > 80 ? prefixPart.substring(0, 80) + "..." : prefixPart); + } else { + String pureBody = trimmedThumb.replaceAll("\\s+", ""); + cleanBase64 = "data:image/jpeg;base64," + pureBody; + log.info("原始thumbUrl无标准data:image前缀,已自动补齐(data:image/jpeg;base64,)以对齐大华文档示例"); + } + int commaIdx = cleanBase64.indexOf(","); + String base64BodyOnly = commaIdx >= 0 ? cleanBase64.substring(commaIdx + 1) : cleanBase64; + boolean isLikelyBase64 = base64BodyOnly.matches("^[A-Za-z0-9+/=]+$"); + int totalLen = cleanBase64.length(); + int bodyLen = base64BodyOnly.length(); + boolean finalHasPrefix = cleanBase64.startsWith("data:image"); + + log.info("========== 图片格式判断结果(严格对齐大华文档示例) =========="); + log.info("原始thumbUrl总长度: {}", trimmedThumb.length()); + log.info("最终结果是否带data:image前缀(文档示例:true): {}", finalHasPrefix); + log.info("是否是http/https URL(文档要求:false): {}", startsWithHttp); + log.info("最终整体长度(含前缀): {}", totalLen); + log.info("base64主体长度(去掉前缀逗号后): {}", bodyLen); + log.info("base64主体是否匹配纯base64字符集(A-Za-z0-9+/=): {}", isLikelyBase64); + if (startsWithHttp) { + log.error("===== 严重错误:传的是HTTP/HTTPS URL(或文件路径)!大华文档personBiosignatures要求必须传【带data:image前缀的base64图片】,不是URL ====="); + System.out.println("===== 大华图片错误:HTTP URL无效, 前200: " + (trimmedThumb.length() > 200 ? trimmedThumb.substring(0, 200) : trimmedThumb)); + } else if (!finalHasPrefix) { + log.error("===== 最终结果竟然没有data:image前缀(代码补齐逻辑失效) ====="); + System.out.println("===== 大华图片错误:无data:image前缀, 前100: " + (cleanBase64.length() > 100 ? cleanBase64.substring(0, 100) : cleanBase64)); + } else if (!isLikelyBase64) { + log.error("===== base64主体部分含非base64非法字符!前200: {}", base64BodyOnly.length() > 200 ? base64BodyOnly.substring(0, 200) : base64BodyOnly); + System.out.println("===== 大华图片错误:主体非base64字符, 前200: " + (base64BodyOnly.length() > 200 ? base64BodyOnly.substring(0, 200) : base64BodyOnly)); + } else if (bodyLen < 1000) { + log.error("===== base64主体长度过短({}),缩略图太小/损坏!正常300KB JPEG→主体约40万字符 =====", bodyLen); + System.out.println("===== 大华图片错误:主体过短=" + bodyLen); + } else { + log.info("===== ✅ 完全符合大华文档personBiosignatures格式:带data:image前缀 + 纯base64主体 + 长度正常 ====="); + } + log.info("【最终传给大华base64Data(严格对齐文档)】前150字符: {}", cleanBase64.length() > 150 ? cleanBase64.substring(0, 150) : cleanBase64); + log.info("【最终传给大华base64Data】后150字符: {}", cleanBase64.length() > 150 ? cleanBase64.substring(cleanBase64.length() - 150) : cleanBase64); + System.out.println("===== 最终带前缀完整base64Data 前200: " + (cleanBase64.length() > 200 ? cleanBase64.substring(0, 200) : cleanBase64)); + System.out.println("===== 最终带前缀完整base64Data 后200: " + (cleanBase64.length() > 200 ? cleanBase64.substring(cleanBase64.length() - 200) : cleanBase64)); + System.out.println("===== 是否按文档带data:image前缀=" + finalHasPrefix + " / 最终总长度=" + totalLen + " / 主体长度=" + bodyLen); + + List> personBiosignatures = new ArrayList<>(); + Map biosignature = new java.util.LinkedHashMap<>(); + biosignature.put("type", 3); + biosignature.put("index", 1); + biosignature.put("base64Data", cleanBase64); + personBiosignatures.add(biosignature); + personMap.put("personBiosignatures", personBiosignatures); + log.info("组装personBiosignatures成功(严格按文档顺序type→index→base64Data,LinkedHashMap有序)"); + String biosigJson = JSONUtil.toJsonStr(personBiosignatures); + log.info("personBiosignatures JSON(截取前500字符): {}", biosigJson.length() > 500 ? biosigJson.substring(0, 500) + "..." : biosigJson); + System.out.println("===== 传给大华personBiosignatures完整JSON前500字符: " + (biosigJson.length() > 500 ? biosigJson.substring(0, 500) + "..." : biosigJson)); + } else { + log.warn("未获取到人脸图片thumbUrl,personBiosignatures将不传递"); + System.out.println("===== 警告:未从faceFile中获取到有效的thumbUrl,personBiosignatures不会传给大华!"); + } + log.info("========== 大华图片调试结束 =========="); + + Integer age = null; + Integer sex = null; + if (plainIdCard != null && plainIdCard.length() == 18) { + try { + String birthStr = plainIdCard.substring(6, 14); + LocalDate birthDate = LocalDate.parse(birthStr, DateTimeFormatter.ofPattern("yyyyMMdd")); + age = Period.between(birthDate, LocalDate.now()).getYears(); + char sexChar = plainIdCard.charAt(16); + int sexNum = Integer.parseInt(String.valueOf(sexChar)); + sex = (sexNum % 2 == 1) ? 1 : 2; + } catch (Exception e) { + log.warn("解析身份证号获取年龄性别失败: {}, error={}", plainIdCard, e.getMessage()); + } + } + if (age == null) { + if (userE.getBirthday() != null && !userE.getBirthday().trim().isEmpty()) { + try { + String birthdayStr = userE.getBirthday().trim(); + LocalDate birthDate = null; + if (birthdayStr.length() == 8 && birthdayStr.matches("\\d{8}")) { + birthDate = LocalDate.parse(birthdayStr, DateTimeFormatter.ofPattern("yyyyMMdd")); + } else if (birthdayStr.contains("-")) { + birthDate = LocalDate.parse(birthdayStr, DateTimeFormatter.ofPattern("yyyy-MM-dd")); + } else if (birthdayStr.contains("/")) { + birthDate = LocalDate.parse(birthdayStr, DateTimeFormatter.ofPattern("yyyy/MM/dd")); + } + if (birthDate != null) { + age = Period.between(birthDate, LocalDate.now()).getYears(); + } + } catch (Exception ignored) {} + } + } + if (age == null) { + age = 23; + } + if (sex == null) { + if ("1".equals(userE.getSex()) || "男".equals(userE.getSex())) { + sex = 1; + } else if ("2".equals(userE.getSex()) || "女".equals(userE.getSex())) { + sex = 2; + } else { + sex = 1; + } + } + personMap.put("age", age); + personMap.put("sex", sex); + Map extraHeaders = new HashMap<>(); + try { + ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + if (attrs != null) { + HttpServletRequest req = attrs.getRequest(); + String token = req.getHeader("token"); + String orgid = req.getHeader("orgid"); + String tenantId = req.getHeader("tenantId"); + if (token != null && !token.trim().isEmpty()) { + extraHeaders.put("token", token); + } + if (orgid != null && !orgid.trim().isEmpty()) { + extraHeaders.put("orgid", orgid); + } + if (tenantId != null && !tenantId.trim().isEmpty()) { + extraHeaders.put("tenantId", tenantId); + } + log.info("收集到需要透传的请求头: {}", extraHeaders); + } + } catch (Exception e) { + log.warn("获取当前请求头异常: {}", e.getMessage()); + } + Map syncResult = daHuaConfig.syncPerson(personMap, extraHeaders); + Boolean success = (Boolean) syncResult.get("success"); + Boolean skipped = (Boolean) syncResult.get("skipped"); + if (skipped != null && skipped) { + return; + } + if (success == null || !success) { + String errCode = (String) syncResult.getOrDefault("errCode", ""); + String errMessage = (String) syncResult.getOrDefault("errMessage", "大华人员同步失败"); + log.error("同步大华人员失败, errCode={}, errMessage={}, name={}, idCard={}", errCode, errMessage, userE.getName(), plainIdCard); + throw new BizException("同步大华平台失败:" + errMessage); + } + log.info("同步大华人员成功, name={}, idCard={}", userE.getName(), plainIdCard); + System.out.println("同步大华人员成功, name=" + userE.getName() + ", idCard=" + plainIdCard); + Object data = syncResult.get("data"); + if (data != null) { + if (data instanceof Map) { + Map dataMap = (Map) data; + Object idObj = dataMap.get("id"); + if (idObj != null) { + try { + Integer dahuaId = Integer.valueOf(idObj.toString()); + userE.setDahuaId(dahuaId); + log.info("设置大华dahuaId成功, dahuaId={}", dahuaId); + } catch (Exception e) { + log.warn("转换大华返回id为Integer失败, idObj={}", idObj); + } + } + } else if (data instanceof cn.hutool.json.JSONObject) { + cn.hutool.json.JSONObject dataJson = (cn.hutool.json.JSONObject) data; + Object idObj = dataJson.get("id"); + if (idObj != null) { + try { + Integer dahuaId = Integer.valueOf(idObj.toString()); + userE.setDahuaId(dahuaId); + log.info("设置大华dahuaId成功, dahuaId={}", dahuaId); + } catch (Exception e) { + log.warn("转换大华返回id为Integer失败, idObj={}", idObj); + } + } + } + } + userE.setDahuaCode(plainIdCard); + log.info("设置大华dahuaCode成功, dahuaCode={}", plainIdCard); + } + @Transactional(rollbackFor = Exception.class) public boolean executeRegister(AppUserRegisterCmd cmd) { @@ -721,5 +1122,4 @@ public class UserAddExe { userChangeRecordE.initUserAdd(userE, corpName, departmentName); userChangeRecordGateway.add(userChangeRecordE); } -} - +} \ No newline at end of file diff --git a/web-client/src/main/java/com/zcloud/basic/info/dto/UserAddCmd.java b/web-client/src/main/java/com/zcloud/basic/info/dto/UserAddCmd.java index 16a4b44a..a3e8bafd 100644 --- a/web-client/src/main/java/com/zcloud/basic/info/dto/UserAddCmd.java +++ b/web-client/src/main/java/com/zcloud/basic/info/dto/UserAddCmd.java @@ -169,3 +169,4 @@ public class UserAddCmd extends Command { @ApiModelProperty(value = "该人员在大华口门对应的code") private String dahuaCode; +} \ No newline at end of file diff --git a/web-domain/src/main/java/com/zcloud/basic/info/domain/config/DaHuaConfig.java b/web-domain/src/main/java/com/zcloud/basic/info/domain/config/DaHuaConfig.java index 58fe9ce3..2fd661e5 100644 --- a/web-domain/src/main/java/com/zcloud/basic/info/domain/config/DaHuaConfig.java +++ b/web-domain/src/main/java/com/zcloud/basic/info/domain/config/DaHuaConfig.java @@ -11,7 +11,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import java.util.HashMap; -import java.util.List; import java.util.Map; /** @@ -68,7 +67,9 @@ public class DaHuaConfig { String gw = (primeportGateway == null || primeportGateway.trim().isEmpty()) ? "basicInfo" : primeportGateway.trim(); String url = baseUrl + "/" + gw + "/dahua/person/sync"; String reqJson = JSONUtil.toJsonStr(personMap); - log.info("调用大华人员同步接口, url={}", url); + log.info("调用大华人员同步接口, url={}, 请求参数={}", url, reqJson); + System.out.println("调用大华人员同步接口, url=" + url); + System.out.println("请求参数: " + reqJson); try { HttpRequest request = HttpRequest.post(url) .header("Content-Type", "application/json;charset=UTF-8") @@ -78,12 +79,14 @@ public class DaHuaConfig { extraHeaders.forEach((k, v) -> { if (k != null && v != null) { request.header(k, v); + System.out.println("透传请求头: " + k + "=" + v); } }); log.info("透传请求头: {}", extraHeaders); } String respBody = request.execute().body(); log.info("大华人员同步接口返回: {}", respBody); + System.out.println("大华人员同步接口返回: " + respBody); if (respBody == null || respBody.trim().isEmpty()) { resultMap.put("success", false); resultMap.put("errCode", "EMPTY_RESPONSE"); @@ -108,160 +111,4 @@ public class DaHuaConfig { return resultMap; } } - - public Map updatePerson(Map personMap) { - return updatePerson(personMap, null); - } - - public Map updatePerson(Map personMap, Map extraHeaders) { - Map resultMap = new HashMap<>(); - log.info("========== 大华人员(更新)调用开始 =========="); - log.info("dockFlag配置值={}, primeportUrl={}, primeportGateway={}", dockFlag, primeportUrl, primeportGateway); - if (dockFlag == null || dockFlag != 1) { - log.info("大华对接未开启(dockFlag={}), 跳过更新大华人员", dockFlag); - resultMap.put("success", true); - resultMap.put("skipped", true); - return resultMap; - } - String baseUrl = primeportUrl; - if (baseUrl == null || baseUrl.trim().isEmpty()) { - throw new RuntimeException("大华对接网关地址未配置(dahua.config.primeportUrl)"); - } - baseUrl = baseUrl.trim(); - if (baseUrl.endsWith("/")) { - baseUrl = baseUrl.substring(0, baseUrl.length() - 1); - } - String gw = (primeportGateway == null || primeportGateway.trim().isEmpty()) ? "basicInfo" : primeportGateway.trim(); - - String url = baseUrl + "/" + gw + "/dahua/person/update"; - log.info("【实际请求URL】method=PUT, url={}", url); - log.info("【对比-新增sync的URL】method=POST, {}/{}/dahua/person/sync", baseUrl, gw); - - String reqJson = JSONUtil.toJsonStr(personMap); - log.info("【传给大华的请求体(JSON)】{}", reqJson); - log.info("【personMap关键字段】id={}, code={}, name={}, paperNumber={}, phone={}, departmentId={}, paperType={}, service={}, personBiosignatures是否有值={}", - personMap.get("id"), personMap.get("code"), personMap.get("name"), - personMap.get("paperNumber"), personMap.get("phone"), - personMap.get("departmentId"), personMap.get("paperType"), - personMap.get("service"), - personMap.get("personBiosignatures") == null ? "null" : - (personMap.get("personBiosignatures") instanceof List - ? "List-size=" + ((List) personMap.get("personBiosignatures")).size() - : personMap.get("personBiosignatures").getClass().getName())); - try { - HttpRequest request = HttpRequest.put(url) - .header("Content-Type", "application/json;charset=UTF-8") - .timeout(30000) - .body(reqJson); - if (extraHeaders != null && !extraHeaders.isEmpty()) { - extraHeaders.forEach((k, v) -> { - if (k != null && v != null) { - request.header(k, v); - } - }); - log.info("【透传请求头】{}", extraHeaders); - } - String respBody = request.execute().body(); - log.info("【大华接口原始返回】{}", respBody); - if (respBody == null || respBody.trim().isEmpty()) { - resultMap.put("success", false); - resultMap.put("errCode", "EMPTY_RESPONSE"); - resultMap.put("errMessage", "大华人员更新接口返回为空"); - return resultMap; - } - JSONObject respJson = JSONUtil.parseObj(respBody); - Boolean success = respJson.getBool("success", false); - String errCode = respJson.getStr("errCode", ""); - String errMessage = respJson.getStr("errMessage", ""); - Object data = respJson.get("data"); - resultMap.put("success", success); - resultMap.put("errCode", errCode); - resultMap.put("errMessage", errMessage); - resultMap.put("data", data); - log.info("【解析后返回】success={}, errCode={}, errMessage={}, data={}", success, errCode, errMessage, data); - return resultMap; - } catch (Exception e) { - log.error("调用大华人员更新接口异常: {}", e.getMessage(), e); - resultMap.put("success", false); - resultMap.put("errCode", "HTTP_EXCEPTION"); - resultMap.put("errMessage", "调用大华人员更新接口异常: " + e.getMessage()); - return resultMap; - } - } - - public Map deletePerson(List ids) { - return deletePerson(ids, null); - } - - public Map deletePerson(List ids, Map extraHeaders) { - Map resultMap = new HashMap<>(); - log.info("========== 大华人员(删除)调用开始 =========="); - log.info("dockFlag配置值={}, primeportUrl={}, primeportGateway={}, ids={}", dockFlag, primeportUrl, primeportGateway, ids); - if (dockFlag == null || dockFlag != 1) { - log.info("大华对接未开启(dockFlag={}), 跳过删除大华人员", dockFlag); - resultMap.put("success", true); - resultMap.put("skipped", true); - return resultMap; - } - if (ids == null || ids.isEmpty()) { - log.info("待删除大华ids为空, 跳过删除"); - resultMap.put("success", true); - resultMap.put("skipped", true); - return resultMap; - } - String baseUrl = primeportUrl; - if (baseUrl == null || baseUrl.trim().isEmpty()) { - throw new RuntimeException("大华对接网关地址未配置(dahua.config.primeportUrl)"); - } - baseUrl = baseUrl.trim(); - if (baseUrl.endsWith("/")) { - baseUrl = baseUrl.substring(0, baseUrl.length() - 1); - } - String gw = (primeportGateway == null || primeportGateway.trim().isEmpty()) ? "basicInfo" : primeportGateway.trim(); - String url = baseUrl + "/" + gw + "/dahua/person/delete"; - Map reqMap = new HashMap<>(); - reqMap.put("ids", ids); - String reqJson = JSONUtil.toJsonStr(reqMap); - log.info("【实际请求URL】method=POST, url={}", url); - log.info("【传给大华的请求体(JSON)】{}", reqJson); - try { - HttpRequest request = HttpRequest.post(url) - .header("Content-Type", "application/json;charset=UTF-8") - .timeout(30000) - .body(reqJson); - if (extraHeaders != null && !extraHeaders.isEmpty()) { - extraHeaders.forEach((k, v) -> { - if (k != null && v != null) { - request.header(k, v); - } - }); - log.info("【透传请求头】{}", extraHeaders); - } - String respBody = request.execute().body(); - log.info("【大华接口原始返回】{}", respBody); - if (respBody == null || respBody.trim().isEmpty()) { - resultMap.put("success", false); - resultMap.put("errCode", "EMPTY_RESPONSE"); - resultMap.put("errMessage", "大华人员删除接口返回为空"); - return resultMap; - } - JSONObject respJson = JSONUtil.parseObj(respBody); - Boolean success = respJson.getBool("success", false); - String errCode = respJson.getStr("errCode", ""); - String errMessage = respJson.getStr("errMessage", ""); - Object data = respJson.get("data"); - resultMap.put("success", success); - resultMap.put("errCode", errCode); - resultMap.put("errMessage", errMessage); - resultMap.put("data", data); - log.info("【解析后返回】success={}, errCode={}, errMessage={}, data={}", success, errCode, errMessage, data); - return resultMap; - } catch (Exception e) { - log.error("调用大华人员删除接口异常: {}", e.getMessage(), e); - resultMap.put("success", false); - resultMap.put("errCode", "HTTP_EXCEPTION"); - resultMap.put("errMessage", "调用大华人员删除接口异常: " + e.getMessage()); - return resultMap; - } - } } \ No newline at end of file