组织同步
组织同步包括两个方向:
- 平台同步到第三方
- 第三方系统作为外部系统,注册到企业门户中
- 企业门户发送组织变化通知给第三方系统
- 第三方系统收到最新组织镜像 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();
}
注册第三方系统
将外部接口服务注册到当前门户下面
组织同步设置
在“企业门户-系统管理-系统配置-组织同步配置”中,添加注册的第三方系统
发送通知
开启自动通知
手工发送通知
获取组织数据
参考《集成外部服务》中的平台服务接口-获取组织增量
第三方同步到平台
平台提供 postOrgs 接口以供组织导入使用,参考《组织权限 API》中维护组织和用户
注意:调用此接口需要携带集成账号的登录 cookie 会话