1. iwork 统一用印发起接口
This commit is contained in:
@@ -14,9 +14,6 @@ public class IWorkOperationRespVO {
|
||||
@Schema(description = "iWork 返回的原始数据")
|
||||
private Map<String, Object> payload;
|
||||
|
||||
@Schema(description = "iWork 返回的原始字符串")
|
||||
private String rawBody;
|
||||
|
||||
@Schema(description = "是否判断为成功")
|
||||
private boolean success;
|
||||
|
||||
|
||||
@@ -14,9 +14,6 @@ public class IWorkUserInfoRespVO {
|
||||
@Schema(description = "iWork 返回的原始数据")
|
||||
private Map<String, Object> payload;
|
||||
|
||||
@Schema(description = "iWork 返回的原始字符串")
|
||||
private String rawBody;
|
||||
|
||||
@Schema(description = "是否判断为成功")
|
||||
private boolean success;
|
||||
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
package com.zt.plat.module.system.controller.admin.integration.iwork.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 发起 iWork 流程的请求体。
|
||||
*/
|
||||
@@ -17,25 +11,36 @@ import java.util.Map;
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class IWorkWorkflowCreateReqVO extends IWorkBaseReqVO {
|
||||
|
||||
@Schema(description = "流程标题", example = "测试流程")
|
||||
@NotBlank(message = "流程标题不能为空")
|
||||
private String requestName;
|
||||
@Schema(description = "用印申请人(iWork 人员 ID)", example = "1001")
|
||||
private String jbr;
|
||||
|
||||
@Schema(description = "流程模板编号,可为空使用默认配置", example = "54")
|
||||
private Long workflowId;
|
||||
@Schema(description = "用印部门 ID", example = "2001")
|
||||
private String yybm;
|
||||
|
||||
@Schema(description = "主表字段")
|
||||
@NotEmpty(message = "主表字段不能为空")
|
||||
@Valid
|
||||
private List<IWorkFormFieldVO> mainFields;
|
||||
@Schema(description = "用印单位(分部 ID)", example = "3001")
|
||||
private String fb;
|
||||
|
||||
@Schema(description = "明细表数据")
|
||||
@Valid
|
||||
private List<IWorkDetailTableVO> detailTables;
|
||||
@Schema(description = "申请时间,格式 yyyy-MM-dd", example = "2025-01-01")
|
||||
private String sqsj;
|
||||
|
||||
@Schema(description = "额外参数")
|
||||
private Map<String, Object> otherParams;
|
||||
@Schema(description = "用印去向")
|
||||
private String yyqx;
|
||||
|
||||
@Schema(description = "额外 Form 数据")
|
||||
private Map<String, String> formExtras;
|
||||
@Schema(description = "用印依据附件 URL")
|
||||
private String yyfkUrl;
|
||||
|
||||
@Schema(description = "用印事由或内容摘要")
|
||||
private String yysy;
|
||||
|
||||
@Schema(description = "用印材料附件 URL(必填)")
|
||||
private String xyywjUrl;
|
||||
|
||||
@Schema(description = "用印事项")
|
||||
private String yysx;
|
||||
|
||||
@Schema(description = "业务系统单据编号(用于派生流程标题)", example = "DJ-2025-0001")
|
||||
private String ywxtdjbh;
|
||||
|
||||
@Schema(description = "流程模板编号(必填)", example = "54")
|
||||
private String workflowId;
|
||||
}
|
||||
|
||||
@@ -18,4 +18,5 @@ public interface IWorkIntegrationErrorCodeConstants {
|
||||
ErrorCode IWORK_WORKFLOW_ID_MISSING = new ErrorCode(1_010_200_008, "缺少 iWork 流程模板编号");
|
||||
ErrorCode IWORK_ORG_IDENTIFIER_MISSING = new ErrorCode(1_010_200_009, "iWork 人力组织接口缺少认证标识");
|
||||
ErrorCode IWORK_ORG_REMOTE_FAILED = new ErrorCode(1_010_200_010, "iWork 人力组织接口请求失败{}");
|
||||
ErrorCode IWORK_SEAL_REQUIRED_FIELD_MISSING = new ErrorCode(1_010_200_011, "缺少用印必填字段:{}");
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
|
||||
IWorkSession session = ensureSession(appId, clientKeyPair, operatorUserId, Boolean.TRUE.equals(reqVO.getForceRefreshToken()));
|
||||
|
||||
Map<String, Object> payload = buildCreatePayload(reqVO);
|
||||
String responseBody = executeJsonRequest(properties.getPaths().getCreateWorkflow(), null, appId, session, payload);
|
||||
String responseBody = executeFormRequest(properties.getPaths().getCreateWorkflow(), null, appId, session, payload);
|
||||
return buildOperationResponse(responseBody);
|
||||
}
|
||||
|
||||
@@ -324,6 +324,39 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
|
||||
return executeRequest(request, IWORK_REMOTE_REQUEST_FAILED);
|
||||
}
|
||||
|
||||
private String executeFormRequest(String path,
|
||||
Map<String, Object> queryParams,
|
||||
String appId,
|
||||
IWorkSession session,
|
||||
Map<String, Object> formFields) {
|
||||
HttpUrl baseUrl = HttpUrl.parse(resolveUrl(path));
|
||||
if (baseUrl == null) {
|
||||
throw ServiceExceptionUtil.exception(IWORK_REMOTE_REQUEST_FAILED, "非法的 URL");
|
||||
}
|
||||
HttpUrl.Builder urlBuilder = baseUrl.newBuilder();
|
||||
if (queryParams != null) {
|
||||
queryParams.forEach((key, value) -> {
|
||||
if (value != null) {
|
||||
urlBuilder.addQueryParameter(key, String.valueOf(value));
|
||||
}
|
||||
});
|
||||
}
|
||||
FormBody.Builder bodyBuilder = new FormBody.Builder();
|
||||
if (formFields != null) {
|
||||
formFields.forEach((key, value) -> {
|
||||
if (StringUtils.hasText(key) && value != null) {
|
||||
bodyBuilder.add(key, toFormValue(value));
|
||||
}
|
||||
});
|
||||
}
|
||||
Request request = new Request.Builder()
|
||||
.url(urlBuilder.build())
|
||||
.headers(authHeaders(appId, session).build())
|
||||
.post(bodyBuilder.build())
|
||||
.build();
|
||||
return executeRequest(request, IWORK_REMOTE_REQUEST_FAILED);
|
||||
}
|
||||
|
||||
private Headers.Builder authHeaders(String appId, IWorkSession session) {
|
||||
return new Headers.Builder()
|
||||
.set(properties.getHeaders().getAppId(), appId)
|
||||
@@ -331,6 +364,19 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
|
||||
.set(properties.getHeaders().getUserId(), session.getEncryptedUserId());
|
||||
}
|
||||
|
||||
private String toFormValue(Object value) {
|
||||
if (value == null) {
|
||||
return "";
|
||||
}
|
||||
if (value instanceof CharSequence || value instanceof Number || value instanceof Boolean) {
|
||||
return String.valueOf(value);
|
||||
}
|
||||
if (value.getClass().isArray() || value instanceof Collection<?> || value instanceof Map<?, ?>) {
|
||||
return toJsonString(value);
|
||||
}
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
private Map<String, Object> buildUserPayload(IWorkUserInfoReqVO reqVO) {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
if (reqVO.getPayload() != null) {
|
||||
@@ -342,27 +388,81 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
|
||||
|
||||
private Map<String, Object> buildCreatePayload(IWorkWorkflowCreateReqVO reqVO) {
|
||||
Map<String, Object> payload = new LinkedHashMap<>();
|
||||
payload.put("requestName", reqVO.getRequestName());
|
||||
payload.put("workflowId", resolveWorkflowId(reqVO.getWorkflowId()));
|
||||
payload.put("mainData", convertFormFields(reqVO.getMainFields()));
|
||||
if (reqVO.getDetailTables() != null && !reqVO.getDetailTables().isEmpty()) {
|
||||
payload.put("detailData", convertDetailTables(reqVO.getDetailTables()));
|
||||
}
|
||||
if (reqVO.getOtherParams() != null && !reqVO.getOtherParams().isEmpty()) {
|
||||
payload.put("otherParams", reqVO.getOtherParams());
|
||||
}
|
||||
appendPayloadExtras(payload, reqVO.getFormExtras());
|
||||
SealRequestFields fields = resolveSealFields(reqVO);
|
||||
payload.put("requestName", buildRequestName(fields.ywxtdjbh()));
|
||||
payload.put("workflowId", parseWorkflowId(fields.workflowId()));
|
||||
payload.put("mainData", buildSealMainData(fields));
|
||||
return payload;
|
||||
}
|
||||
|
||||
private long resolveWorkflowId(Long requestWorkflowId) {
|
||||
if (requestWorkflowId != null) {
|
||||
return requestWorkflowId;
|
||||
private String buildRequestName(String billNo) {
|
||||
return "用印-" + billNo;
|
||||
}
|
||||
|
||||
private long parseWorkflowId(String workflowId) {
|
||||
try {
|
||||
return Long.parseLong(workflowId);
|
||||
} catch (NumberFormatException ex) {
|
||||
throw ServiceExceptionUtil.exception(IWORK_SEAL_REQUIRED_FIELD_MISSING, "workflowId");
|
||||
}
|
||||
if (properties.getWorkflowId() != null) {
|
||||
return properties.getWorkflowId();
|
||||
}
|
||||
|
||||
private List<Map<String, Object>> buildSealMainData(SealRequestFields fields) {
|
||||
List<Map<String, Object>> main = new ArrayList<>();
|
||||
addField(main, "jbr", fields.jbr());
|
||||
addField(main, "yybm", fields.yybm());
|
||||
addField(main, "fb", fields.fb());
|
||||
addField(main, "sqsj", fields.sqsj());
|
||||
addField(main, "yyqx", fields.yyqx());
|
||||
addField(main, "yyfk", fields.yyfkUrl());
|
||||
addField(main, "yysy", fields.yysy());
|
||||
addField(main, "xyywj", fields.xyywjUrl());
|
||||
addField(main, "yysx", fields.yysx());
|
||||
addField(main, "lclx", SealRequestFields.DEFAULT_FLOW_TYPE);
|
||||
addField(main, "qsdz", SealRequestFields.DEFAULT_SIGN_ACTION);
|
||||
addField(main, "ywxtdjbh", fields.ywxtdjbh());
|
||||
return main;
|
||||
}
|
||||
|
||||
private void addField(List<Map<String, Object>> target, String name, String value) {
|
||||
if (!StringUtils.hasText(value)) {
|
||||
return;
|
||||
}
|
||||
throw ServiceExceptionUtil.exception(IWORK_WORKFLOW_ID_MISSING);
|
||||
Map<String, Object> map = new HashMap<>(2);
|
||||
map.put("fieldName", name);
|
||||
map.put("fieldValue", value);
|
||||
target.add(map);
|
||||
}
|
||||
|
||||
private SealRequestFields resolveSealFields(IWorkWorkflowCreateReqVO reqVO) {
|
||||
String jbr = requireSealField(reqVO.getJbr(), "jbr");
|
||||
String yybm = requireSealField(reqVO.getYybm(), "yybm");
|
||||
String fb = requireSealField(reqVO.getFb(), "fb");
|
||||
String sqsj = requireSealField(reqVO.getSqsj(), "sqsj");
|
||||
String yyqx = requireSealField(reqVO.getYyqx(), "yyqx");
|
||||
String xyywjUrl = requireSealField(reqVO.getXyywjUrl(), "xyywjUrl");
|
||||
String yysx = requireSealField(reqVO.getYysx(), "yysx");
|
||||
String billNo = requireSealField(reqVO.getYwxtdjbh(), "ywxtdjbh");
|
||||
String workflowId = requireSealField(reqVO.getWorkflowId(), "workflowId");
|
||||
String yyfkUrl = trimToNull(reqVO.getYyfkUrl());
|
||||
String yysy = trimToNull(reqVO.getYysy());
|
||||
return new SealRequestFields(jbr, yybm, fb, sqsj, yyqx, yyfkUrl, yysy, xyywjUrl, yysx, billNo, workflowId);
|
||||
}
|
||||
|
||||
private String requireSealField(String value, String fieldName) {
|
||||
String trimmed = trimToNull(value);
|
||||
if (trimmed == null) {
|
||||
throw ServiceExceptionUtil.exception(IWORK_SEAL_REQUIRED_FIELD_MISSING, fieldName);
|
||||
}
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
private String trimToNull(String value) {
|
||||
if (!StringUtils.hasText(value)) {
|
||||
return null;
|
||||
}
|
||||
String trimmed = value.trim();
|
||||
return trimmed.isEmpty() ? null : trimmed;
|
||||
}
|
||||
|
||||
private Map<String, Object> buildVoidPayload(IWorkWorkflowVoidReqVO reqVO) {
|
||||
@@ -389,35 +489,8 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
|
||||
});
|
||||
}
|
||||
|
||||
private List<Map<String, Object>> convertFormFields(List<IWorkFormFieldVO> fields) {
|
||||
return fields.stream().map(field -> {
|
||||
Map<String, Object> map = new HashMap<>(2);
|
||||
map.put("fieldName", field.getFieldName());
|
||||
map.put("fieldValue", field.getFieldValue());
|
||||
return map;
|
||||
}).toList();
|
||||
}
|
||||
|
||||
private List<Map<String, Object>> convertDetailTables(List<IWorkDetailTableVO> tables) {
|
||||
return tables.stream().map(table -> {
|
||||
Map<String, Object> tableMap = new HashMap<>(2);
|
||||
tableMap.put("tableDBName", table.getTableDBName());
|
||||
List<Map<String, Object>> records = table.getRecords().stream().map(record -> {
|
||||
Map<String, Object> recordMap = new HashMap<>(2);
|
||||
if (record.getRecordOrder() != null) {
|
||||
recordMap.put("recordOrder", record.getRecordOrder());
|
||||
}
|
||||
recordMap.put("workflowRequestTableFields", convertFormFields(record.getFields()));
|
||||
return recordMap;
|
||||
}).toList();
|
||||
tableMap.put("workflowRequestTableRecords", records);
|
||||
return tableMap;
|
||||
}).toList();
|
||||
}
|
||||
|
||||
private IWorkUserInfoRespVO buildUserInfoResponse(String responseBody) {
|
||||
IWorkUserInfoRespVO respVO = new IWorkUserInfoRespVO();
|
||||
respVO.setRawBody(responseBody);
|
||||
if (!StringUtils.hasText(responseBody)) {
|
||||
return respVO;
|
||||
}
|
||||
@@ -432,7 +505,6 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
|
||||
|
||||
private IWorkOperationRespVO buildOperationResponse(String responseBody) {
|
||||
IWorkOperationRespVO respVO = new IWorkOperationRespVO();
|
||||
respVO.setRawBody(responseBody);
|
||||
if (!StringUtils.hasText(responseBody)) {
|
||||
return respVO;
|
||||
}
|
||||
@@ -666,6 +738,21 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
|
||||
return value.replace("'", "'\"'\"'");
|
||||
}
|
||||
|
||||
private record SealRequestFields(String jbr,
|
||||
String yybm,
|
||||
String fb,
|
||||
String sqsj,
|
||||
String yyqx,
|
||||
String yyfkUrl,
|
||||
String yysy,
|
||||
String xyywjUrl,
|
||||
String yysx,
|
||||
String ywxtdjbh,
|
||||
String workflowId) {
|
||||
private static final String DEFAULT_FLOW_TYPE = "2979600781334966993";
|
||||
private static final String DEFAULT_SIGN_ACTION = "CORPORATE";
|
||||
}
|
||||
|
||||
private record RegistrationState(String secret, String spk, ClientKeyPair clientKeyPair) {
|
||||
}
|
||||
|
||||
|
||||
@@ -109,7 +109,6 @@ iwork:
|
||||
base-url: http://172.16.36.233:8080
|
||||
# app-id: f47ac10b-58cc-4372-a567-0e02b2c3d479
|
||||
app-id: f47ac10b-58cc-4372-a567-0e02b2c3d479
|
||||
client-public-key:
|
||||
user-id: 9869
|
||||
workflow-id: 1753
|
||||
paths:
|
||||
|
||||
Reference in New Issue
Block a user