组织同步

组织同步包括两个方向:

  • 平台同步到第三方
    • 第三方系统作为外部系统,注册到企业门户中
    • 企业门户发送组织变化通知给第三方系统
    • 第三方系统收到最新组织镜像 md5,和上一次更新后收到的组织镜像 md5 比较
      • 如果相同,说明组织是最新的,无需更新
      • 如果不同,说明组织需要更新
        • 调用获取组织增量接口
          • 如果是第一次调用,无需参数,会获取全部组织数据
          • 如果不是第一次调用,参数传入上一次更新的组织镜像 md5,会获取组织增量数据
        • 调用接口后,收到组织变更数据及最新组织镜像 md5,组织更新后,存储最新组织镜像 md5,作为下一次获取组织增量的参数
  • 第三方同步到平台
    • 调用 postOrgs API 将组织同步到平台

平台同步到第三方

第三方系统需要作为外部系统,整体过程参考《集成外部服务

实现接口

第三方系统需要实现的两个接口:/notice 和 /serviceMetaInfo,示例代码如下

通知接口 /notice

基于 spring 及 hutool 实现,参考如下

@Autowired
OrgSyncService orgSyncService;

// 外部验证密钥
String apisecretStr = "1234567890";
// 上一次组织校验码
String upOrgDigest = "86e2258d22ad7b43aba5684fb9050c31";


/**
* 接收组织同步通知
* 
* @param params    推送消息内容
* @param apisecret 请求密钥
* @throws IOException 
* @throws ParseException 
*/
@PostMapping("/main/notice")
public void notice(@RequestBody String params, @RequestParam(name = "apisecret") String apisecret,HttpServletRequest httpServletRequest) throws ParseException, IOException{
    // TODO 安全校验逻辑
    if (!apisecretStr.equals(apisecret)) {
        throw new RuntimeException("密钥错误:" + apisecret);
    }
    // 组织机构数据
    JSONObject result = JSONObject.parseObject(params);
    logger.warn("通知类型:{}", result.getString("type"));
    String orgDigest = result.getJSONObject("data").getString("orgDigest");
    // 判断组织是否有变化
    if (upOrgDigest.equals(orgDigest)) {
        // 如果没有变化不执行下面的组织数据同步操作
        return;
    }
    // 使用上一次组织校验码orgDigest获取全量或是增量组织数据(当orgDigest为空时则获取全量数据)
    JSONObject orgsData = orgSyncService.syncOrgs(upOrgDigest,httpServletRequest);
    // TODO 保存组织校验码,用于下次同步时比较
    upOrgDigest = orgsData.getString("orgDigest");
    // TODO 同步组织数据到第三方应用
    JSONObject updateOrgs = orgsData.getJSONObject("data");
    // 用户数据
    JSONArray users = updateOrgs.getJSONArray("users");
    logger.warn("保存用户数据到第三方:{}", users.toJSONString());
    // 组织数据
    JSONArray orgs = updateOrgs.getJSONArray("orgs");
    logger.warn("保存组织数据到第三方:{}", orgs.toJSONString());
}


//orgSyncService代码如下:
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;

//企业门户地址
private String entryBaseUrl="http://entrylzsentry8-vip.trunk2.xcaas.com:8800";

/**
* 根据组织md5信息获取组织数据
* @param orgDigest        为空时获取全量组织
* @throws IOException 
* @throws ParseException 
*/
public JSONObject syncOrgs(String orgDigest,HttpServletRequest httpServletRequest) throws ParseException, IOException {
    //使用账号密码,登录低代码平台
    JSONObject loginData=this.login("kaifa1", "aSDF1@#$");

    //获取组织同步数据
    String syncOrgUrl="/entry/misc/org/getOrgSnapshot";

    Map<String, String> data = new HashMap<>();
    data.put("orgDigest", orgDigest);

    Map<String, String> extHeaders = ServletUtil.getHeaderMap(httpServletRequest);
    extHeaders.put("content-type", "application/json;charset=UTF-8");
    extHeaders.put("Accept", "application/json");
    extHeaders.put("Cookie","user_session=" + loginData.getString("userSession"));

    //TODO 同步平台组织数据到当前应用
    String orgDataStr=HttpRequest.get(entryBaseUrl + syncOrgUrl).addHeaders(extHeaders).formStr(data).execute().body();
    logger.warn("获取同步组织数据:{}",orgDataStr);
    return JSON.parseObject(orgDataStr);
}

/**
* 低代码平台用户密码登录
* @param username
* @param password
* @return    用户登录相关信息
* @throws IOException 
* @throws ParseException 
*/
public JSONObject login(String username,String password) throws ParseException, IOException {
    //请求参数
    Map<String,Object> fromData=new HashMap<>();
    fromData.put("username", username);
    fromData.put("password", password);    

    HttpResponse httpResponse=HttpRequest.post(entryBaseUrl + "/login").form(fromData).execute();
    JSONObject responseJSON =JSON.parseObject(httpResponse.body());

    JSONObject loginData = new JSONObject();
    loginData.put("userId",responseJSON.getString("id"));
    loginData.put("userName",responseJSON.getString("userName"));
    loginData.put("userSession",httpResponse.header("X-User-Session"));
    String accessToken=httpResponse.header("X-Credential-Access-Token");
    if (StrUtil.isNotBlank(accessToken)) {
        loginData.put("credentialAccessToken",accessToken);
    }

    logger.warn("登录低代码平台:{}",loginData.toString());
    return loginData;

}

基于平台应用实现,参考如下

@Autowired
OrgSyncService orgSyncService;

// 外部验证密钥
String apisecretStr = "1234567890";
// 上一次组织校验码
String upOrgDigest = "86e2258d22ad7b43aba5684fb9050c31";


/**
* 接收组织同步通知
* 
* @param params    推送消息内容
* @param apisecret 请求密钥
* @throws IOException 
* @throws ParseException 
*/
@PostMapping("/main/notice")
public void notice(@RequestBody String params, @RequestParam(name = "apisecret") String apisecret) throws ParseException, IOException{
    // TODO 安全校验逻辑
    if (!apisecretStr.equals(apisecret)) {
        throw new RuntimeException("密钥错误:" + apisecret);
    }
    // 组织机构数据
    JSONObject result = JSONObject.parseObject(params);
    logger.warn("通知类型:{}", result.getString("type"));
    String orgDigest = result.getJSONObject("data").getString("orgDigest");
    // 判断组织是否有变化
    if (upOrgDigest.equals(orgDigest)) {
        // 如果没有变化不执行下面的组织数据同步操作
        return;
    }
    // 使用上一次组织校验码orgDigest获取全量或是增量组织数据(当orgDigest为空时则获取全量数据)
    JSONObject orgsData = orgSyncService.syncOrgs(upOrgDigest);
    // TODO 保存组织校验码,用于下次同步时比较
    upOrgDigest = orgsData.getString("orgDigest");
    // TODO 同步组织数据到第三方应用
    JSONObject updateOrgs = orgsData.getJSONObject("data");
    // 用户数据
    JSONArray users = updateOrgs.getJSONArray("users");
    logger.warn("保存用户数据到第三方:{}", users.toJSONString());
    // 组织数据
    JSONArray orgs = updateOrgs.getJSONArray("orgs");
    logger.warn("保存组织数据到第三方:{}", orgs.toJSONString());
}


//orgSyncService代码如下:

//企业门户地址
private String entryBaseUrl="http://entrylzsentry8-vip.trunk2.xcaas.com:8800";

/**
* 根据组织md5信息获取组织数据
* @param orgDigest        为空时获取全量组织
* @throws IOException 
* @throws ParseException 
*/
public JSONObject syncOrgs(String orgDigest) throws ParseException, IOException {
    //使用账号密码,登录低代码平台
    String userSession=this.login("kaifa1", "aSDF1@#$");

    //获取组织同步数据    
    String syncOrgUrl="/entry/misc/org/getOrgSnapshot";    

    Map<String, String> data = new HashMap<>();
    data.put("orgDigest", orgDigest);

    Map<String, String> extHeaders = ServiceUtil.getExtHeaders(SpringWebUtil.getRequest());
    extHeaders.put("content-type", "application/json;charset=UTF-8");
    extHeaders.put("Accept", "application/json");
    extHeaders.put("Cookie","user_session=" + userSession);

    JSONObject orgData =  ServiceUtil.get(entryBaseUrl + syncOrgUrl,data,extHeaders);
    logger.warn("获取同步组织数据:{}",orgData.toString());
    return orgData;
}

/**
* 低代码平台用户密码登录
* @param username
* @param password
* @return
*/
public String login(String username,String password){
    //请求参数
    Map<String,Object> fromData=new HashMap<>();
    fromData.put("username", username);
    fromData.put("password", password);    

    String userSession= AuthUtil.login(entryBaseUrl, username, password);    

    logger.warn("登录低代码平台:{}",userSession);
    return userSession;        
}

服务元信息接口 /serviceMetaInfo

参考如下

/**
* 服务元信息注册
* 
* @param apisecret 请求密钥
* @return
*/
@GetMapping("/main/serviceMetaInfo")
public String serviceMetaInfo(@RequestParam(name = "apisecret") String apisecret) {
    // TODO 校验apisecret
    if (!apisecretStr.equals(apisecret)) {
        throw new RuntimeException("密钥错误:" + apisecret);
    }
    JSONObject json = new JSONObject();
    json.put("enableDevMode", true);
    json.put("profile", "");
    json.put("menu", null);
    json.put("authorize", null);
    // 根据实际需求定义服务名称及标签
    JSONObject serviceInfo = new JSONObject();
    serviceInfo.put("name", "testOrgService");//自定义
    serviceInfo.put("label", "测试组织服务");//自定义
    // TODO 元数据信息根据实际情况补充
    json.put("serviceInfo", serviceInfo);
    return json.toJSONString();
}

注册第三方系统

将外部接口服务注册到当前门户下面

image-20240701162455427

image-20240701162802857

组织同步设置

在“企业门户-系统管理-系统配置-组织同步配置”中,添加注册的第三方系统

image-20240701163122970

image-20240701163321134

发送通知

开启自动通知

image-20240701164310065

image-20240701164423448

image-20240701164502913

手工发送通知

image-20240701164716101

获取组织数据

参考《集成外部服务》中的平台服务接口-获取组织增量

第三方同步到平台

平台提供 postOrgs 接口以供组织导入使用,参考《组织权限 API》中维护组织和用户

注意:调用此接口需要携带集成账号的登录 cookie 会话

results matching ""

    No results matching ""