package jnpf.base.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import jnpf.base.UserInfo; import jnpf.base.entity.SynThirdInfoEntity; import jnpf.base.entity.SysConfigEntity; import jnpf.base.model.synthirdinfo.QyWebChatDeptModel; import jnpf.base.model.synthirdinfo.QyWebChatUserModel; import jnpf.base.service.SynThirdInfoService; import jnpf.base.service.SynThirdQyService; import jnpf.base.service.SysconfigService; import jnpf.base.util.SynQyWebChatUtil; import jnpf.base.util.SynThirdUtil; import jnpf.constant.JnpfConst; import jnpf.exception.WxErrorException; import jnpf.message.util.SynThirdConsts; import jnpf.model.BaseSystemInfo; import jnpf.model.SocialsSysConfig; import jnpf.permission.OrganizeApi; import jnpf.permission.PositionApi; import jnpf.permission.UserApi; import jnpf.permission.UserRelationApi; import jnpf.permission.entity.OrganizeEntity; import jnpf.permission.entity.PositionEntity; import jnpf.permission.entity.UserEntity; import jnpf.permission.entity.UserRelationEntity; import jnpf.permission.model.organize.OrganizeModel; import jnpf.util.*; import lombok.RequiredArgsConstructor; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.util.Assert; import java.text.ParseException; import java.util.*; import java.util.stream.Collectors; /** * 本系统的公司、部门、用户与企业微信的同步 * * @版本: V3.1.0 * @版权: 引迈信息技术有限公司(https://www.jnpfsoft.com) * @作者: JNPF开发平台组 * @日期: 2021/4/27 11:12 */ @Service @RequiredArgsConstructor public class SynThirdQyServiceImpl implements SynThirdQyService { public static final String ERROR="error"; private static final String TOKEN_NULL = "access_token值为空,不能同步信息"; private static final String TOP_DEFAULT = "顶级不同步,默认值id1"; private static final String SYS_NO_SINGLE_SY = "系统未设置单条同步"; private static final String RET_DEPT_ID = "retDeptId"; private static final String PARENT_ID = "parentid"; private static final String ORG_EXIST = "组织已存在"; private static final String CODE_60104 = "60104"; private static final String DEPARTMENT_EXISTED = "department existed"; private static final String QY_USER_OBJECT = "qyUserObject"; private static final String NAME_EN = "name_en"; private static final String TOKEN = "access_token"; private final SysconfigService sysconfigService; private final SynThirdInfoService synThirdInfoService; private final UserApi userApi; private final SynThirdUtil synThirdUtil; private final PositionApi positionApi; private final OrganizeApi organizeApi; private final UserRelationApi userRelationApi; @Override public JSONObject unifyDepartmentSysToQy(boolean isBatch, OrganizeEntity deptEntity, String accessToken,String choice) throws WxErrorException { SocialsSysConfig socialsConfig = sysconfigService.getSocialsConfig(); String qyhDepartment = socialsConfig.getQyhDepartment(); if (StringUtil.isEmpty(qyhDepartment)){ return new JSONObject(); } List organizeEntitiesBind = synThirdInfoService.getOrganizeEntitiesBind(qyhDepartment); List collect = organizeEntitiesBind.stream().map(OrganizeEntity::getId) .collect(Collectors.toList()); if (!collect.contains(deptEntity.getId()) && !choice.equals(JnpfConst.DELETE_DEP)) { return new JSONObject(); } switch (choice) { case JnpfConst.CREAT_DEP: return this.createDepartmentSysToQy(isBatch, deptEntity, accessToken); case JnpfConst.UPDATE_DEP: return this.updateDepartmentSysToQy(isBatch, deptEntity, accessToken); case JnpfConst.DELETE_DEP: return this.deleteDepartmentSysToQy(isBatch, deptEntity.getId(), accessToken); default: return new JSONObject(); } } @Override public JSONObject unifyDepartmentSysToQy(boolean isBatch, List organizeEntities, String accessToken, String choice) throws WxErrorException { for (OrganizeEntity organizeEntity : organizeEntities) { this.unifyDepartmentSysToQy(isBatch, organizeEntity, accessToken,choice); } return new JSONObject(); } /** * 获取企业微信的配置信息 * @return */ @Override public BaseSystemInfo getQyhConfig() { Map objModel = new HashMap<>(); List configList = sysconfigService.getList("SysConfig"); for (SysConfigEntity entity : configList) { objModel.put(entity.getFkey(), entity.getValue()); } return JsonUtil.getJsonToBean(objModel, BaseSystemInfo.class); } //------------------------------------本系统同步公司、部门到企业微信------------------------------------- /** * 根据部门的同步表信息判断同步情况 * 不带第三方错误定位判断的功能代码 20210604 * @param synThirdInfoEntity * @return */ public JSONObject checkDepartmentSysToQy(SynThirdInfoEntity synThirdInfoEntity) { JSONObject retMsg = new JSONObject(); retMsg.put("code", true); retMsg.put("flag", ""); retMsg.put(ERROR, ""); if (BeanUtil.isEmpty(synThirdInfoEntity)||synThirdInfoEntity.getThirdObjId()==null) { // 上级部门未同步 retMsg.put("code", false); retMsg.put("flag", "3"); retMsg.put(ERROR, "部门未同步到企业微信!"); }else { if (synThirdInfoEntity.getThirdObjId().equals("-1")) { retMsg.put("code", true); } // 同步表的企业微信ID为空 if (synThirdInfoEntity.getThirdObjId().isEmpty() || "null".equals(synThirdInfoEntity.getThirdObjId())) { retMsg.put("code", false); retMsg.put("flag", "2"); retMsg.put(ERROR, "同步表中部门对应的企业微信ID为空!"); } } return retMsg; } /** * 检查部门中文名称与英文名称是否相同 * @param cnName * @param enName * @param opType * @param synThirdInfoEntity * @param thirdType * @param dataType * @param sysObjId * @param thirdObjId * @param deptFlag * @return */ public JSONObject checkCnEnName(String cnName, String enName, String opType, SynThirdInfoEntity synThirdInfoEntity, Integer thirdType, Integer dataType, String sysObjId, String thirdObjId, String deptFlag) { JSONObject retMsg = new JSONObject(); retMsg.put("code", true); retMsg.put(ERROR, ""); if (cnName.equals(enName)) { // 同步失败 Integer synState = SynThirdConsts.SYN_STATE_FAIL; String description = deptFlag + "部门中文名称与英文名称不能相同"; // 更新同步表 saveSynThirdInfoEntity(opType, synThirdInfoEntity, thirdType, dataType, sysObjId, thirdObjId, synState, description, ""); retMsg.put("code", false); retMsg.put(ERROR, description); } return retMsg; } /** * 将组织、用户的信息写入同步表 * @param opType "add":创建 “upd”:修改 * @param synThirdInfoEntity 本地同步表信息 * @param thirdType 第三方类型 * @param dataType 数据类型 * @param sysObjId 本地对象ID * @param thirdObjId 第三方对象ID * @param synState 同步状态(0:未同步;1:同步成功;2:同步失败) * @param description */ public void saveSynThirdInfoEntity(String opType, SynThirdInfoEntity synThirdInfoEntity, Integer thirdType, Integer dataType, String sysObjId, String thirdObjId, Integer synState, String description, String thirdName) { UserInfo userInfo = UserProvider.getUser(); SynThirdInfoEntity entity = new SynThirdInfoEntity(); String compValue = SynThirdConsts.OBJECT_OP_ADD; if (compValue.equals(opType)) { entity.setId(RandomUtil.uuId()); entity.setThirdType(thirdType); entity.setDataType(dataType); entity.setSysObjId(sysObjId); entity.setThirdObjId(thirdObjId); entity.setEnabledMark(synState); entity.setThirdName(thirdName); // 备注当作同步失败信息来用 entity.setDescription(description); entity.setCreatorUserId(userInfo.getUserId()); entity.setCreatorTime(DateUtil.getNowDate()); entity.setLastModifyUserId(userInfo.getUserId()); // 修改时间当作最后同步时间来用 entity.setLastModifyTime(DateUtil.getNowDate()); synThirdInfoService.create(entity); } else { entity = synThirdInfoEntity; entity.setThirdName(thirdName); entity.setThirdType(thirdType); entity.setDataType(dataType); entity.setThirdObjId(thirdObjId); entity.setEnabledMark(synState); // 备注当作同步失败信息来用 entity.setDescription(description); entity.setLastModifyUserId(userInfo.getUserId()); // 修改时间当作最后同步时间来用 entity.setLastModifyTime(DateUtil.getNowDate()); synThirdInfoService.update(entity.getId(), entity); } } /** * 往企业微信创建部门 * 不带错误定位判断的功能代码,只获取调用接口的返回信息 20210604 * @param isBatch 是否批量(批量不受开关限制) * @param deptEntity * @param accessToken (单条调用时为空) * @return * @throws WxErrorException */ @Override public JSONObject createDepartmentSysToQy(boolean isBatch, OrganizeEntity deptEntity, String accessToken) throws WxErrorException { SocialsSysConfig config = sysconfigService.getSocialsConfig(); // 单条记录执行时,受开关限制 int qyhIsSyn = isBatch ? 1 : config.getQyhIsSynOrg(); JSONObject tokenObject ; String token = ""; JSONObject retMsg = new JSONObject(); JSONObject object = new JSONObject(); String thirdObjId = ""; String thirdName = ""; Integer synState = 0; String description = ""; boolean isDeptDiff = true; String deptFlag = "创建:"; // 返回值初始化 retMsg.put("code", true); retMsg.put(ERROR, "创建:系统未设置单条同步"); // 支持同步 if (isBatch || qyhIsSyn == 1) { if (isBatch) { token = accessToken; } else { // 获取 access_token 值 String corpId = config.getQyhCorpId(); // 向企业微信插入数据需要另外token(应用密钥) String corpSecret = config.getQyhAgentSecret(); tokenObject = SynQyWebChatUtil.getAccessToken(corpId, corpSecret); token = tokenObject.getString(TOKEN); } if (token != null && !token.isEmpty()) { object.put("id", null); // name:必填项,同一个层级的部门名称不能重复 // name_en:必填项,同一个层级的部门名称不能重复 // name与name_en的值不能相同,否则会报错, 20210429 object.put("name", deptEntity.getFullName()); object.put(NAME_EN, deptEntity.getEnCode()); // 从本地数据库的同步表获取对应的企业微信ID,为空报异常,不为空再验证所获取接口部门列表是否当前ID 未处理 if ( "-1".equals(deptEntity.getParentId())) { //顶级节点时,企业微信的父节点设置为1 object.put(PARENT_ID, 1); } else { SynThirdInfoEntity synThirdInfoEntity = synThirdInfoService.getInfoBySysObjId(SynThirdConsts.THIRD_TYPE_QY, SynThirdConsts.DATA_TYPE_ORG, deptEntity.getParentId()); retMsg = checkDepartmentSysToQy(synThirdInfoEntity); isDeptDiff = retMsg.getBoolean("code"); if (isDeptDiff) { object.put(PARENT_ID, synThirdInfoEntity.getThirdObjId()); } } object.put("order", deptEntity.getSortCode()); if (isDeptDiff) { // 往企业微信写入公司或部门 if (!"-1".equals(deptEntity.getParentId())) { retMsg = SynQyWebChatUtil.createDepartment(object.toJSONString(), token); } else { retMsg.put("code", true); retMsg.put(ERROR, TOP_DEFAULT); retMsg.put(RET_DEPT_ID, "1"); } // 往同步写入本系统与第三方的对应信息 if (Boolean.TRUE.equals(retMsg.getBoolean("code"))) { // 同步成功 thirdObjId = retMsg.getString(RET_DEPT_ID); thirdName = deptEntity.getFullName(); synState = SynThirdConsts.SYN_STATE_OK; description = "创建成功"; } else { if (retMsg.getString(ERROR).contains(DEPARTMENT_EXISTED)){ List organizeListVOS = getOrganizeListVOS(config); List collect = organizeListVOS.stream() .filter(t -> t.getFullName().equals(deptEntity.getFullName())) .collect(Collectors.toList()); thirdObjId=collect.get(0).getId(); synState = SynThirdConsts.SYN_STATE_OK; thirdName = deptEntity.getFullName(); description = ORG_EXIST; }else { // 同步失败 synState = SynThirdConsts.SYN_STATE_FAIL; description = deptFlag + retMsg.getString(ERROR); } } } else { // 同步失败,上级部门无对应的企业微信ID synState = SynThirdConsts.SYN_STATE_FAIL; description = deptFlag + "部门所属的上级部门未同步到企业微信"; retMsg.put("code", false); retMsg.put(ERROR, description); retMsg.put(RET_DEPT_ID, "0"); } } else { synState = SynThirdConsts.SYN_STATE_FAIL; description = deptFlag + TOKEN_NULL; retMsg.put("code", false); retMsg.put(ERROR, description); retMsg.put(RET_DEPT_ID, "0"); } } else { return retMsg; } // 更新同步表 saveSynThirdInfoEntity(SynThirdConsts.OBJECT_OP_ADD, null, Integer.parseInt(SynThirdConsts.THIRD_TYPE_QY), Integer.parseInt(SynThirdConsts.DATA_TYPE_ORG), deptEntity.getId(), thirdObjId, synState, description, thirdName); return retMsg; } private static List getOrganizeListVOS(SocialsSysConfig config) throws WxErrorException { List qyDeptAllList ; JSONObject tokenObject = SynQyWebChatUtil.getAccessToken(config.getQyhCorpId(), config.getQyhCorpSecret()); String accessToken = tokenObject.getString(TOKEN); // 获取企业微信上的部门列表 String departId = SynThirdConsts.QY_ROOT_DEPT_ID; JSONObject retMsg = SynQyWebChatUtil.getDepartmentList(departId, accessToken); qyDeptAllList = JsonUtil.getJsonToList(retMsg.get("department").toString(), QyWebChatDeptModel.class); // 部门进行树结构化,固化上下层级序列化 return qyDeptAllList.stream().map(t -> { OrganizeModel model = JsonUtil.getJsonToBean(t, OrganizeModel.class); model.setFullName(t.getName()); model.setParentId(t.getParentId() + ""); return model; }).collect(Collectors.toList()); } /** * 往企业微信更新部门 * 不带错误定位判断的功能代码,只获取调用接口的返回信息 20210604 * @param isBatch 是否批量(批量不受开关限制) * @param deptEntity * @param accessToken (单条调用时为空) * @return * @throws WxErrorException */ @Override public JSONObject updateDepartmentSysToQy(boolean isBatch, OrganizeEntity deptEntity, String accessToken) throws WxErrorException { SocialsSysConfig config = sysconfigService.getSocialsConfig(); // 单条记录执行时,受开关限制 int qyhIsSyn = isBatch ? 1 : config.getQyhIsSynOrg(); JSONObject tokenObject ; String token = ""; JSONObject retMsg = new JSONObject(); JSONObject object = new JSONObject(); SynThirdInfoEntity synThirdInfoEntity; String opType = ""; Integer synState = 0; String description = ""; String thirdObjId = ""; String thirdName = ""; SynThirdInfoEntity synThirdInfoPara = new SynThirdInfoEntity(); boolean isDeptDiff = true; String deptFlag = "更新:"; // 返回值初始化 retMsg.put("code", true); retMsg.put(ERROR, SYS_NO_SINGLE_SY); // 支持同步,设置需要同步到企业微信的对象属性值 if (isBatch || qyhIsSyn == 1) { if (isBatch) { token = accessToken; } else { String corpId = config.getQyhCorpId(); // 向企业微信插入数据需要另外token(凭证密钥) String corpSecret = config.getQyhAgentSecret(); // 获取 access_token tokenObject = SynQyWebChatUtil.getAccessToken(corpId, corpSecret); token = tokenObject.getString(TOKEN); } // 获取同步表信息 synThirdInfoEntity = synThirdInfoService.getInfoBySysObjId(SynThirdConsts.THIRD_TYPE_QY, SynThirdConsts.DATA_TYPE_ORG, deptEntity.getId()); if (StringUtil.isNotEmpty(token)) { object.put("id", null); object.put("name", deptEntity.getFullName()); object.put(NAME_EN, deptEntity.getEnCode()); // 从本地数据库的同步表获取对应的企业微信ID,为空报异常,不为空再验证所获取接口部门列表是否当前ID 未处理 if ("-1".equals(deptEntity.getParentId())) { //顶级节点时,企业微信的父节点设置为1 object.put(PARENT_ID, 1); } else { // 判断上级部门的合法性 synThirdInfoEntity = synThirdInfoService.getInfoBySysObjId(SynThirdConsts.THIRD_TYPE_QY, SynThirdConsts.DATA_TYPE_ORG, deptEntity.getParentId()); //如果是最高级 if (Objects.equals(deptEntity.getParentId(), "-1")) { synThirdInfoEntity = new SynThirdInfoEntity(); synThirdInfoEntity.setThirdObjId("-1"); } retMsg = checkDepartmentSysToQy(synThirdInfoEntity); isDeptDiff = retMsg.getBoolean("code"); if (isDeptDiff) { object.put(PARENT_ID, synThirdInfoEntity.getThirdObjId()); } } object.put("order", deptEntity.getSortCode()); // 上级部门检查是否异常 if (isDeptDiff) { // 获取同步表信息 synThirdInfoEntity = synThirdInfoService.getInfoBySysObjId(SynThirdConsts.THIRD_TYPE_QY, SynThirdConsts.DATA_TYPE_ORG, deptEntity.getId()); // 判断当前部门对应的第三方的合法性 retMsg = checkDepartmentSysToQy(synThirdInfoEntity); if (Boolean.FALSE.equals(retMsg.getBoolean("code"))) { if ("3".equals(retMsg.getString("flag")) || "1".equals(retMsg.getString("flag"))) { // flag:3 未同步,需要创建同步到企业微信、写入同步表 // flag:1 已同步但第三方上没对应的ID,需要删除原来的同步信息,再创建同步到企业微信、写入同步表 if ("1".equals(retMsg.getString("flag"))) { synThirdInfoService.delete(synThirdInfoEntity); } opType = SynThirdConsts.OBJECT_OP_ADD; synThirdInfoPara = null; thirdObjId = ""; // 部门中文名称与英文名称不能相同 retMsg = checkCnEnName(object.getString("name"), object.getString(NAME_EN), opType, synThirdInfoPara, Integer.parseInt(SynThirdConsts.THIRD_TYPE_QY), Integer.parseInt(SynThirdConsts.DATA_TYPE_ORG), deptEntity.getId(), thirdObjId, deptFlag); if (Boolean.FALSE.equals(retMsg.getBoolean("code"))) { return retMsg; } // 往企业微信写入公司或部门 retMsg = SynQyWebChatUtil.updateDepartment(object.toJSONString(), token); // 往同步写入本系统与第三方的对应信息 if (Boolean.TRUE.equals(retMsg.getBoolean("code"))) { // 同步成功 thirdObjId = retMsg.getString(RET_DEPT_ID); thirdName = deptEntity.getFullName(); synState = SynThirdConsts.SYN_STATE_OK; description = "更新成功"; } else { // 同步失败 if (retMsg.getString(ERROR).contains(DEPARTMENT_EXISTED)){ List organizeListVOS = getOrganizeListVOS(config); List collect = organizeListVOS.stream() .filter(t -> t.getFullName().equals(deptEntity.getFullName())) .collect(Collectors.toList()); thirdObjId=collect.get(0).getId(); synState = SynThirdConsts.SYN_STATE_OK; thirdName = deptEntity.getFullName(); description = ORG_EXIST; }else { synState = SynThirdConsts.SYN_STATE_FAIL; description = deptFlag + retMsg.getString(ERROR); } } } if ("2".equals(retMsg.getString("flag"))) { // flag:2 已同步但第三方ID为空,需要创建同步到企业微信、修改同步表 opType = SynThirdConsts.OBJECT_OP_UPD; synThirdInfoPara = synThirdInfoEntity; thirdObjId = ""; // 部门中文名称与英文名称不能相同 retMsg = checkCnEnName(object.getString("name"), object.getString(NAME_EN), opType, synThirdInfoPara, Integer.parseInt(SynThirdConsts.THIRD_TYPE_QY), Integer.parseInt(SynThirdConsts.DATA_TYPE_ORG), deptEntity.getId(), thirdObjId, deptFlag); if (Boolean.FALSE.equals(retMsg.getBoolean("code"))) { return retMsg; } // 往企业微信写入公司或部门 if (!Objects.equals(object.getString(PARENT_ID), "1")){ retMsg = SynQyWebChatUtil.createDepartment(object.toJSONString(), token); }else { retMsg.put(RET_DEPT_ID, "1"); } // 往同步表更新本系统与第三方的对应信息 if (Boolean.TRUE.equals(retMsg.getBoolean("code"))) { // 同步成功 thirdObjId = retMsg.getString(RET_DEPT_ID); thirdName = deptEntity.getFullName(); synState = SynThirdConsts.SYN_STATE_OK; description = "更新成功"; } else { // 同步失败 if (retMsg.getString(ERROR).contains(DEPARTMENT_EXISTED)){ List organizeListVOS = getOrganizeListVOS(config); List collect = organizeListVOS.stream() .filter(t -> t.getFullName().equals(deptEntity.getFullName())) .collect(Collectors.toList()); thirdObjId=collect.get(0).getId(); synState = SynThirdConsts.SYN_STATE_OK; thirdName = deptEntity.getFullName(); description = ORG_EXIST; }else { synState = SynThirdConsts.SYN_STATE_FAIL; description = deptFlag + retMsg.getString(ERROR); } } } } else { // 更新同步表 opType = SynThirdConsts.OBJECT_OP_UPD; synThirdInfoPara = synThirdInfoEntity; thirdObjId = synThirdInfoEntity.getThirdObjId(); // 部门中文名称与英文名称不能相同 retMsg = checkCnEnName(object.getString("name"), object.getString(NAME_EN), opType, synThirdInfoPara, Integer.parseInt(SynThirdConsts.THIRD_TYPE_QY), Integer.parseInt(SynThirdConsts.DATA_TYPE_ORG), deptEntity.getId(), thirdObjId, deptFlag); if (Boolean.FALSE.equals(retMsg.getBoolean("code"))) { return retMsg; } object.put("id", synThirdInfoEntity.getThirdObjId()); if (!deptEntity.getParentId().equals("-1")) { retMsg = SynQyWebChatUtil.updateDepartment(object.toJSONString(), token); } // 往同步表更新本系统与第三方的对应信息 if (Boolean.TRUE.equals(retMsg.getBoolean("code"))) { // 同步成功 synState = SynThirdConsts.SYN_STATE_OK; thirdName = deptEntity.getFullName(); description = "同步成功"; } else { if (retMsg.getString(ERROR).contains(DEPARTMENT_EXISTED)){ List organizeListVOS = getOrganizeListVOS(config); List collect = organizeListVOS.stream() .filter(t -> t.getFullName().equals(deptEntity.getFullName())) .collect(Collectors.toList()); thirdObjId=collect.get(0).getId(); synState = SynThirdConsts.SYN_STATE_OK; thirdName = deptEntity.getFullName(); description = ORG_EXIST; }else { // 同步失败 synState = SynThirdConsts.SYN_STATE_FAIL; description = deptFlag + retMsg.getString(ERROR); } } } } else { // 同步失败,上级部门检查有异常 if (synThirdInfoEntity != null) { // 修改同步表 opType = SynThirdConsts.OBJECT_OP_UPD; synThirdInfoPara = synThirdInfoEntity; thirdObjId = synThirdInfoEntity.getThirdObjId(); } else { // 写入同步表 opType = SynThirdConsts.OBJECT_OP_ADD; synThirdInfoPara = null; thirdObjId = ""; } synState = SynThirdConsts.SYN_STATE_FAIL; description = deptFlag + "上级部门无对应的企业微信ID"; retMsg.put("code", false); retMsg.put(ERROR, description); } } else { // 同步失败 if (synThirdInfoEntity != null) { // 修改同步表 opType = SynThirdConsts.OBJECT_OP_UPD; synThirdInfoPara = synThirdInfoEntity; thirdObjId = synThirdInfoEntity.getThirdObjId(); } else { // 写入同步表 opType = SynThirdConsts.OBJECT_OP_ADD; synThirdInfoPara = null; thirdObjId = ""; } synState = SynThirdConsts.SYN_STATE_FAIL; description = deptFlag + TOKEN_NULL; retMsg.put("code", true); retMsg.put(ERROR, description); } } else { description = deptFlag + SYS_NO_SINGLE_SY; retMsg.put("code", true); retMsg.put(ERROR, description); return retMsg; } // 更新同步表 saveSynThirdInfoEntity(opType, synThirdInfoPara, Integer.parseInt(SynThirdConsts.THIRD_TYPE_QY), Integer.parseInt(SynThirdConsts.DATA_TYPE_ORG), deptEntity.getId(), thirdObjId, synState, description, thirdName); return retMsg; } /** * 往企业微信删除部门 * 不带错误定位判断的功能代码,只获取调用接口的返回信息 20210604 * @param isBatch 是否批量(批量不受开关限制) * @param id 本系统的公司或部门ID * @param accessToken (单条调用时为空) * @return * @throws WxErrorException */ @Override public JSONObject deleteDepartmentSysToQy(boolean isBatch, String id, String accessToken) throws WxErrorException { SocialsSysConfig config = sysconfigService.getSocialsConfig(); // 单条记录执行时,受开关限制 int qyhIsSyn = isBatch ? 1 : config.getQyhIsSynOrg(); JSONObject tokenObject; String token = ""; JSONObject retMsg = new JSONObject(); SynThirdInfoEntity synThirdInfoEntity = synThirdInfoService.getInfoBySysObjId(SynThirdConsts.THIRD_TYPE_QY, SynThirdConsts.DATA_TYPE_ORG, id); String deptFlag = "删除:"; // 返回值初始化 retMsg.put("code", true); retMsg.put(ERROR, SYS_NO_SINGLE_SY); // 支持同步 if (synThirdInfoEntity != null) { if (qyhIsSyn == 1) { if (isBatch) { token = accessToken; } else { String corpId = config.getQyhCorpId(); String corpSecret = config.getQyhAgentSecret(); // 获取 access_token tokenObject = SynQyWebChatUtil.getAccessToken(corpId, corpSecret); token = tokenObject.getString(TOKEN); } if (StringUtil.isNotEmpty(token)) { if (!"".equals(String.valueOf(synThirdInfoEntity.getThirdObjId())) && !"null".equals(String.valueOf(synThirdInfoEntity.getThirdObjId()))) { retMsg = SynQyWebChatUtil.deleteDepartment(synThirdInfoEntity.getThirdObjId(), token); if (Boolean.TRUE.equals(retMsg.getBoolean("code"))) { // 同步成功,直接删除同步表记录 synThirdInfoService.delete(synThirdInfoEntity); } else { // 同步失败 String msg=deptFlag+retMsg.getString(ERROR); if (retMsg.getString(ERROR).contains("60005")) { msg=deptFlag + "该组织下包含用户,无法删除";} if (retMsg.getString(ERROR).contains("60006")) { msg=deptFlag + "该组织下包含组织,无法删除"; } saveSynThirdInfoEntity(SynThirdConsts.OBJECT_OP_UPD, synThirdInfoEntity, Integer.parseInt(SynThirdConsts.THIRD_TYPE_QY), Integer.parseInt(SynThirdConsts.DATA_TYPE_ORG) , id, synThirdInfoEntity.getThirdObjId() , SynThirdConsts.SYN_STATE_FAIL, msg, ""); } } else { // 根据企业微信ID找不到相应的信息,直接删除同步表记录 synThirdInfoService.delete(synThirdInfoEntity); } } else { // 同步失败 saveSynThirdInfoEntity(SynThirdConsts.OBJECT_OP_UPD, synThirdInfoEntity, Integer.parseInt(SynThirdConsts.THIRD_TYPE_QY), Integer.parseInt(SynThirdConsts.DATA_TYPE_ORG) , id, synThirdInfoEntity.getThirdObjId(), SynThirdConsts.SYN_STATE_FAIL , deptFlag + TOKEN_NULL, ""); retMsg.put("code", false); retMsg.put(ERROR, deptFlag + "access_token值为空,不能同步信息!"); } } else { retMsg.put("code", true); retMsg.put(ERROR, deptFlag + SYS_NO_SINGLE_SY); } } return retMsg; } //------------------------------------本系统同步用户到企业微信------------------------------------- /** * 获取企业微信的单个成员列表,用于更新成员信息使用 * @param id * @param accessToken * @return * @throws WxErrorException */ public QyWebChatUserModel getQyUserById(String id, String accessToken) throws WxErrorException { QyWebChatUserModel userModel = new QyWebChatUserModel(); JSONObject userObject = SynQyWebChatUtil.getUserById(id,accessToken); if(Boolean.TRUE.equals(userObject.getBoolean("code"))) { userModel = JsonUtil.getJsonToBean(userObject.getString("userinfo"), QyWebChatUserModel.class); } return userModel; } /** * 设置需要提交给企业微信接口的单个成品JSON信息 * 不带第三方错误定位判断的功能代码 20210604 * @param userEntity 本地用户信息 * @param qyWebChatUserModel * @return */ public JSONObject setQyUserObject(UserEntity userEntity, QyWebChatUserModel qyWebChatUserModel) { List userList = userApi.getList(false); JSONObject object = new JSONObject(); JSONObject retMsg = new JSONObject(); retMsg.put("code", true); retMsg.put(ERROR, ""); // 验证邮箱格式的合法性 if (StringUtil.isNotEmpty(userEntity.getEmail()) && !RegexUtils.checkEmail(userEntity.getEmail())) { retMsg.put("code", false); retMsg.put(ERROR, "邮箱格式不合法!"); retMsg.put(QY_USER_OBJECT, ""); return retMsg; } object.put("userid", userEntity.getId()); object.put("name", userEntity.getRealName()); object.put("mobile", userEntity.getMobilePhone()); SynThirdInfoEntity synThirdInfoEntity = synThirdInfoService.getInfoBySysObjId(SynThirdConsts.THIRD_TYPE_QY, SynThirdConsts.DATA_TYPE_ORG, userEntity.getOrganizeId()); retMsg = checkDepartmentSysToQy(synThirdInfoEntity); if (Boolean.TRUE.equals(retMsg.getBoolean("code"))) { String formatString = "[%s]"; object.put("department", String.format(formatString, synThirdInfoEntity.getThirdObjId())); object.put("main_department", synThirdInfoEntity.getThirdObjId()); String isLeader = userList.stream().filter(t -> userEntity.getOrganizeId().equals(t.getOrganizeId()) && userEntity.getId().equals(t.getManagerId())).count() == 0 ? "0" : "1"; object.put("is_leader_in_dept", String.format(formatString, isLeader)); } else { retMsg.put("code", false); retMsg.put(ERROR, "部门找不到对应的企业微信ID!"); retMsg.put(QY_USER_OBJECT, ""); return retMsg; } object.put("email", userEntity.getEmail()); PositionEntity positionEntity = positionApi.queryInfoById(userEntity.getPositionId()); if (positionEntity != null) { object.put("position", positionEntity.getFullName()); } else { object.put("position", ""); } object.put("gender", userEntity.getGender()); object.put("telephone", userEntity.getTelePhone()); object.put("enable", userEntity.getEnabledMark()); JSONObject extattr = new JSONObject(); extattr.put("attrs", "[]"); object.put("extattr", extattr.toJSONString()); object.put("address", userEntity.getPostalAddress()); object.put("alias", ""); object.put("avatar_mediaid", ""); JSONObject externalProfile = new JSONObject(); externalProfile.put("external_corp_name", ""); externalProfile.put("external_attr", "[]"); object.put("external_profile", externalProfile.toJSONString()); object.put("external_position", ""); // 修改时:未更新字段信息来源企业微信 if (qyWebChatUserModel != null) { object.put("alias", qyWebChatUserModel.getAlias()); object.put("avatar_mediaid", qyWebChatUserModel.getAvatarMediaid()); object.put("external_profile", qyWebChatUserModel.getExternalProfile()); object.put("external_position", qyWebChatUserModel.getExternalPosition()); } String jsonString = object.toJSONString(); // 格式与用户的格式不一致就需要做处理,否则提交JSON格式验证无法通过 jsonString = jsonString.replace("\\\\", ""); jsonString = jsonString.replace("\"\\{", "{"); jsonString = jsonString.replace("}\"", "}"); jsonString = jsonString.replace("\"\\[", "["); jsonString = jsonString.replace("\\]\"", "]"); retMsg.put(QY_USER_OBJECT, jsonString); return retMsg; } /** * 根据用户的同步表信息判断同步情况 * 不带错误定位判断的功能代码,只获取调用接口的返回信息 20210604 * @param synThirdInfoEntity * @return */ public JSONObject checkUserSysToQy(SynThirdInfoEntity synThirdInfoEntity) { JSONObject retMsg = new JSONObject(); retMsg.put("code", true); retMsg.put("flag", ""); retMsg.put(ERROR, ""); if (synThirdInfoEntity != null) { if ("".equals(String.valueOf(synThirdInfoEntity.getThirdObjId())) || "null".equals(String.valueOf(synThirdInfoEntity.getThirdObjId()))) { // 同步表的企业微信ID为空 retMsg.put("code", false); retMsg.put("flag", "2"); retMsg.put(ERROR, "同步表中用户对应的第三方ID为空!"); } } else { // 上级用户未同步 retMsg.put("code", false); retMsg.put("flag", "3"); retMsg.put(ERROR, "用户未同步!"); } return retMsg; } /** * 往企业微信创建成员信息 * 不带错误定位判断的功能代码,只获取调用接口的返回信息 20210604 * @param isBatch 是否批量(批量不受开关限制) * @param userEntity * @param accessToken (单条调用时为空) * @return * @throws WxErrorException */ @Override public JSONObject createUserSysToQy(boolean isBatch, UserEntity userEntity, String accessToken) throws WxErrorException { SocialsSysConfig config = sysconfigService.getSocialsConfig(); // 单条记录执行时,受开关限制 int qyhIsSyn = isBatch ? 1 : config.getQyhIsSynUser(); JSONObject tokenObject ; String token = ""; JSONObject retMsg = new JSONObject(); String userObjectModel = ""; String thirdObjId = ""; String thirdName = ""; Integer synState = 0; String description = ""; String userFlag = "创建:"; // 返回值初始化 retMsg.put("code", true); retMsg.put(ERROR, userFlag + SYS_NO_SINGLE_SY); // 企业微信限制:不能手机号、邮箱同时为空 if (StringUtil.isEmpty(userEntity.getMobilePhone()) && StringUtil.isEmpty(userEntity.getEmail()) && qyhIsSyn == 1) { retMsg.put("code", false); retMsg.put(ERROR, userFlag + "企业微信不允许手机号、邮箱不能同时为空!"); } if (isBatch || qyhIsSyn == 1) { if (Boolean.TRUE.equals(retMsg.getBoolean("code"))) { if (isBatch) { token = accessToken; } else { // 获取 access_token String corpId = config.getQyhCorpId(); // 向企业微信插入数据需要另外token(凭证密钥) String corpSecret = config.getQyhAgentSecret(); tokenObject = SynQyWebChatUtil.getAccessToken(corpId, corpSecret); token = tokenObject.getString(TOKEN); } if (token != null && !token.isEmpty()) { // 要同步到企业微信的对象赋值 retMsg = setQyUserObject(userEntity, null); if (Boolean.TRUE.equals(retMsg.getBoolean("code"))) { userObjectModel = retMsg.getString(QY_USER_OBJECT); // 往企业微信写入成员 retMsg = SynQyWebChatUtil.createUser(userObjectModel, token); // 往同步写入本系统与第三方的对应信息 if (Boolean.TRUE.equals(retMsg.getBoolean("code"))) { // 同步成功 thirdObjId = userEntity.getId(); thirdName = userEntity.getRealName(); synState = SynThirdConsts.SYN_STATE_OK; } else { if (retMsg.getString(ERROR).contains(CODE_60104)){ QyWebChatUserModel model = getQyUserList(config, userEntity.getMobilePhone()); assert model != null; thirdObjId = model.getUserid(); thirdName = userEntity.getRealName(); synState = SynThirdConsts.SYN_STATE_OK; }else { // 同步失败 synState = SynThirdConsts.SYN_STATE_FAIL; description = userFlag + retMsg.getString(ERROR); } } } else { // 同步失败,原因:部门找不到对应的第三方ID、邮箱格式不合法 synState = SynThirdConsts.SYN_STATE_FAIL; description = userFlag + retMsg.getString(ERROR); } } else { // 同步失败 synState = SynThirdConsts.SYN_STATE_FAIL; description = userFlag + TOKEN_NULL; retMsg.put("code", false); retMsg.put(ERROR, description); } } else { // 同步失败,原因:企业微信不允许手机号、邮箱不能同时为空 synState = SynThirdConsts.SYN_STATE_FAIL; description = userFlag + retMsg.getString(ERROR); } } else { // 无须同步,未同步状态 description = userFlag + SYS_NO_SINGLE_SY; retMsg.put("code", true); retMsg.put(ERROR, description); return retMsg; } // 更新同步表 saveSynThirdInfoEntity(SynThirdConsts.OBJECT_OP_ADD, null, Integer.parseInt(SynThirdConsts.THIRD_TYPE_QY), Integer.parseInt(SynThirdConsts.DATA_TYPE_USER), userEntity.getId(), thirdObjId, synState, description, thirdName); return retMsg; } @Override public JSONObject createUserSysToQy(boolean isBatch, List userList, String accessToken, String positionId) throws WxErrorException { SocialsSysConfig config = sysconfigService.getSocialsConfig(); List organizeEntitiesBind = synThirdInfoService.getOrganizeEntitiesBind(config.getQyhDepartment()); PositionEntity info = positionApi.queryInfoById(positionId); if (BeanUtil.isNotEmpty(info) && !organizeEntitiesBind.stream() .map(OrganizeEntity::getId) .collect(Collectors.toList()).contains(info.getOrganizeId())) { return new JSONObject(); } for (UserEntity userEntity : userList) { createUserSysToQy(isBatch, userEntity, accessToken); } return new JSONObject(); } @Override public JSONObject createUserSysToQy(boolean isBatch, UserEntity userEntity, String accessToken, List ids) throws ParseException, WxErrorException { SocialsSysConfig config = sysconfigService.getSocialsConfig(); List organizeEntitiesBind = synThirdInfoService.getOrganizeEntitiesBind(config.getQyhDepartment()); for (String id : ids) { if (organizeEntitiesBind.stream() .map(OrganizeEntity::getId) .collect(Collectors.toList()).contains(id)) { userEntity.setOrganizeId(id); createUserSysToQy(isBatch, userEntity, accessToken); } } return new JSONObject(); } private QyWebChatUserModel getQyUserList(SocialsSysConfig config,String mobile){ JSONObject tokenObject = SynQyWebChatUtil.getAccessToken(config.getQyhCorpId(), config.getQyhAgentSecret()); String token = tokenObject.getString(TOKEN); // 获取企业微信的用户列表 JSONObject retMsg = SynQyWebChatUtil.getUserIdByMobile(mobile, token); String string = retMsg.getString("userid"); QyWebChatUserModel qyWebChatUserModel = new QyWebChatUserModel(); qyWebChatUserModel.setUserid(string); return qyWebChatUserModel; } /** * 往企业微信更新成员信息 * 不带错误定位判断的功能代码,只获取调用接口的返回信息 20210604 * @param isBatch 是否批量(批量不受开关限制) * @param userEntity * @param accessToken (单条调用时为空) * @return * @throws WxErrorException */ @Override public JSONObject updateUserSysToQy(boolean isBatch, UserEntity userEntity, String accessToken,String corpToken) throws WxErrorException { SocialsSysConfig config = sysconfigService.getSocialsConfig(); // 单条记录执行时,受开关限制 int qyhIsSyn = isBatch ? 1 : config.getQyhIsSynUser(); JSONObject tokenObject; String token = ""; JSONObject retMsg = new JSONObject(); String userObjectModel = ""; SynThirdInfoEntity synThirdInfoEntity ; String opType = ""; SynThirdInfoEntity synThirdInfoPara = new SynThirdInfoEntity(); String thirdObjId = ""; String thirdName = ""; Integer synState = 0; String description = ""; String userFlag = "更新:"; // 返回值初始化 retMsg.put("code", true); retMsg.put(ERROR, userFlag + SYS_NO_SINGLE_SY); // 企业微信限制:不能手机号、邮箱同时为空 if (StringUtil.isEmpty(userEntity.getMobilePhone()) && StringUtil.isEmpty(userEntity.getEmail()) && qyhIsSyn == 1) { retMsg.put("code", false); retMsg.put(ERROR, userFlag + "企业微信不允许手机号、邮箱不能同时为空!"); } // 支持同步 if (isBatch || qyhIsSyn == 1) { if (Boolean.TRUE.equals(retMsg.getBoolean("code"))) { if (!isBatch) { tokenObject = SynQyWebChatUtil.getAccessToken(config.getQyhCorpId(), config.getQyhAgentSecret()); token = tokenObject.getString(TOKEN); JSONObject corpTokenObject = SynQyWebChatUtil .getAccessToken(config.getQyhCorpId(), config.getQyhCorpSecret()); corpToken = corpTokenObject.getString(TOKEN); }else { token = accessToken; } // 获取同步表信息 synThirdInfoEntity = synThirdInfoService.getInfoBySysObjId(SynThirdConsts.THIRD_TYPE_QY, SynThirdConsts.DATA_TYPE_USER, userEntity.getId()); if (StringUtil.isNotEmpty(token)) { // 要同步到企业微信的对象赋值 retMsg = setQyUserObject(userEntity, null); if (Boolean.TRUE.equals(retMsg.getBoolean("code"))) { // 判断当前用户对应的第三方的合法性 userObjectModel = retMsg.getString(QY_USER_OBJECT); retMsg = checkUserSysToQy(synThirdInfoEntity); if (Boolean.FALSE.equals(retMsg.getBoolean("code"))) { if ("3".equals(retMsg.getString("flag")) || "1".equals(retMsg.getString("flag"))) { // flag:3 未同步,需要创建同步到企业微信、写入同步表 // flag:1 已同步但第三方上没对应的ID,需要删除原来的同步信息,再创建同步到企业微信、写入同步表 if ("1".equals(retMsg.getString("flag"))) { synThirdInfoService.delete(synThirdInfoEntity); } opType = SynThirdConsts.OBJECT_OP_ADD; synThirdInfoPara = null; thirdObjId = ""; // 往企业微信写入成员 retMsg = SynQyWebChatUtil.createUser(userObjectModel, token); if (Boolean.TRUE.equals(retMsg.getBoolean("code"))) { // 同步成功 thirdObjId = userEntity.getId(); thirdName=userEntity.getRealName(); synState = SynThirdConsts.SYN_STATE_OK; description = ""; } else { if (retMsg.getString(ERROR).contains(CODE_60104)){ QyWebChatUserModel model = getQyUserList(config, userEntity.getMobilePhone()); assert model != null; thirdObjId = model.getUserid(); thirdName = userEntity.getRealName(); synState = SynThirdConsts.SYN_STATE_OK; }else { // 同步失败 synState = SynThirdConsts.SYN_STATE_FAIL; description = userFlag + retMsg.getString(ERROR); } } } if ("2".equals(retMsg.getString("flag"))) { // 已同步但第三方ID为空,需要创建同步到企业微信、修改同步表 opType = SynThirdConsts.OBJECT_OP_UPD; synThirdInfoPara = synThirdInfoEntity; thirdObjId = ""; // 往企业微信写入成员 retMsg = SynQyWebChatUtil.createUser(userObjectModel, token); if (Boolean.TRUE.equals(retMsg.getBoolean("code"))) { // 同步成功 thirdObjId = userEntity.getId(); thirdName=userEntity.getRealName(); synState = SynThirdConsts.SYN_STATE_OK; description = ""; } else { if (retMsg.getString(ERROR).contains(CODE_60104)){ QyWebChatUserModel model = getQyUserList(config, userEntity.getMobilePhone()); assert model != null; thirdObjId = model.getUserid(); thirdName = userEntity.getRealName(); synState = SynThirdConsts.SYN_STATE_OK; }else { // 同步失败 synState = SynThirdConsts.SYN_STATE_FAIL; description = userFlag + retMsg.getString(ERROR); } } } } else { // 更新同步表 opType = SynThirdConsts.OBJECT_OP_UPD; synThirdInfoPara = synThirdInfoEntity; thirdObjId = synThirdInfoEntity.getThirdObjId(); // 获取当前成员信息 QyWebChatUserModel qyWebChatUserModel = getQyUserById(synThirdInfoEntity.getThirdObjId(), corpToken); if ("0".equals(qyWebChatUserModel.getErrcode())) { // 要同步到企业微信的对象重新赋值 retMsg = setQyUserObject(userEntity, qyWebChatUserModel); userObjectModel = retMsg.getString(QY_USER_OBJECT); // 往企业微信更新成员信息 retMsg = SynQyWebChatUtil.updateUser(userObjectModel, token); if (Boolean.TRUE.equals(retMsg.getBoolean("code"))) { // 同步成功 synState = SynThirdConsts.SYN_STATE_OK; description = ""; } else { if (retMsg.getString(ERROR).contains(CODE_60104)){ QyWebChatUserModel model = getQyUserList(config, userEntity.getMobilePhone()); assert model != null; thirdObjId = model.getUserid(); thirdName = userEntity.getRealName(); synState = SynThirdConsts.SYN_STATE_OK; }else { // 同步失败 synState = SynThirdConsts.SYN_STATE_FAIL; description = userFlag + retMsg.getString(ERROR); } } } else { // 同步失败,获取企业微信当前用户信息失败 synState = SynThirdConsts.SYN_STATE_FAIL; description = userFlag + "获取企业微信当前用户信息失败"; } } } else { // 同步失败,原因:用户所属部门找不到相应的企业微信ID、邮箱格式不合法 if (synThirdInfoEntity != null) { // 修改同步表 opType = SynThirdConsts.OBJECT_OP_UPD; synThirdInfoPara = synThirdInfoEntity; thirdObjId = synThirdInfoEntity.getThirdObjId(); } else { // 写入同步表 opType = SynThirdConsts.OBJECT_OP_ADD; synThirdInfoPara = null; thirdObjId = ""; } synState = SynThirdConsts.SYN_STATE_FAIL; description = userFlag + retMsg.getString(ERROR); retMsg.put("code", false); retMsg.put(ERROR, description); } } else { // 同步失败 if (synThirdInfoEntity != null) { // 修改同步表 opType = SynThirdConsts.OBJECT_OP_UPD; synThirdInfoPara = synThirdInfoEntity; thirdObjId = synThirdInfoEntity.getThirdObjId(); } else { // 写入同步表 opType = SynThirdConsts.OBJECT_OP_ADD; synThirdInfoPara = null; thirdObjId = ""; } synState = SynThirdConsts.SYN_STATE_FAIL; description = userFlag + TOKEN_NULL; retMsg.put("code", true); retMsg.put(ERROR, description); } } else { // 获取同步表信息 synThirdInfoEntity = synThirdInfoService.getInfoBySysObjId(SynThirdConsts.THIRD_TYPE_QY, SynThirdConsts.DATA_TYPE_USER, userEntity.getId()); if (synThirdInfoEntity != null) { // 修改同步表 opType = SynThirdConsts.OBJECT_OP_UPD; synThirdInfoPara = synThirdInfoEntity; thirdObjId = synThirdInfoEntity.getThirdObjId(); } else { // 写入同步表 opType = SynThirdConsts.OBJECT_OP_ADD; synThirdInfoPara = null; thirdObjId = ""; } synState = SynThirdConsts.SYN_STATE_FAIL; description = userFlag + retMsg.getString(ERROR); retMsg.put("code", false); retMsg.put(ERROR, description); } } else { description = userFlag + SYS_NO_SINGLE_SY; retMsg.put("code", true); retMsg.put(ERROR, description); return retMsg; } // 更新同步表 saveSynThirdInfoEntity(opType, synThirdInfoPara, Integer.parseInt(SynThirdConsts.THIRD_TYPE_QY), Integer.parseInt(SynThirdConsts.DATA_TYPE_USER), userEntity.getId(), thirdObjId, synState, description, thirdName); return retMsg; } @Override public JSONObject updateUserSysToQy(boolean isBatch, UserEntity userEntity, String accessToken, Integer single) throws WxErrorException { SocialsSysConfig config = sysconfigService.getSocialsConfig(); String qyhDepartment = config.getQyhDepartment(); List organizeEntitiesBind = synThirdInfoService.getOrganizeEntitiesBind(qyhDepartment); List listByUserId = userRelationApi.getOrgListByUserId(userEntity.getId(), "organize"); List collect = organizeEntitiesBind.stream() .map(OrganizeEntity::getId) .collect(Collectors.toList()); List relationEntities = listByUserId.stream() .filter(t ->collect.contains(t.getObjectId())) .collect(Collectors.toList()); if (CollUtil.isEmpty(relationEntities)) { return new JSONObject(); } userEntity.setOrganizeId(relationEntities.get(0).getObjectId()); return updateUserSysToQy(isBatch, userEntity, accessToken,""); } /** * 往企业微信删除成员信息 * 不带错误定位判断的功能代码,只获取调用接口的返回信息 20210604 * @param isBatch 是否批量(批量不受开关限制) * @param id 本系统的公司或部门ID * @param accessToken (单条调用时为空) * @return * @throws WxErrorException */ @Override public JSONObject deleteUserSysToQy(boolean isBatch, String id, String accessToken) throws WxErrorException { SocialsSysConfig config = sysconfigService.getSocialsConfig(); // 单条记录执行时,受开关限制 int qyhIsSyn = isBatch ? 1 : config.getQyhIsSynUser(); JSONObject tokenObject ; String token = ""; JSONObject retMsg = new JSONObject(); SynThirdInfoEntity synThirdInfoEntity = synThirdInfoService.getInfoBySysObjId(SynThirdConsts.THIRD_TYPE_QY, SynThirdConsts.DATA_TYPE_USER, id); // 返回值初始化 retMsg.put("code", true); retMsg.put(ERROR, SYS_NO_SINGLE_SY); // 支持同步 if (synThirdInfoEntity != null) { if (qyhIsSyn == 1) { // 获取 access_token if (isBatch) { token = accessToken; } else { String corpId = config.getQyhCorpId(); String corpSecret = config.getQyhAgentSecret(); tokenObject = SynQyWebChatUtil.getAccessToken(corpId, corpSecret); token = tokenObject.getString(TOKEN); } if (token != null && !token.isEmpty()) { if (!"".equals(String.valueOf(synThirdInfoEntity.getThirdObjId())) && !"null".equals(String.valueOf(synThirdInfoEntity.getThirdObjId()))) { retMsg = SynQyWebChatUtil.deleteUser(synThirdInfoEntity.getThirdObjId(), token); if (Boolean.TRUE.equals(retMsg.getBoolean("code"))) { // 同步成功,直接删除同步表记录 synThirdInfoService.delete(synThirdInfoEntity); } else { // 同步失败 saveSynThirdInfoEntity(SynThirdConsts.OBJECT_OP_UPD, synThirdInfoEntity, Integer.parseInt(SynThirdConsts.THIRD_TYPE_QY), Integer.parseInt(SynThirdConsts.DATA_TYPE_USER) , id, synThirdInfoEntity.getThirdObjId() , SynThirdConsts.SYN_STATE_FAIL, retMsg.getString(ERROR), ""); } } else { // 根据企业微信ID找不到相应的信息,直接删除同步表记录 synThirdInfoService.delete(synThirdInfoEntity); } } else { // 同步失败 saveSynThirdInfoEntity(SynThirdConsts.OBJECT_OP_UPD, synThirdInfoEntity, Integer.parseInt(SynThirdConsts.THIRD_TYPE_QY), Integer.parseInt(SynThirdConsts.DATA_TYPE_USER) , id, synThirdInfoEntity.getThirdObjId(), SynThirdConsts.SYN_STATE_FAIL , TOKEN_NULL, ""); retMsg.put("code", false); retMsg.put(ERROR, "access_token值为空,不能同步信息!"); } } else { retMsg.put("code", true); retMsg.put(ERROR, SYS_NO_SINGLE_SY); } } return retMsg; } @Override public JSONObject deleteUserSysToQy(boolean isBatch, List userList, String accessToken, String positionId) throws WxErrorException { for (String id : userList) { this.deleteUserSysToQy(isBatch, id, accessToken); } return new JSONObject(); } /** * 企业微信同步组织部门到本地 * 企业微信同步单个公司或部门到本地(供调用) * 不带错误定位判断的功能代码,只获取调用接口的返回信息 20210604 * @param isBatch 是否批量(批量不受开关限制) * @param deptEntity * @param accessToken (单条调用时为空) * @return */ @Override public JSONObject createDepartmentQyToSys(boolean isBatch, QyWebChatDeptModel deptEntity, String accessToken) { SocialsSysConfig config = sysconfigService.getSocialsConfig(); // 单条记录执行时,受开关限制 int dingIsSyn = isBatch ? 1 : config.getQyhIsSynOrg(); Long dingDeptId = deptEntity.getId(); String dingDeptName = deptEntity.getName(); Long dingParentId = deptEntity.getParentId(); Integer synState = 0; String deptFlag = "创建:"; String description = ""; JSONObject retMsg = new JSONObject(); boolean isDeptDiff = true; String sysParentId = ""; String sysObjId = ""; // 返回值初始化 retMsg.put("code", true); retMsg.put(ERROR, "创建:系统未设置单条同步"); boolean createOrUpdate = true; SynThirdInfoEntity entity = new SynThirdInfoEntity(); // 支持同步 if (isBatch || dingIsSyn == 1) { boolean tag = false; if (dingDeptId == 1) { tag = true; } SynThirdInfoEntity synThirdInfoEntity = synThirdInfoService.getInfoByThirdObjId(SynThirdConsts.THIRD_TYPE_QY, SynThirdConsts.DATA_TYPE_ORG, dingParentId + ""); isDeptDiff = retMsg.getBoolean("code"); if (isDeptDiff || tag) { sysParentId = tag ? " -1" : synThirdInfoEntity.getSysObjId(); // 新增保存组织 OrganizeEntity newOrg = new OrganizeEntity(); sysObjId = RandomUtil.uuId(); newOrg.setId(sysObjId); if (!"1".equals(dingDeptId + "")) { Assert.notNull(sysParentId, "父级组织未同步"); newOrg.setCategory(SynThirdConsts.OBJECT_TYPE_DEPARTMENT); newOrg.setParentId(sysParentId); // 通过组织id获取父级组织 String organizeIdTree = organizeApi.getOrganizeIdTree(newOrg); List depsByParentId = organizeApi.getDepsByParentId(sysParentId); if (depsByParentId.stream().noneMatch(t->t.getFullName().equals(dingDeptName))){ newOrg.setOrganizeIdTree(organizeIdTree + "," + sysObjId); newOrg.setFullName(dingDeptName); newOrg.setSortCode(deptEntity.getOrder() != null ? deptEntity.getOrder() : 1L); organizeApi.create(newOrg); } } else { String qyhDepartment = config.getQyhDepartment(); //绑定最高组织 OrganizeEntity info = organizeApi.getInfoById(qyhDepartment); sysObjId = info.getId(); entity = synThirdInfoService .getInfoBySysObjId(SynThirdConsts.THIRD_TYPE_QY , SynThirdConsts.DATA_TYPE_ORG, info.getId()); if (BeanUtil.isNotEmpty(entity)) { createOrUpdate = false; } } // 中间表 retMsg.put(RET_DEPT_ID, sysObjId); synState = SynThirdConsts.SYN_STATE_OK; } else { // 同步失败,上级部门无对应的企业微信ID synState = SynThirdConsts.SYN_STATE_FAIL; description = deptFlag + "部门所属的上级部门未同步到本地"; retMsg.put("code", false); retMsg.put(ERROR, description); retMsg.put(RET_DEPT_ID, "0"); } } // 更新同步表 saveSynThirdInfoEntity(createOrUpdate ? SynThirdConsts.OBJECT_OP_ADD : SynThirdConsts.OBJECT_OP_UPD , createOrUpdate ? null : entity, Integer.parseInt(SynThirdConsts.THIRD_TYPE_QY), Integer.parseInt(SynThirdConsts.DATA_TYPE_ORG) , sysObjId, dingDeptId + "", synState, description, deptEntity.getName()); return retMsg; } /** * 企业微信更新组织-部门到本地 * 不带错误定位判断的功能代码,只获取调用接口的返回信息 20210604 * @param isBatch 是否批量(批量不受开关限制) * @param deptEntity * @param accessToken (单条调用时为空) * @return */ @Override public JSONObject updateDepartmentQyToSys(boolean isBatch, QyWebChatDeptModel deptEntity, String accessToken) { SocialsSysConfig config = sysconfigService.getSocialsConfig(); // 单条记录执行时,受开关限制 int dingIsSyn = isBatch ? 1 : config.getQyhIsSynOrg(); JSONObject retMsg = new JSONObject(); SynThirdInfoEntity synThirdInfoEntity ; SynThirdInfoEntity synThirdInfoParentEntity; String opType = ""; Integer synState = 0; String description = ""; String sysObjId = ""; String sysParentId = ""; SynThirdInfoEntity synThirdInfoPara = new SynThirdInfoEntity(); boolean isDeptDiff = true; String deptFlag = "更新:"; Long dingDeptId = deptEntity.getId(); String dingDeptName = deptEntity.getName(); Long dingParentId = deptEntity.getParentId(); OrganizeEntity orgInfo ; // 返回值初始化 retMsg.put("code", true); retMsg.put(ERROR, SYS_NO_SINGLE_SY); if (isBatch || dingIsSyn == 1) { // 获取同步表信息 synThirdInfoEntity = synThirdInfoService.getInfoByThirdObjId(SynThirdConsts.THIRD_TYPE_QY, SynThirdConsts.DATA_TYPE_ORG, dingDeptId + ""); synThirdInfoParentEntity = synThirdInfoService.getInfoByThirdObjId(SynThirdConsts.THIRD_TYPE_QY, SynThirdConsts.DATA_TYPE_ORG, dingParentId + ""); if (synThirdInfoParentEntity == null) { retMsg.put("code", false); retMsg.put(ERROR, "上级部门未同步"); return retMsg; } isDeptDiff = retMsg.getBoolean("code"); if (isDeptDiff) { sysParentId = synThirdInfoParentEntity.getSysObjId(); // 判断当前部门对应的第三方的合法性 if (Boolean.FALSE.equals(retMsg.getBoolean("code"))) { if ("3".equals(retMsg.getString("flag")) || "1".equals(retMsg.getString("flag"))) { // flag:3 未同步,需要创建同步到企业微信、写入同步表 // flag:1 已同步但第三方上没对应的ID,需要删除原来的同步信息,再创建同步到企业微信、写入同步表 if ("1".equals(retMsg.getString("flag"))) { synThirdInfoService.delete(synThirdInfoEntity); } opType = SynThirdConsts.OBJECT_OP_ADD; synThirdInfoPara = null; // 新增保存组织 orgInfo = new OrganizeEntity(); sysObjId = RandomUtil.uuId(); orgInfo.setId(sysObjId); if (!"1".equals(dingDeptId + "")) { orgInfo.setCategory(SynThirdConsts.OBJECT_TYPE_DEPARTMENT); orgInfo.setParentId(sysParentId); // 通过组织id获取父级组织 String organizeIdTree = organizeApi.getOrganizeIdTree(orgInfo); orgInfo.setOrganizeIdTree(organizeIdTree + "," + sysObjId); orgInfo.setFullName(dingDeptName); orgInfo.setSortCode(deptEntity.getOrder() != null ? deptEntity.getOrder() : 1L); organizeApi.save(orgInfo); } else { sysObjId = organizeApi.getOrganizeByParentId().get(0).getId(); } // 同步成功 retMsg.put(RET_DEPT_ID, sysObjId); synState = SynThirdConsts.SYN_STATE_OK; description = ""; } if ("2".equals(retMsg.getString("flag"))) { // flag:2 已同步但第三方ID为空,需要创建同步到企业微信、修改同步表 opType = SynThirdConsts.OBJECT_OP_UPD; synThirdInfoPara = synThirdInfoEntity; // 新增保存组织 orgInfo = new OrganizeEntity(); sysObjId = RandomUtil.uuId(); orgInfo.setId(sysObjId); if (!"1".equals(dingDeptId + "")) { orgInfo.setCategory(SynThirdConsts.OBJECT_TYPE_DEPARTMENT); orgInfo.setParentId(sysParentId); // 通过组织id获取父级组织 String organizeIdTree = organizeApi.getOrganizeIdTree(orgInfo); orgInfo.setOrganizeIdTree(organizeIdTree + "/" + sysObjId); orgInfo.setEnCode(RandomUtil.uuId()); orgInfo.setFullName(dingDeptName); orgInfo.setSortCode(deptEntity.getOrder() != null ? deptEntity.getOrder() : 1L); organizeApi.save(orgInfo); } else { sysObjId = organizeApi.getOrganizeByParentId().get(0).getId(); } // 同步成功 retMsg.put(RET_DEPT_ID, sysObjId); synState = SynThirdConsts.SYN_STATE_OK; description = ""; } } else { // 更新同步表 opType = SynThirdConsts.OBJECT_OP_UPD; synThirdInfoPara = synThirdInfoEntity; sysObjId = synThirdInfoEntity.getSysObjId(); orgInfo = organizeApi.getInfoById(sysObjId); if (orgInfo != null) { orgInfo.setFullName(dingDeptName); if (!"1".equals(dingDeptId + "")) { orgInfo.setParentId(sysParentId); orgInfo.setOrganizeIdTree(orgInfo.getOrganizeIdTree().replace("," + orgInfo.getId(), "")); organizeApi.update(orgInfo.getId(), orgInfo); } // 同步成功 synState = SynThirdConsts.SYN_STATE_OK; description = ""; } else { // 同步失败 synState = SynThirdConsts.SYN_STATE_FAIL; description = deptFlag + "未找到对应的部门"; } } } else { synThirdInfoEntity = synThirdInfoService.getInfoByThirdObjId(SynThirdConsts.THIRD_TYPE_QY, SynThirdConsts.DATA_TYPE_ORG, dingDeptId + ""); // 同步失败,上级部门检查有异常 if (synThirdInfoEntity != null) { // 修改同步表 opType = SynThirdConsts.OBJECT_OP_UPD; synThirdInfoPara = synThirdInfoEntity; sysObjId = synThirdInfoEntity.getSysObjId(); } else { // 写入同步表 opType = SynThirdConsts.OBJECT_OP_ADD; synThirdInfoPara = null; sysObjId = ""; } synState = SynThirdConsts.SYN_STATE_FAIL; description = deptFlag + "上级部门无对应的本地ID"; retMsg.put("code", false); retMsg.put(ERROR, description); } } else { // 未设置单条同步,归并到未同步状态 // 获取同步表信息 synThirdInfoEntity = synThirdInfoService.getInfoByThirdObjId(SynThirdConsts.THIRD_TYPE_QY, SynThirdConsts.DATA_TYPE_ORG, dingDeptId + ""); if (synThirdInfoEntity != null) { // 修改同步表 opType = SynThirdConsts.OBJECT_OP_UPD; synThirdInfoPara = synThirdInfoEntity; sysObjId = synThirdInfoEntity.getSysObjId(); } else { // 写入同步表 opType = SynThirdConsts.OBJECT_OP_ADD; synThirdInfoPara = null; sysObjId = ""; } synState = SynThirdConsts.SYN_STATE_NO; description = deptFlag + SYS_NO_SINGLE_SY; retMsg.put("code", true); retMsg.put(ERROR, description); } // 更新同步表 saveSynThirdInfoEntity(opType, synThirdInfoPara, Integer.parseInt(SynThirdConsts.THIRD_TYPE_QY), Integer.parseInt(SynThirdConsts.DATA_TYPE_ORG) , sysObjId, dingDeptId + "", synState, description, deptEntity.getName()); return retMsg; } /** * 企业微信同步用户到本地 * @param isBatch 是否批量(批量不受开关限制) * @param qyWebChatUserModel * @return */ @Override public JSONObject createUserQyToSys(boolean isBatch, QyWebChatUserModel qyWebChatUserModel, String accessToken) throws WxErrorException { String dingUserId = qyWebChatUserModel.getUserid(); List department = qyWebChatUserModel.getDepartment(); SocialsSysConfig config = sysconfigService.getSocialsConfig(); String corpId = config.getQyhCorpId(); JSONObject retMsg2 = SynQyWebChatUtil.getLinkedcorpUserById(corpId + "/" + dingUserId, accessToken); String dingUserName = qyWebChatUserModel.getName(); String dingMobile = retMsg2.getJSONObject("userinfo").getString("mobile"); String sysObjId = ""; // 单条记录执行时,受开关限制 int dingIsSyn = config.getQyhIsSynUser(); JSONObject retMsg = new JSONObject(); int synState = 0; String description = ""; String userFlag = "创建:"; UserEntity userEntity = new UserEntity(); String tag = SynThirdConsts.OBJECT_OP_ADD; if (isBatch || dingIsSyn == 1) { // 检测账户唯一 UserEntity userAccount = userApi.getUserByMobile(dingMobile); if (userAccount != null) { // 查询用户id在不在同步表 sysObjId = userAccount.getId(); boolean hasExist = synThirdInfoService.getBySysObjId(sysObjId, SynThirdConsts.THIRD_TYPE_QY); if (hasExist) { return retMsg; } else { retMsg.put("code", true); description = "账户名重复:线上手机账号" + dingMobile + "自动合并为本地账号"; synThirdUtil.syncDingUserRelation(sysObjId,department,SynThirdConsts.THIRD_TYPE_DING); synState = SynThirdConsts.SYN_STATE_OK; retMsg.put("msg", description); } } else { // 判断中间表用户组织是否存在 List deptIdList = qyWebChatUserModel.getDepartment(); List deptIdStrList = deptIdList.stream().map(t -> t + "").collect(Collectors.toList()); QueryWrapper wrapper = new QueryWrapper<>(); wrapper.lambda().in(SynThirdInfoEntity::getThirdObjId, deptIdStrList); wrapper.lambda().eq(SynThirdInfoEntity::getThirdType, Integer.valueOf(SynThirdConsts.THIRD_TYPE_QY)); List synThirdInfoEntities = synThirdInfoService.list(wrapper); if (synThirdInfoEntities != null && !synThirdInfoEntities.isEmpty()) { // 返回值初始化 retMsg.put("code", true); retMsg.put(ERROR, userFlag + SYS_NO_SINGLE_SY); userEntity.setId(RandomUtil.uuId()); userEntity.setHeadIcon("001.png"); userEntity.setAccount(dingMobile); // 工号 userEntity.setEmail(qyWebChatUserModel.getEmail()); userEntity.setMobilePhone(dingMobile); userEntity.setRealName(dingUserName); userEntity.setEnabledMark(1); if (StringUtils.isBlank(userEntity.getOrganizeId())) { String orgId = synThirdInfoService.getSysByThird(String.valueOf(deptIdList.get(0))); userEntity.setOrganizeId(orgId); } sysObjId = userEntity.getId(); List orgIdList = new ArrayList<>(); List posIdList = new ArrayList<>(); for (String deptIdStr : deptIdStrList) { String orgId = synThirdInfoService.getSysByThird(deptIdStr); List ids = new ArrayList<>(); ids.add(orgId); List listByOrganizeId = positionApi.getListByOrganizeId(ids); List positionEntityList = listByOrganizeId.stream() .filter(t -> t.getDefaultMark().equals(1)) .collect(Collectors.toList()); if (CollUtil.isNotEmpty(positionEntityList)) { posIdList.add(positionEntityList.get(0).getId()); } orgIdList.add(orgId); } userEntity.setPositionId(String.join(",", posIdList)); userEntity.setOrganizeId(String.join(",", orgIdList)); userEntity.setSortCode(0L); userApi.create(userEntity); // 往同步写入本系统与第三方的对应信息 if (Boolean.TRUE.equals(retMsg.getBoolean("code"))) { // 同步成功 synState = SynThirdConsts.SYN_STATE_OK; } else { // 同步失败 synState = SynThirdConsts.SYN_STATE_FAIL; description = userFlag + retMsg.getString(ERROR); } } else { // 无须同步,未同步状态 synState = SynThirdConsts.SYN_STATE_NO; description = userFlag + "用户未同步组织信息"; retMsg.put("code", false); retMsg.put(ERROR, description); } } } else { // 无须同步,未同步状态 synState = SynThirdConsts.SYN_STATE_NO; description = userFlag + SYS_NO_SINGLE_SY; retMsg.put("code", true); retMsg.put(ERROR, description); } // 更新同步表 saveSynThirdInfoEntity(tag, null, Integer.parseInt(SynThirdConsts.THIRD_TYPE_QY), Integer.parseInt(SynThirdConsts.DATA_TYPE_USER) , sysObjId, dingUserId, synState, description, qyWebChatUserModel.getName()); return retMsg; } // 更新同步表 /** * 企业微信更新用户信息到本地 * 将组织、用户的信息写入同步表 */ @Override public JSONObject updateUserQyToSystem(boolean isBatch, QyWebChatUserModel qyWebChatUserModel, String accessToken) { SocialsSysConfig config = sysconfigService.getSocialsConfig(); JSONObject retMsg = new JSONObject(); SynThirdInfoEntity synThirdInfoEntity ; String opType = ""; String thirdObjId = ""; int synState = 0; String description = ""; String userFlag = "更新:"; // 赋值第三方id thirdObjId = qyWebChatUserModel.getUserid(); // 返回值初始化 retMsg.put("code", true); retMsg.put(ERROR, userFlag + SYS_NO_SINGLE_SY); // 单条记录执行时,受开关限制 int dingIsSyn = config.getQyhIsSynUser(); // 支持同步 if (isBatch || dingIsSyn == 1) { // 获取同步表信息 /** * 获取指定第三方工具、指定数据类型、本地对象ID的同步信息 * // 获取方式如果第三方用户id和第三方组织id会一致则须修改 * thirdType 22 企业微信 * dataType 2 用户 * thirdId 第三方id */ synThirdInfoEntity = synThirdInfoService.getInfoByThirdObjId(SynThirdConsts.THIRD_TYPE_QY, SynThirdConsts.DATA_TYPE_USER, thirdObjId); if (synThirdInfoEntity != null && StringUtils.isNoneBlank(synThirdInfoEntity.getSysObjId())) { opType = SynThirdConsts.OBJECT_OP_UPD; String sysObjId = synThirdInfoEntity.getSysObjId(); UserEntity info = userApi.getInfoById(sysObjId); if (info == null) { description = "本地更新记录未找到"; retMsg.put("code", false); retMsg.put(ERROR, description); synThirdInfoService.removeById(synThirdInfoEntity.getId()); } else { // 更新系统用户表 List deptIdList = qyWebChatUserModel.getDepartment(); List deptIdStrList = deptIdList.stream().map(t -> t + "").collect(Collectors.toList()); List orgIdList = new ArrayList<>(); List posIdList = new ArrayList<>(); for (String deptIdStr : deptIdStrList) { String orgId = synThirdInfoService.getSysByThird(deptIdStr, Integer.valueOf(SynThirdConsts.THIRD_TYPE_QY)); orgIdList.add(orgId); List ids = new ArrayList<>(); List listByOrganizeId = positionApi.getListByOrganizeId(ids); List positionEntityList = listByOrganizeId.stream() .filter(t -> t.getDefaultMark().equals(1)) .collect(Collectors.toList()); if (CollUtil.isNotEmpty(positionEntityList)) { posIdList.add(positionEntityList.get(0).getId()); } } info.setPositionId(String.join(",", posIdList)); info.setOrganizeId(String.join(",", orgIdList)); userApi.update(info.getId(), info); synState = 1; // 更新同步表记录 description = "账号同步更新完成"; saveSynThirdInfoEntity(opType, synThirdInfoEntity, Integer.parseInt(SynThirdConsts.THIRD_TYPE_QY), Integer.parseInt(SynThirdConsts.DATA_TYPE_USER) , synThirdInfoEntity.getSysObjId(), thirdObjId, synState, description, qyWebChatUserModel.getName()); } } else { if ((synThirdInfoEntity != null && StringUtils.isBlank(synThirdInfoEntity.getSysObjId()))) { // 删除记录 synThirdInfoService.removeById(synThirdInfoEntity.getId()); } try { this.createUserQyToSys(true, qyWebChatUserModel, accessToken); } catch (Exception e) { e.printStackTrace(); } } } else { // 未设置单条同步,归并到未同步状态 synState = SynThirdConsts.SYN_STATE_NO; description = userFlag + SYS_NO_SINGLE_SY; retMsg.put("code", true); retMsg.put(ERROR, description); opType = SynThirdConsts.OBJECT_OP_ADD; saveSynThirdInfoEntity(opType, null, Integer.parseInt(SynThirdConsts.THIRD_TYPE_QY), Integer.parseInt(SynThirdConsts.DATA_TYPE_USER) , null, thirdObjId, synState, description, ""); } return retMsg; } }