Merge remote-tracking branch 'base-version/main' into dev

This commit is contained in:
chenbowen
2025-11-26 20:12:46 +08:00
5 changed files with 78 additions and 349 deletions

View File

@@ -1,228 +0,0 @@
package com.zt.plat.module.system.service.integration.iwork.impl;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkDetailRecordVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkDetailTableVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkFormFieldVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkOperationRespVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkUserInfoReqVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkUserInfoRespVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkWorkflowCreateReqVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkWorkflowVoidReqVO;
import com.zt.plat.module.system.framework.integration.iwork.config.IWorkProperties;
import com.zt.plat.module.system.service.integration.iwork.IWorkIntegrationService;
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.web.reactive.function.client.WebClient;
import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.time.Duration;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
class IWorkIntegrationServiceImplTest {
private static KeyPair serverKeyPair;
private static String serverPublicKeyBase64;
private static String clientPublicKeyBase64;
private MockWebServer mockWebServer;
private IWorkIntegrationService integrationService;
private IWorkProperties properties;
@BeforeAll
static void initKeys() throws Exception {
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(1024);
serverKeyPair = generator.generateKeyPair();
serverPublicKeyBase64 = Base64.getEncoder().encodeToString(serverKeyPair.getPublic().getEncoded());
KeyPair clientKeyPair = generator.generateKeyPair();
clientPublicKeyBase64 = Base64.getEncoder().encodeToString(clientKeyPair.getPublic().getEncoded());
}
@BeforeEach
void setUp() throws Exception {
mockWebServer = new MockWebServer();
mockWebServer.start();
properties = buildProperties();
WebClient.Builder builder = WebClient.builder();
ObjectMapper objectMapper = new ObjectMapper();
integrationService = new IWorkIntegrationServiceImpl(properties, objectMapper, builder);
}
@AfterEach
void tearDown() throws Exception {
mockWebServer.shutdown();
}
@Test
void testWorkflowLifecycle() throws Exception {
enqueueRegisterResponse();
enqueueApplyTokenResponse();
enqueueJsonResponse("{\"code\":1,\"userid\":\"1001\",\"msg\":\"OK\"}");
enqueueJsonResponse("{\"code\":\"1\",\"requestid\":\"REQ-001\",\"msg\":\"created\"}");
enqueueJsonResponse("{\"code\":\"1\",\"msg\":\"voided\"}");
IWorkUserInfoReqVO userReq = new IWorkUserInfoReqVO();
userReq.setIdentifierKey("loginid");
userReq.setIdentifierValue("zhangsan");
IWorkUserInfoRespVO userResp = integrationService.resolveUserId(userReq);
assertThat(userResp.isSuccess()).isTrue();
assertThat(userResp.getUserId()).isEqualTo("1001");
IWorkWorkflowCreateReqVO createReq = buildCreateRequest();
IWorkOperationRespVO createResp = integrationService.createWorkflow(createReq);
assertThat(createResp.isSuccess()).isTrue();
assertThat(createResp.getPayload().get("requestid")).isEqualTo("REQ-001");
IWorkWorkflowVoidReqVO voidReq = new IWorkWorkflowVoidReqVO();
voidReq.setRequestId("REQ-001");
voidReq.setReason("testing void");
IWorkOperationRespVO voidResp = integrationService.voidWorkflow(voidReq);
assertThat(voidResp.isSuccess()).isTrue();
verifyRegisterRequest(mockWebServer.takeRequest());
verifyApplyTokenRequest(mockWebServer.takeRequest());
verifyUserInfoRequest(mockWebServer.takeRequest());
verifyCreateRequest(mockWebServer.takeRequest());
verifyVoidRequest(mockWebServer.takeRequest());
assertThat(mockWebServer.getRequestCount()).isEqualTo(5);
}
private IWorkProperties buildProperties() {
IWorkProperties properties = new IWorkProperties();
properties.setEnabled(true);
properties.setBaseUrl(mockWebServer.url("/").toString());
properties.setAppId("test-app");
properties.setClientPublicKey(clientPublicKeyBase64);
properties.setUserId("1");
properties.setWorkflowId(54L);
properties.getToken().setTtlSeconds(3600L);
properties.getToken().setRefreshAheadSeconds(30L);
properties.getClient().setResponseTimeout(Duration.ofSeconds(5));
properties.getPaths().setRegister("/api/ec/dev/auth/regist");
properties.getPaths().setApplyToken("/api/ec/dev/auth/applytoken");
properties.getPaths().setUserInfo("/api/workflow/paService/getUserInfo");
properties.getPaths().setCreateWorkflow("/api/workflow/paService/doCreateRequest");
properties.getPaths().setVoidWorkflow("/api/workflow/paService/doCancelRequest");
properties.getClient().setConnectTimeout(Duration.ofSeconds(5));
return properties;
}
private void verifyRegisterRequest(RecordedRequest request) {
assertThat(request.getPath()).isEqualTo("/api/ec/dev/auth/regist");
assertThat(request.getHeader(properties.getHeaders().getAppId())).isEqualTo("test-app");
assertThat(request.getHeader(properties.getHeaders().getClientPublicKey())).isEqualTo(clientPublicKeyBase64);
}
private void verifyApplyTokenRequest(RecordedRequest request) throws Exception {
assertThat(request.getPath()).isEqualTo("/api/ec/dev/auth/applytoken");
assertThat(request.getHeader(properties.getHeaders().getAppId())).isEqualTo("test-app");
assertThat(request.getHeader(properties.getHeaders().getTime())).isEqualTo("3600");
String decryptedSecret = decryptHeader(request.getHeader(properties.getHeaders().getSecret()));
assertThat(decryptedSecret).isEqualTo("plain-secret");
}
private void verifyUserInfoRequest(RecordedRequest request) throws Exception {
assertThat(request.getPath()).isEqualTo("/api/workflow/paService/getUserInfo");
assertThat(request.getHeader(properties.getHeaders().getToken())).isEqualTo("token-123");
String decryptedUserId = decryptHeader(request.getHeader(properties.getHeaders().getUserId()));
assertThat(decryptedUserId).isEqualTo("1");
String body = request.getBody().readUtf8();
assertThat(body).contains("loginid");
assertThat(body).contains("zhangsan");
}
private void verifyCreateRequest(RecordedRequest request) throws Exception {
assertThat(request.getPath()).isEqualTo("/api/workflow/paService/doCreateRequest");
assertThat(request.getHeader(properties.getHeaders().getToken())).isEqualTo("token-123");
String decryptedUserId = decryptHeader(request.getHeader(properties.getHeaders().getUserId()));
assertThat(decryptedUserId).isEqualTo("1");
String body = request.getBody().readUtf8();
assertThat(body).contains("requestName=测试流程");
assertThat(body).contains("workflowId=54");
assertThat(body).contains("mainData=%5B");
}
private void verifyVoidRequest(RecordedRequest request) throws Exception {
assertThat(request.getPath()).isEqualTo("/api/workflow/paService/doCancelRequest");
assertThat(request.getHeader(properties.getHeaders().getToken())).isEqualTo("token-123");
String decryptedUserId = decryptHeader(request.getHeader(properties.getHeaders().getUserId()));
assertThat(decryptedUserId).isEqualTo("1");
String body = request.getBody().readUtf8();
assertThat(body).contains("requestId=REQ-001");
assertThat(body).contains("remark=testing+void");
}
private void enqueueRegisterResponse() {
enqueueJsonResponse("{" +
"\"secret\":\"plain-secret\"," +
"\"spk\":\"" + serverPublicKeyBase64 + "\"}");
}
private void enqueueApplyTokenResponse() {
enqueueJsonResponse("{\"token\":\"token-123\",\"expire\":3600}");
}
private void enqueueJsonResponse(String body) {
mockWebServer.enqueue(new MockResponse()
.setHeader("Content-Type", "application/json")
.setBody(body));
}
private IWorkWorkflowCreateReqVO buildCreateRequest() {
IWorkFormFieldVO field1 = new IWorkFormFieldVO();
field1.setFieldName("sqr");
field1.setFieldValue("张三");
IWorkFormFieldVO field2 = new IWorkFormFieldVO();
field2.setFieldName("sqrq");
field2.setFieldValue("2023-11-02");
IWorkDetailRecordVO detailRecord = new IWorkDetailRecordVO();
detailRecord.setRecordOrder(0);
IWorkFormFieldVO detailField = new IWorkFormFieldVO();
detailField.setFieldName("ddh");
detailField.setFieldValue("100010");
detailRecord.setFields(List.of(detailField));
IWorkDetailTableVO detailTable = new IWorkDetailTableVO();
detailTable.setTableDBName("formtable_main_26_dt1");
detailTable.setRecords(List.of(detailRecord));
IWorkWorkflowCreateReqVO req = new IWorkWorkflowCreateReqVO();
req.setRequestName("测试流程");
req.setMainFields(List.of(field1, field2));
req.setDetailTables(List.of(detailTable));
req.setOtherParams(Map.of("isnextflow", "0"));
return req;
}
private String decryptHeader(String headerValue) throws Exception {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, serverKeyPair.getPrivate());
byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(headerValue));
return new String(decrypted, StandardCharsets.UTF_8);
}
}

View File

@@ -1,121 +0,0 @@
package com.zt.plat.module.system.service.integration.iwork.impl;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
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.IWorkOrgSyncReqVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkSubcompanyQueryReqVO;
import com.zt.plat.module.system.framework.integration.iwork.config.IWorkProperties;
import com.zt.plat.module.system.service.integration.iwork.IWorkOrgRestService;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.util.DigestUtils;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
import java.time.ZoneOffset;
import java.util.List;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
class IWorkOrgRestServiceImplTest {
private MockWebServer mockWebServer;
private IWorkOrgRestService service;
private IWorkProperties properties;
private Clock fixedClock;
private ObjectMapper objectMapper;
@BeforeEach
void setUp() throws Exception {
mockWebServer = new MockWebServer();
mockWebServer.start();
properties = buildProperties();
fixedClock = Clock.fixed(Instant.ofEpochMilli(1_672_531_200_000L), ZoneOffset.UTC);
objectMapper = new ObjectMapper();
service = new IWorkOrgRestServiceImpl(properties, objectMapper, fixedClock);
}
@AfterEach
void tearDown() throws Exception {
mockWebServer.shutdown();
}
@Test
void shouldListSubcompanies() throws Exception {
mockWebServer.enqueue(jsonResponse("{\"code\":\"1\",\"data\":{\"totalSize\":1,\"totalPage\":1,\"pageSize\":10,\"pageNumber\":1,\"dataList\":[{\"subcompanyid1\":4,\"subcompanyname\":\"总部\"}]}}"));
IWorkSubcompanyQueryReqVO reqVO = new IWorkSubcompanyQueryReqVO();
reqVO.setParams(Map.of("curpage", 1));
IWorkHrSubcompanyPageRespVO respVO = service.listSubcompanies(reqVO);
assertThat(respVO.isSuccess()).isTrue();
assertThat(respVO.getTotalSize()).isEqualTo(1);
assertThat(respVO.getDataList()).hasSize(1);
assertThat(respVO.getDataList().get(0).getSubcompanyname()).isEqualTo("总部");
RecordedRequest request = mockWebServer.takeRequest();
assertThat(request.getPath()).isEqualTo(properties.getOrg().getPaths().getSubcompanyPage());
String decoded = URLDecoder.decode(request.getBody().readUtf8(), StandardCharsets.UTF_8);
JsonNode bodyNode = objectMapper.readTree(decoded);
assertThat(bodyNode.path("params").path("curpage").asInt()).isEqualTo(1);
JsonNode tokenNode = bodyNode.path("token");
assertThat(tokenNode.path("ts").asText()).isEqualTo("1672531200000");
String expectedKey = DigestUtils.md5DigestAsHex("test-seed1672531200000".getBytes(StandardCharsets.UTF_8)).toUpperCase();
assertThat(tokenNode.path("key").asText()).isEqualTo(expectedKey);
}
@Test
void shouldSyncDepartments() throws Exception {
mockWebServer.enqueue(jsonResponse("{\"code\":\"1\",\"result\":[{\"@action\":\"add\",\"code\":\"demo\",\"result\":\"success\"}]}"));
IWorkOrgSyncReqVO reqVO = new IWorkOrgSyncReqVO();
reqVO.setData(List.of(Map.of("@action", "add", "code", "demo")));
IWorkHrSyncRespVO respVO = service.syncDepartments(reqVO);
assertThat(respVO.isSuccess()).isTrue();
assertThat(respVO.getResult()).hasSize(1);
assertThat(respVO.getResult().get(0).getCode()).isEqualTo("demo");
RecordedRequest request = mockWebServer.takeRequest();
assertThat(request.getPath()).isEqualTo(properties.getOrg().getPaths().getSyncDepartment());
String decoded = URLDecoder.decode(request.getBody().readUtf8(), StandardCharsets.UTF_8);
JsonNode bodyNode = objectMapper.readTree(decoded);
assertThat(bodyNode.path("data").isArray()).isTrue();
assertThat(bodyNode.path("data").get(0).path("code").asText()).isEqualTo("demo");
}
private MockResponse jsonResponse(String body) {
return new MockResponse()
.setHeader("Content-Type", "application/json")
.setBody(body);
}
private IWorkProperties buildProperties() {
IWorkProperties properties = new IWorkProperties();
properties.setBaseUrl(mockWebServer.url("/").toString());
properties.getClient().setConnectTimeout(Duration.ofSeconds(5));
properties.getClient().setResponseTimeout(Duration.ofSeconds(5));
properties.getOrg().setTokenSeed("test-seed");
IWorkProperties.OrgPaths paths = properties.getOrg().getPaths();
paths.setSubcompanyPage("/api/hrm/resful/getHrmsubcompanyWithPage");
paths.setDepartmentPage("/api/hrm/resful/getHrmdepartmentWithPage");
paths.setJobTitlePage("/api/hrm/resful/getJobtitleInfoWithPage");
paths.setUserPage("/api/hrm/resful/getHrmUserInfoWithPage");
paths.setSyncSubcompany("/api/hrm/resful/synSubcompany");
paths.setSyncDepartment("/api/hrm/resful/synDepartment");
paths.setSyncJobTitle("/api/hrm/resful/synJobtitle");
paths.setSyncUser("/api/hrm/resful/synHrmresource");
return properties;
}
}