Merge branch 'dev' into test
This commit is contained in:
@@ -97,30 +97,6 @@ public class IWorkIntegrationController {
|
|||||||
return success(orgRestService.listUsers(reqVO));
|
return success(orgRestService.listUsers(reqVO));
|
||||||
}
|
}
|
||||||
|
|
||||||
// @PostMapping("/hr/subcompany/sync")
|
|
||||||
// @Operation(summary = "同步分部信息至 iWork")
|
|
||||||
// public CommonResult<IWorkHrSyncRespVO> syncSubcompanies(@Valid @RequestBody IWorkOrgSyncReqVO reqVO) {
|
|
||||||
// return success(orgRestService.syncSubcompanies(reqVO));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @PostMapping("/hr/department/sync")
|
|
||||||
// @Operation(summary = "同步部门信息至 iWork")
|
|
||||||
// public CommonResult<IWorkHrSyncRespVO> syncDepartments(@Valid @RequestBody IWorkOrgSyncReqVO reqVO) {
|
|
||||||
// return success(orgRestService.syncDepartments(reqVO));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @PostMapping("/hr/job-title/sync")
|
|
||||||
// @Operation(summary = "同步岗位信息至 iWork")
|
|
||||||
// public CommonResult<IWorkHrSyncRespVO> syncJobTitles(@Valid @RequestBody IWorkOrgSyncReqVO reqVO) {
|
|
||||||
// return success(orgRestService.syncJobTitles(reqVO));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @PostMapping("/hr/user/sync")
|
|
||||||
// @Operation(summary = "同步人员信息至 iWork")
|
|
||||||
// public CommonResult<IWorkHrSyncRespVO> syncUsers(@Valid @RequestBody IWorkOrgSyncReqVO reqVO) {
|
|
||||||
// return success(orgRestService.syncUsers(reqVO));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// ----------------- 同步到本地 -----------------
|
// ----------------- 同步到本地 -----------------
|
||||||
|
|
||||||
@PostMapping("/hr/departments/full-sync")
|
@PostMapping("/hr/departments/full-sync")
|
||||||
|
|||||||
@@ -1,74 +0,0 @@
|
|||||||
package com.zt.plat.module.system.controller.admin.integration.iwork.vo;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonAnyGetter;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonAnySetter;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* iWork 人力同步响应。
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Schema(description = "iWork 人力同步响应")
|
|
||||||
public class IWorkHrSyncRespVO {
|
|
||||||
|
|
||||||
@Schema(description = "响应码")
|
|
||||||
private String code;
|
|
||||||
|
|
||||||
@Schema(description = "提示信息")
|
|
||||||
private String message;
|
|
||||||
|
|
||||||
@Schema(description = "是否成功")
|
|
||||||
private boolean success;
|
|
||||||
|
|
||||||
@Schema(description = "同步结果明细")
|
|
||||||
private List<SyncResult> result;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Schema(description = "同步结果项")
|
|
||||||
public static class SyncResult {
|
|
||||||
|
|
||||||
@Schema(description = "操作动作 add/update/delete")
|
|
||||||
@JsonProperty("@action")
|
|
||||||
private String action;
|
|
||||||
|
|
||||||
@Schema(description = "外部编码")
|
|
||||||
@JsonProperty("code")
|
|
||||||
private String code;
|
|
||||||
|
|
||||||
@Schema(description = "执行结果 success/fail")
|
|
||||||
@JsonProperty("result")
|
|
||||||
private String result;
|
|
||||||
|
|
||||||
@Schema(description = "是否成功")
|
|
||||||
@JsonProperty("success")
|
|
||||||
private Boolean success;
|
|
||||||
|
|
||||||
@Schema(description = "失败描述")
|
|
||||||
@JsonProperty("message")
|
|
||||||
private String message;
|
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
private Map<String, Object> attributes;
|
|
||||||
|
|
||||||
@JsonAnySetter
|
|
||||||
public void putAttribute(String key, Object value) {
|
|
||||||
if (attributes == null) {
|
|
||||||
attributes = new LinkedHashMap<>();
|
|
||||||
}
|
|
||||||
attributes.put(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonAnyGetter
|
|
||||||
public Map<String, Object> any() {
|
|
||||||
return attributes == null ? Collections.emptyMap() : attributes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
package com.zt.plat.module.system.controller.admin.integration.iwork.vo;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import jakarta.validation.constraints.NotEmpty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 同步 iWork 人力组织信息的请求。
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class IWorkOrgSyncReqVO {
|
|
||||||
|
|
||||||
@Schema(description = "同步数据集合,将被序列化为 data 传给 iWork", requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
@NotEmpty(message = "同步数据不能为空")
|
|
||||||
private List<Map<String, Object>> data;
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,35 @@
|
|||||||
package com.zt.plat.module.system.framework.integration.iwork.config;
|
package com.zt.plat.module.system.framework.integration.iwork.config;
|
||||||
|
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 负责加载 {@link IWorkProperties} 的自动配置类。
|
* 负责加载 {@link IWorkProperties} 的自动配置类。
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@RequiredArgsConstructor
|
||||||
@EnableConfigurationProperties(IWorkProperties.class)
|
@EnableConfigurationProperties(IWorkProperties.class)
|
||||||
public class IWorkIntegrationConfiguration {
|
public class IWorkIntegrationConfiguration {
|
||||||
|
|
||||||
|
private final IWorkProperties properties;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
void reportConfigurationStatus() {
|
||||||
|
if (!properties.hasAnyConfiguredValue()) {
|
||||||
|
log.info("[iWork] 未检测到集成配置,默认关闭 iWork 功能。需要时请在配置文件中补充 iwork.* 项。");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<String> issues = properties.collectCriticalIssues();
|
||||||
|
if (!issues.isEmpty()) {
|
||||||
|
log.warn("[iWork] 配置不完整:{}。系统会继续启动,但 iWork 能力将不可用。", String.join(";", issues));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
log.info("[iWork] 已检测到完整配置,iWork 集成能力已启用。");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,18 @@
|
|||||||
package com.zt.plat.module.system.framework.integration.iwork.config;
|
package com.zt.plat.module.system.framework.integration.iwork.config;
|
||||||
|
|
||||||
import jakarta.validation.Valid;
|
|
||||||
import jakarta.validation.constraints.Min;
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
|
||||||
import jakarta.validation.constraints.NotNull;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* iWork 集成所需的配置项。
|
* iWork 集成所需的配置项。
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Validated
|
|
||||||
@ConfigurationProperties(prefix = "iwork")
|
@ConfigurationProperties(prefix = "iwork")
|
||||||
public class IWorkProperties {
|
public class IWorkProperties {
|
||||||
|
|
||||||
@@ -39,16 +36,11 @@ public class IWorkProperties {
|
|||||||
*/
|
*/
|
||||||
private String userId;
|
private String userId;
|
||||||
|
|
||||||
@Valid
|
|
||||||
private final Paths paths = new Paths();
|
private final Paths paths = new Paths();
|
||||||
private final Headers headers = new Headers();
|
private final Headers headers = new Headers();
|
||||||
@Valid
|
|
||||||
private final Token token = new Token();
|
private final Token token = new Token();
|
||||||
@Valid
|
|
||||||
private final Client client = new Client();
|
private final Client client = new Client();
|
||||||
@Valid
|
|
||||||
private final OrgRest org = new OrgRest();
|
private final OrgRest org = new OrgRest();
|
||||||
@Valid
|
|
||||||
private final Workflow workflow = new Workflow();
|
private final Workflow workflow = new Workflow();
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@@ -56,27 +48,22 @@ public class IWorkProperties {
|
|||||||
/**
|
/**
|
||||||
* 负责交换公钥和密钥的注册接口路径。
|
* 负责交换公钥和密钥的注册接口路径。
|
||||||
*/
|
*/
|
||||||
@NotBlank(message = "iWork 注册接口路径不能为空")
|
|
||||||
private String register;
|
private String register;
|
||||||
/**
|
/**
|
||||||
* 申请访问令牌的接口路径。
|
* 申请访问令牌的接口路径。
|
||||||
*/
|
*/
|
||||||
@NotBlank(message = "iWork 申请 Token 接口路径不能为空")
|
|
||||||
private String applyToken;
|
private String applyToken;
|
||||||
/**
|
/**
|
||||||
* 查询用户信息的接口路径。
|
* 查询用户信息的接口路径。
|
||||||
*/
|
*/
|
||||||
@NotBlank(message = "iWork 用户信息接口路径不能为空")
|
|
||||||
private String userInfo;
|
private String userInfo;
|
||||||
/**
|
/**
|
||||||
* 发起流程的接口路径。
|
* 发起流程的接口路径。
|
||||||
*/
|
*/
|
||||||
@NotBlank(message = "iWork 发起流程接口路径不能为空")
|
|
||||||
private String createWorkflow;
|
private String createWorkflow;
|
||||||
/**
|
/**
|
||||||
* 干预或作废流程的接口路径。
|
* 干预或作废流程的接口路径。
|
||||||
*/
|
*/
|
||||||
@NotBlank(message = "iWork 作废流程接口路径不能为空")
|
|
||||||
private String voidWorkflow;
|
private String voidWorkflow;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +82,6 @@ public class IWorkProperties {
|
|||||||
/**
|
/**
|
||||||
* 向 iWork 申请的 Token 有效期(单位秒)。
|
* 向 iWork 申请的 Token 有效期(单位秒)。
|
||||||
*/
|
*/
|
||||||
@Min(value = 1, message = "iWork Token 有效期必须大于 0")
|
|
||||||
private long ttlSeconds;
|
private long ttlSeconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,12 +90,10 @@ public class IWorkProperties {
|
|||||||
/**
|
/**
|
||||||
* Reactor Netty 连接超时时间。
|
* Reactor Netty 连接超时时间。
|
||||||
*/
|
*/
|
||||||
@NotNull(message = "iWork 客户端连接超时时间不能为空")
|
|
||||||
private Duration connectTimeout;
|
private Duration connectTimeout;
|
||||||
/**
|
/**
|
||||||
* Reactor Netty 响应超时时间。
|
* Reactor Netty 响应超时时间。
|
||||||
*/
|
*/
|
||||||
@NotNull(message = "iWork 客户端响应超时时间不能为空")
|
|
||||||
private Duration responseTimeout;
|
private Duration responseTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +103,6 @@ public class IWorkProperties {
|
|||||||
* 认证所需的标识(与 iWork 约定)。
|
* 认证所需的标识(与 iWork 约定)。
|
||||||
*/
|
*/
|
||||||
private String tokenSeed;
|
private String tokenSeed;
|
||||||
@Valid
|
|
||||||
private final OrgPaths paths = new OrgPaths();
|
private final OrgPaths paths = new OrgPaths();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,7 +123,69 @@ public class IWorkProperties {
|
|||||||
/**
|
/**
|
||||||
* 用印流程对应的 iWork 模板编号。
|
* 用印流程对应的 iWork 模板编号。
|
||||||
*/
|
*/
|
||||||
@NotBlank(message = "iWork 用印流程模板编号不能为空")
|
|
||||||
private String sealWorkflowId;
|
private String sealWorkflowId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否显式配置了关键参数,用于判断是否需要提示用户。
|
||||||
|
*/
|
||||||
|
public boolean hasAnyConfiguredValue() {
|
||||||
|
return hasText(baseUrl)
|
||||||
|
|| hasText(appId)
|
||||||
|
|| hasText(clientPublicKey)
|
||||||
|
|| hasText(userId)
|
||||||
|
|| hasAnyPathConfigured()
|
||||||
|
|| token.getTtlSeconds() > 0
|
||||||
|
|| client.getConnectTimeout() != null
|
||||||
|
|| client.getResponseTimeout() != null
|
||||||
|
|| hasText(org.getTokenSeed())
|
||||||
|
|| hasText(workflow.getSealWorkflowId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 收集关键配置缺失信息,用于提示或日志告警。
|
||||||
|
*/
|
||||||
|
public List<String> collectCriticalIssues() {
|
||||||
|
List<String> issues = new ArrayList<>();
|
||||||
|
if (!hasText(baseUrl)) {
|
||||||
|
issues.add("iwork.base-url 未配置");
|
||||||
|
}
|
||||||
|
if (!hasText(appId)) {
|
||||||
|
issues.add("iwork.app-id 未配置");
|
||||||
|
}
|
||||||
|
if (!hasText(paths.getRegister())) {
|
||||||
|
issues.add("iwork.paths.register 未配置");
|
||||||
|
}
|
||||||
|
if (!hasText(paths.getApplyToken())) {
|
||||||
|
issues.add("iwork.paths.apply-token 未配置");
|
||||||
|
}
|
||||||
|
if (!hasText(paths.getUserInfo())) {
|
||||||
|
issues.add("iwork.paths.user-info 未配置");
|
||||||
|
}
|
||||||
|
if (!hasText(paths.getCreateWorkflow())) {
|
||||||
|
issues.add("iwork.paths.create-workflow 未配置");
|
||||||
|
}
|
||||||
|
if (!hasText(paths.getVoidWorkflow())) {
|
||||||
|
issues.add("iwork.paths.void-workflow 未配置");
|
||||||
|
}
|
||||||
|
if (token.getTtlSeconds() <= 0) {
|
||||||
|
issues.add("iwork.token.ttl-seconds 需要大于 0");
|
||||||
|
}
|
||||||
|
if (!hasText(workflow.getSealWorkflowId())) {
|
||||||
|
issues.add("iwork.workflow.seal-workflow-id 未配置");
|
||||||
|
}
|
||||||
|
return issues;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasAnyPathConfigured() {
|
||||||
|
return hasText(paths.getRegister())
|
||||||
|
|| hasText(paths.getApplyToken())
|
||||||
|
|| hasText(paths.getUserInfo())
|
||||||
|
|| hasText(paths.getCreateWorkflow())
|
||||||
|
|| hasText(paths.getVoidWorkflow());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasText(String value) {
|
||||||
|
return StringUtils.hasText(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,8 @@ import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkDepa
|
|||||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkHrDepartmentPageRespVO;
|
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkHrDepartmentPageRespVO;
|
||||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkHrJobTitlePageRespVO;
|
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkHrJobTitlePageRespVO;
|
||||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkHrSubcompanyPageRespVO;
|
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkHrSubcompanyPageRespVO;
|
||||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkHrSyncRespVO;
|
|
||||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkHrUserPageRespVO;
|
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkHrUserPageRespVO;
|
||||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkJobTitleQueryReqVO;
|
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkJobTitleQueryReqVO;
|
||||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkOrgSyncReqVO;
|
|
||||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkSubcompanyQueryReqVO;
|
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkSubcompanyQueryReqVO;
|
||||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkUserQueryReqVO;
|
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkUserQueryReqVO;
|
||||||
|
|
||||||
@@ -24,11 +22,4 @@ public interface IWorkOrgRestService {
|
|||||||
|
|
||||||
IWorkHrUserPageRespVO listUsers(IWorkUserQueryReqVO reqVO);
|
IWorkHrUserPageRespVO listUsers(IWorkUserQueryReqVO reqVO);
|
||||||
|
|
||||||
IWorkHrSyncRespVO syncSubcompanies(IWorkOrgSyncReqVO reqVO);
|
|
||||||
|
|
||||||
IWorkHrSyncRespVO syncDepartments(IWorkOrgSyncReqVO reqVO);
|
|
||||||
|
|
||||||
IWorkHrSyncRespVO syncJobTitles(IWorkOrgSyncReqVO reqVO);
|
|
||||||
|
|
||||||
IWorkHrSyncRespVO syncUsers(IWorkOrgSyncReqVO reqVO);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,7 +124,8 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
|
|||||||
|
|
||||||
IWorkSession session = createSession(appId, clientKeyPair, operatorUserId, Boolean.TRUE.equals(reqVO.getForceRefreshToken()));
|
IWorkSession session = createSession(appId, clientKeyPair, operatorUserId, Boolean.TRUE.equals(reqVO.getForceRefreshToken()));
|
||||||
Map<String, Object> payload = buildUserPayload(reqVO);
|
Map<String, Object> payload = buildUserPayload(reqVO);
|
||||||
String responseBody = executeJsonRequest(properties.getPaths().getUserInfo(), reqVO.getQueryParams(), appId, session, payload);
|
String userInfoPath = requireConfiguredPath(properties.getPaths().getUserInfo(), "iwork.paths.user-info");
|
||||||
|
String responseBody = executeJsonRequest(userInfoPath, reqVO.getQueryParams(), appId, session, payload);
|
||||||
|
|
||||||
return buildUserInfoResponse(responseBody);
|
return buildUserInfoResponse(responseBody);
|
||||||
}
|
}
|
||||||
@@ -138,7 +139,8 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
|
|||||||
IWorkSession session = createSession(appId, clientKeyPair, operatorUserId, Boolean.TRUE.equals(reqVO.getForceRefreshToken()));
|
IWorkSession session = createSession(appId, clientKeyPair, operatorUserId, Boolean.TRUE.equals(reqVO.getForceRefreshToken()));
|
||||||
|
|
||||||
Map<String, Object> payload = buildCreatePayload(reqVO);
|
Map<String, Object> payload = buildCreatePayload(reqVO);
|
||||||
String responseBody = executeFormRequest(properties.getPaths().getCreateWorkflow(), null, appId, session, payload);
|
String createWorkflowPath = requireConfiguredPath(properties.getPaths().getCreateWorkflow(), "iwork.paths.create-workflow");
|
||||||
|
String responseBody = executeFormRequest(createWorkflowPath, null, appId, session, payload);
|
||||||
return buildOperationResponse(responseBody);
|
return buildOperationResponse(responseBody);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +156,8 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
|
|||||||
IWorkSession session = createSession(appId, clientKeyPair, operatorUserId, Boolean.TRUE.equals(reqVO.getForceRefreshToken()));
|
IWorkSession session = createSession(appId, clientKeyPair, operatorUserId, Boolean.TRUE.equals(reqVO.getForceRefreshToken()));
|
||||||
|
|
||||||
Map<String, Object> payload = buildVoidPayload(reqVO);
|
Map<String, Object> payload = buildVoidPayload(reqVO);
|
||||||
String responseBody = executeJsonRequest(properties.getPaths().getVoidWorkflow(), null, appId, session, payload);
|
String voidWorkflowPath = requireConfiguredPath(properties.getPaths().getVoidWorkflow(), "iwork.paths.void-workflow");
|
||||||
|
String responseBody = executeJsonRequest(voidWorkflowPath, null, appId, session, payload);
|
||||||
return buildOperationResponse(responseBody);
|
return buildOperationResponse(responseBody);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,6 +296,17 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
|
|||||||
return StringUtils.trimWhitespace(value);
|
return StringUtils.trimWhitespace(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String requireConfiguredPath(String value, String propertyPath) {
|
||||||
|
if (!StringUtils.hasText(value)) {
|
||||||
|
throw ServiceExceptionUtil.exception(IWORK_CONFIGURATION_INVALID, propertyPath + " 未配置");
|
||||||
|
}
|
||||||
|
return StringUtils.trimWhitespace(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private long resolveTokenTtlSeconds() {
|
||||||
|
return Math.max(1L, properties.getToken().getTtlSeconds());
|
||||||
|
}
|
||||||
|
|
||||||
private ClientKeyPair resolveClientKeyPair(String appId, boolean forceRefresh) {
|
private ClientKeyPair resolveClientKeyPair(String appId, boolean forceRefresh) {
|
||||||
String configured = properties.getClientPublicKey();
|
String configured = properties.getClientPublicKey();
|
||||||
if (StringUtils.hasText(configured)) {
|
if (StringUtils.hasText(configured)) {
|
||||||
@@ -333,7 +347,8 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
|
|||||||
String encryptedSecret = encryptWithPublicKey(registration.secret(), registration.spk());
|
String encryptedSecret = encryptWithPublicKey(registration.secret(), registration.spk());
|
||||||
String encryptedUserId = encryptWithPublicKey(operatorUserId, registration.spk());
|
String encryptedUserId = encryptWithPublicKey(operatorUserId, registration.spk());
|
||||||
String token = applyToken(appId, encryptedSecret);
|
String token = applyToken(appId, encryptedSecret);
|
||||||
Instant expiresAt = Instant.now().plusSeconds(Math.max(1L, properties.getToken().getTtlSeconds()));
|
long ttlSeconds = resolveTokenTtlSeconds();
|
||||||
|
Instant expiresAt = Instant.now().plusSeconds(ttlSeconds);
|
||||||
return new IWorkSession(token, encryptedUserId, expiresAt, registration.spk());
|
return new IWorkSession(token, encryptedUserId, expiresAt, registration.spk());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,8 +374,9 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private RegistrationState register(String appId, ClientKeyPair clientKeyPair) {
|
private RegistrationState register(String appId, ClientKeyPair clientKeyPair) {
|
||||||
|
String registerPath = requireConfiguredPath(properties.getPaths().getRegister(), "iwork.paths.register");
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(resolveUrl(properties.getPaths().getRegister()))
|
.url(resolveUrl(registerPath))
|
||||||
.header(properties.getHeaders().getAppId(), appId)
|
.header(properties.getHeaders().getAppId(), appId)
|
||||||
.header(properties.getHeaders().getClientPublicKey(), clientKeyPair.publicKey())
|
.header(properties.getHeaders().getClientPublicKey(), clientKeyPair.publicKey())
|
||||||
.post(RequestBody.create(null, new byte[0]))
|
.post(RequestBody.create(null, new byte[0]))
|
||||||
@@ -376,11 +392,13 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String applyToken(String appId, String encryptedSecret) {
|
private String applyToken(String appId, String encryptedSecret) {
|
||||||
|
String applyTokenPath = requireConfiguredPath(properties.getPaths().getApplyToken(), "iwork.paths.apply-token");
|
||||||
|
long ttlSeconds = resolveTokenTtlSeconds();
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(resolveUrl(properties.getPaths().getApplyToken()))
|
.url(resolveUrl(applyTokenPath))
|
||||||
.header(properties.getHeaders().getAppId(), appId)
|
.header(properties.getHeaders().getAppId(), appId)
|
||||||
.header(properties.getHeaders().getSecret(), encryptedSecret)
|
.header(properties.getHeaders().getSecret(), encryptedSecret)
|
||||||
.header(properties.getHeaders().getTime(), String.valueOf(properties.getToken().getTtlSeconds()))
|
.header(properties.getHeaders().getTime(), String.valueOf(ttlSeconds))
|
||||||
.post(RequestBody.create(null, new byte[0]))
|
.post(RequestBody.create(null, new byte[0]))
|
||||||
.build();
|
.build();
|
||||||
String responseBody = executeRequest(request, IWORK_APPLY_TOKEN_FAILED);
|
String responseBody = executeRequest(request, IWORK_APPLY_TOKEN_FAILED);
|
||||||
|
|||||||
@@ -9,11 +9,9 @@ import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkDepa
|
|||||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkHrDepartmentPageRespVO;
|
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkHrDepartmentPageRespVO;
|
||||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkHrJobTitlePageRespVO;
|
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkHrJobTitlePageRespVO;
|
||||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkHrSubcompanyPageRespVO;
|
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkHrSubcompanyPageRespVO;
|
||||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkHrSyncRespVO;
|
|
||||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkHrUserPageRespVO;
|
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkHrUserPageRespVO;
|
||||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkJobTitleQueryReqVO;
|
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkJobTitleQueryReqVO;
|
||||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkOrgBaseQueryReqVO;
|
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkOrgBaseQueryReqVO;
|
||||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkOrgSyncReqVO;
|
|
||||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkSubcompanyQueryReqVO;
|
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkSubcompanyQueryReqVO;
|
||||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkUserQueryReqVO;
|
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkUserQueryReqVO;
|
||||||
import com.zt.plat.module.system.framework.integration.iwork.config.IWorkProperties;
|
import com.zt.plat.module.system.framework.integration.iwork.config.IWorkProperties;
|
||||||
@@ -62,9 +60,6 @@ public class IWorkOrgRestServiceImpl implements IWorkOrgRestService {
|
|||||||
private static final TypeReference<List<IWorkHrUserPageRespVO.User>> USER_LIST_TYPE =
|
private static final TypeReference<List<IWorkHrUserPageRespVO.User>> USER_LIST_TYPE =
|
||||||
new TypeReference<>() {
|
new TypeReference<>() {
|
||||||
};
|
};
|
||||||
private static final TypeReference<List<IWorkHrSyncRespVO.SyncResult>> SYNC_RESULT_LIST_TYPE =
|
|
||||||
new TypeReference<>() {
|
|
||||||
};
|
|
||||||
private static final okhttp3.MediaType JSON_MEDIA_TYPE = okhttp3.MediaType.get("application/json; charset=UTF-8");
|
private static final okhttp3.MediaType JSON_MEDIA_TYPE = okhttp3.MediaType.get("application/json; charset=UTF-8");
|
||||||
|
|
||||||
private final IWorkProperties properties;
|
private final IWorkProperties properties;
|
||||||
@@ -178,34 +173,6 @@ public class IWorkOrgRestServiceImpl implements IWorkOrgRestService {
|
|||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public IWorkHrSyncRespVO syncSubcompanies(IWorkOrgSyncReqVO reqVO) {
|
|
||||||
String path = orgPaths().getSyncSubcompany();
|
|
||||||
JsonNode node = invokeDataEndpoint(path, reqVO.getData());
|
|
||||||
return buildSyncResp(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IWorkHrSyncRespVO syncDepartments(IWorkOrgSyncReqVO reqVO) {
|
|
||||||
String path = orgPaths().getSyncDepartment();
|
|
||||||
JsonNode node = invokeDataEndpoint(path, reqVO.getData());
|
|
||||||
return buildSyncResp(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IWorkHrSyncRespVO syncJobTitles(IWorkOrgSyncReqVO reqVO) {
|
|
||||||
String path = orgPaths().getSyncJobTitle();
|
|
||||||
JsonNode node = invokeDataEndpoint(path, reqVO.getData());
|
|
||||||
return buildSyncResp(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IWorkHrSyncRespVO syncUsers(IWorkOrgSyncReqVO reqVO) {
|
|
||||||
String path = orgPaths().getSyncUser();
|
|
||||||
JsonNode node = invokeDataEndpoint(path, reqVO.getData());
|
|
||||||
return buildSyncResp(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
private JsonNode invokeParamsEndpoint(String path, Map<String, Object> params) {
|
private JsonNode invokeParamsEndpoint(String path, Map<String, Object> params) {
|
||||||
Objects.requireNonNull(params, "查询参数不能为空");
|
Objects.requireNonNull(params, "查询参数不能为空");
|
||||||
Map<String, Object> payload = new HashMap<>();
|
Map<String, Object> payload = new HashMap<>();
|
||||||
@@ -213,13 +180,6 @@ public class IWorkOrgRestServiceImpl implements IWorkOrgRestService {
|
|||||||
return executeJson(path, payload);
|
return executeJson(path, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
private JsonNode invokeDataEndpoint(String path, Object data) {
|
|
||||||
Objects.requireNonNull(data, "同步数据不能为空");
|
|
||||||
Map<String, Object> payload = new HashMap<>();
|
|
||||||
payload.put("data", data);
|
|
||||||
return executeJson(path, payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
private JsonNode executeJson(String path, Map<String, Object> payload) {
|
private JsonNode executeJson(String path, Map<String, Object> payload) {
|
||||||
// 统一封装请求体并发送 POST 调用
|
// 统一封装请求体并发送 POST 调用
|
||||||
assertOrgConfigured(path);
|
assertOrgConfigured(path);
|
||||||
@@ -369,17 +329,6 @@ public class IWorkOrgRestServiceImpl implements IWorkOrgRestService {
|
|||||||
return respVO;
|
return respVO;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析并封装同步结果
|
|
||||||
private IWorkHrSyncRespVO buildSyncResp(JsonNode node) {
|
|
||||||
ParsedEnvelope envelope = parseEnvelope(node);
|
|
||||||
IWorkHrSyncRespVO respVO = new IWorkHrSyncRespVO();
|
|
||||||
respVO.setCode(envelope.code());
|
|
||||||
respVO.setMessage(envelope.message());
|
|
||||||
respVO.setSuccess(envelope.success());
|
|
||||||
respVO.setResult(readList(envelope.root(), "result", SYNC_RESULT_LIST_TYPE));
|
|
||||||
return respVO;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JsonNode parseJson(String body) {
|
private JsonNode parseJson(String body) {
|
||||||
try {
|
try {
|
||||||
return objectMapper.readTree(body);
|
return objectMapper.readTree(body);
|
||||||
|
|||||||
Reference in New Issue
Block a user