iwork 用印改动 未完成

This commit is contained in:
chenbowen
2026-01-28 16:34:51 +08:00
parent b7293f7897
commit 1d79da5914
32 changed files with 1277 additions and 75 deletions

View File

@@ -1,6 +1,6 @@
# iWork 统一集成使用说明
本文档介绍如何在 System 模块中使用项目已实现的统一 iWork 流程发起能力controller + service + properties。内容包含配置项、调用方式内部 Java 调用 & 外部 HTTP 调用)、请求/响应示例、错误处理、缓存与 Token 生命周期、典型问题与排查步骤。
本文档介绍如何在 System 模块中使用项目已实现的统一 iWork 流程发起能力controller + service + properties。内容包含配置项、调用方式内部 Java 调用 & 外部 HTTP 调用)、请求/响应示例、错误处理、缓存与 Token 生命周期、业务回调分发与重试、流程日志查询,以及典型问题与排查步骤。
---
@@ -12,7 +12,10 @@
- 提供 Service 层 `IWorkIntegrationService`,供其它模块以 Spring Bean 注入方式直接调用。
- 使用 `IWorkProperties` 绑定 `application.yml``iwork` 的配置项。
- Token / 会话采用本地 Caffeine 缓存缓存(按 appId + operatorUserId 缓存 session并在到期前按配置提前刷新。
- 使用统一配置的 appId、公钥以及默认流程编号无需再维护多套凭证。
- 使用统一配置的 appId、公钥以及默认流程编号无需再维护多套凭证,所有调用强制使用配置的 appId不再接受请求覆盖
- 全链路以 requestId 作为唯一业务标识(发起返回、作废入参、日志查询、回调与重试均基于 requestIdworkflowId 仅用于指定 iWork 模板。
- 支持业务回调标识 bizCallbackKey字符串≤255发起时提交回调时按标识分发业务回调并带自动重试与手工重试入口。
- 回调与日志记录会保存截断后的原始回调请求/响应文本(无需脱敏),无业务附件或处理异常时标记失败。
---
@@ -47,6 +50,10 @@ iwork:
token:
ttl-seconds: 3600 # token 有效期(秒)
refresh-ahead-seconds: 60 # 在到期前多少秒认为需要刷新
callback:
retry:
max-attempts: 3 # 业务回调自动重试次数(默认 3 次,可调整)
delay-seconds: 5 # 业务回调自动重试间隔秒数(默认 5 秒,可调整)
client:
connect-timeout: 5s
response-timeout: 30s
@@ -55,10 +62,11 @@ iwork:
说明:
- `base-url` 为 iWork 网关的基础地址,不能留空。
- `app-id``client-public-key` 共同构成注册/申请 token 所需的凭据信息,由配置统一提供,不再支持多套切换。
- `workflow-id` 提供全局默认流程编号,单次调用也可通过 `workflowId` 覆盖
- `app-id``client-public-key` 共同构成注册/申请 token 所需的凭据信息,由配置统一提供,不再支持多套切换,系统强制使用配置的 appId忽略请求中的 appId
- `workflow-id` 提供全局默认流程编号,仅用于向 iWork 指定流程模板;流程标识、查询、补偿、回调与重试一律使用 requestId不再以 workflowId 标识业务
- 请求头键名固定为 `app-id``client-public-key``secret``token``time``user-id`,无需在配置中重复声明。
- `org.*` 配置负责 iWork 人力组织 REST 代理:`token-seed` 为与 iWork 约定的标识,系统会自动将其与毫秒时间戳拼接并计算 MD5 生成 `key`,无需额外传递 token。
- `callback.retry.*` 控制业务回调的自动重试次数与间隔,默认为 3 次、5 秒,可按需调整。
---
@@ -102,7 +110,7 @@ Controller 暴露的 REST 接口:
## 请求 VO 说明(重要字段)
- IWorkBaseReqVO公用字段
- `appId` (String)为兼容历史接口保留,系统始终使用配置项 `iwork.app-id`
- `appId` (String)仅保留字段,系统强制使用配置项 `iwork.app-id`,忽略请求值
- `operatorUserId` (String):在 iWork 内部代表操作人的用户编号(可为空,框架会使用 `properties.userId`)。
- `forceRefreshToken` (Boolean):是否强制刷新 token例如遇到 token 错误时强制刷新)。
@@ -117,7 +125,7 @@ Controller 暴露的 REST 接口:
- `success` / `message`:调用成功标志与提示信息。
- IWorkWorkflowCreateReqVO统一用印流程发起
- `workflowId` (String):流程模板 ID必填不再回退到配置
- `workflowId` (String):流程模板 ID必填通常由配置 `iwork.workflow-id` 提供;仅用于向 iWork 指定模板,不再作为业务标识
- `jbr`用印申请人iWork 人员 ID必填
- `yybm`:用印部门 ID必填
- `fb`:用印单位/分部 ID必填
@@ -128,10 +136,11 @@ Controller 暴露的 REST 接口:
- `xyywjUrl`:用印材料附件 URL必填
- `yysx`:用印事项(必填)。
- `ywxtdjbh`:业务系统单据编号(必填,同时用于生成流程标题“用印-{ywxtdjbh}”)。
- `bizCallbackKey` (String)业务回调标识≤255 字符,回调时按该标识分发到对应业务回调入口(可选但推荐)。
- 额外字段不再支持Service 会根据以上字段自动补齐固定流程类型 (`lclx=2979600781334966993`) 与签署动作 (`qsdz=CORPORATE`)。
- IWorkWorkflowVoidReqVO作废
- `requestId` (String):流程请求编号(必填)。
- `requestId` (String):流程请求编号(必填,唯一标识)。
- `reason``extraParams``formExtras` 等用于传递作废原因或额外字段。
- IWorkFormFieldVO表单字段
@@ -188,8 +197,9 @@ public class MyService {
说明:
- 若需使用特定凭证,可设置 `req.setAppId("my-iwork-app")`
- 若需覆盖默认流程模板,可调用 `req.setWorkflowId(123L)` 指定
- 无需设置 appId系统强制使用配置项 `iwork.app-id`
- `workflowId` 通常来自配置 `iwork.workflow-id`,也可在请求中指定模板编号,但流程标识一律以返回的 requestId 为准
- 可设置 `bizCallbackKey` 以便回调时分发到对应业务处理;建议在发起后立即记录响应中的 requestId 及 bizCallbackKey。
- 若希望以特定 iWork 操作人发起,可设置 `req.setOperatorUserId("1001")`
---
@@ -202,7 +212,6 @@ public class MyService {
curl -X POST \
-H "Content-Type: application/json" \
-d '{
"appId":"my-iwork-app",
"identifierKey":"loginid",
"identifierValue":"zhangsan"
}' \
@@ -238,19 +247,20 @@ curl -X POST -H "Content-Type: application/json" -d '{
"yysy":"与客户合同用印",
"xyywjUrl":"https://files.example.com/contract.pdf",
"yysx":"合同用印",
"ywxtdjbh":"DJ-2025-0001"
"ywxtdjbh":"DJ-2025-0001",
"bizCallbackKey":"seal-flow-callback"
}' https://your-zt-server/admin-api/system/integration/iwork/workflow/create
```
> 说明:外部仍以 JSON 请求调用本服务,系统在向 iWork 转发时会自动将负载转换为 `application/x-www-form-urlencoded` 表单(含 `requestName`、`workflowId`、`mainData` 等字段)。
> 响应的 `data.requestId` 为唯一业务标识请在业务侧保存appId 始终取配置;`xyywjFileName` 不存储。
1. Void workflow
```bash
curl -X POST -H "Content-Type: application/json" -d '{
"requestId":"REQ-001",
"reason":"作废原因",
"appId":"my-iwork-app"
"reason":"作废原因"
}' https://your-zt-server/admin-api/system/integration/iwork/workflow/void
```
@@ -259,34 +269,98 @@ curl -X POST -H "Content-Type: application/json" -d '{
## 核心逻辑与细节
1. 基础参数解析
appId始终取配置 `iwork.app-id`,忽略请求值。
主标识:全链路仅使用 `requestId`(发起返回、作废入参、日志查询、回调分发、重试都基于 requestId
模板:`workflowId` 仅用于选择 iWork 模板,不作为业务标识。
业务回调标识:`bizCallbackKey`字符串≤255发起时提交回调按该标识分发到具体业务回调入口。
附件文件名:`xyywjFileName` 不存储也不参与处理;仅使用 `xyywjUrl`
系统始终使用 `application.yml` 中配置的 `app-id``client-public-key` 与 iWork 通信
请求体中的 `appId` 字段仅为兼容历史调用而保留,框架内部不会使用该值做切换
1. Workflow 模板解析
调用时优先使用请求体中的 `workflowId`
若未显式传入,则回退到全局 `iwork.workflow-id`,若仍为空则抛出 `IWORK_WORKFLOW_ID_MISSING`
1. 注册 + RSA + Token
- 在首次或 token 过期时,会按以下步骤获取 session
调用时可在请求体中指定 `workflowId` 以选择模板;若未显式传入,则回退到全局 `iwork.workflow-id`,若仍为空则抛出 `IWORK_WORKFLOW_ID_MISSING`
POST `/system/integration/iwork/workflow/create`:发起用印流程,返回 `requestId`
POST `/system/integration/iwork/workflow/void`:作废流程,请求需携带 `requestId`
POST `/system/integration/iwork/callback/file`(上游回调):接收 iWork 回调,校验 `requestId`,若缺 `bizCallbackKey` 则记录失败但不中断附件保存;下载并落库附件,记录回调日志(截断原文),并在提供 `bizCallbackKey` 时通过 RocketMQ 分发业务回调(自动/手工重试)。
POST `/system/integration/iwork/log/page`分页查询用印回调日志requestId / 业务单号 / bizCallbackKey / 状态 / 时间段)。
POST `/system/integration/iwork/log/retry`:手工重试业务回调,需权限,入参 `requestId`(状态为失败/超重试时可用)
1. 向 iWork 的 `register` 接口发起请求Headers 包含 appId 与 clientPublicKey
2. 从注册响应中获取 `secret``spk`(服务端公钥),使用本地的 client 公钥做 RSA 加密(`spk` 用于加密),得到加密后的 secret 与 encryptedUserId。
3. 使用注册返回的密钥申请 tokenapply-tokentoken 会被按 `ttl-seconds` 缓存
- `IWorkIntegrationServiceImpl` 中维护一个 Caffeine `sessionCache`,缓存 key 为 `appId::operatorUserId`
发起:`workflowId``jbr``yybm``fb``sqsj``yyqx``xyywjUrl``yysx``ywxtdjbh` 必填;`bizCallbackKey` 可选但建议提供appId 忽略
作废:`requestId` 必填;`reason` 可选。
回调:若无法找到业务附件(或不存在),标记用印失败并记日志,不抛出未捕获异常;记录原始回调文本(截断)
- 当 token 接近到期(`refresh-ahead-seconds`)时会在下一次请求触发刷新。
1. 请求构造
- 用户解析、作废等场景继续以 `application/json` 调用 iWork
- 用印流程发起在转发至 iWork 时改为 `application/x-www-form-urlencoded` 表单,请求正文包含 `requestName``workflowId` 及字符串化后的 `mainData`,与 iWork 网关当前要求保持一致
- 认证 Header`IWorkProperties.Headers` 中的常量控制,固定键名为 `app-id``client-public-key``secret``token``time``user-id`
1) 发起:校验必填 → 使用配置 appId 与模板 workflowId → 申请/缓存 token → 以 form-urlencoded 调 iWork → 返回 `requestId`,记录发起日志状态。
2) 回调(/callback/file校验 requestId + bizCallbackKey → 校验租户/必备字段 → 下载/保存附件(若缺业务附件则直接标记失败并记日志)→ 写入回调日志,保存原始回调请求/响应(截断)→ 通过 RocketMQ 发送业务回调消息topic=`SYSTEM_IWORK_BIZ_CALLBACK`tag=`bizCallbackKey`)。
3) 业务处理 & 结果上报(跨模块/跨进程):业务模块订阅 `SYSTEM_IWORK_BIZ_CALLBACK` 对应 tag 处理后,将结果发布到 `SYSTEM_IWORK_BIZ_CALLBACK_RESULT`tag 同 bizCallbackKey携带 requestId / bizCallbackKey / success / errorMessage / payload / attempt / maxAttemptssystem 模块消费结果并更新日志,失败且未超限时由 system 端按配置延迟重试再次投递回调消息
4) 重试:默认 3 次、间隔 5 秒,可配置(`iwork.callback.retry.*`),手工重试仍使用 `/log/retry`,由 system 模块重新投递 MQ 消息
5) 手工重试:需具备 iWork 模块权限;根据 requestId 将任务重新投递至回调分发器,不增加自动重试计数,可在日志详情中发起
1. 响应解析
`CREATE_PENDING` / `CREATE_SUCCESS` / `CREATE_FAILED`
`CALLBACK_PENDING` / `CALLBACK_SUCCESS` / `CALLBACK_FAILED`
`CALLBACK_RETRYING` / `CALLBACK_RETRY_FAILED`
- 实现里对响应成功的判定比较宽松:检查 `code``status``success``errno` 等字段(支持布尔、字符串 0/1/success以判断是否成功并解析常见的 message 字段 `msg|message|errmsg`
---
## 用印流程日志与业务回调
### 范围与标识
- appId始终取配置 `iwork.app-id`,忽略请求值。
- 主标识:全链路仅使用 `requestId`(发起返回、作废入参、日志查询、回调分发、重试都基于 requestId
- 模板:`workflowId` 仅用于选择 iWork 模板,不作为业务标识。
- 业务回调标识:`bizCallbackKey`字符串≤255发起时提交回调按该标识分发到具体业务回调入口。
- 附件文件名:`xyywjFileName` 不存储也不参与处理;仅使用 `xyywjUrl`
### 入口REST
- POST `/system/integration/iwork/workflow/create`:发起用印流程,返回 `requestId`
- POST `/system/integration/iwork/workflow/void`:作废流程,请求需携带 `requestId`
- POST `/system/integration/iwork/callback/file`(上游回调):接收 iWork 回调,校验 `requestId`,若缺 `bizCallbackKey` 则记录失败但不中断附件保存;下载并落库附件,记录回调日志(截断原文),并在提供 `bizCallbackKey` 时通过 RocketMQ 分发业务回调(自动/手工重试)。
- POST `/system/integration/iwork/log/page`分页查询用印回调日志requestId / 业务单号 / bizCallbackKey / 状态 / 时间段)。
- POST `/system/integration/iwork/log/retry`:手工重试业务回调,需权限,入参 `requestId`(状态为失败/超重试时可用)。
### 必填/校验要点
- 发起:`workflowId``jbr``yybm``fb``sqsj``yyqx``xyywjUrl``yysx``ywxtdjbh` 必填;`bizCallbackKey` 可选但建议提供appId 忽略。
- 作废:`requestId` 必填;`reason` 可选。
- 回调:若无法找到业务附件(或不存在),标记用印失败并记日志,不抛出未捕获异常;记录原始回调文本(截断)。
### 处理流程(摘要)
1) 发起:校验必填 → 使用配置 appId 与模板 workflowId → 申请/缓存 token → 以 form-urlencoded 调 iWork → 返回 `requestId`,记录发起日志状态。
2) 回调(/callback/file校验 requestId + bizCallbackKey → 校验租户/必备字段 → 下载/保存附件(若缺业务附件则直接标记失败并记日志)→ 写入回调日志,保存原始回调请求/响应(截断)→ 通过 RocketMQ 发送业务回调消息topic=`SYSTEM_IWORK_BIZ_CALLBACK`tag=`bizCallbackKey`)。
3) 业务处理 & 结果上报(跨模块/跨进程):业务模块订阅 `SYSTEM_IWORK_BIZ_CALLBACK` 对应 tag 处理后,将结果发布到 `SYSTEM_IWORK_BIZ_CALLBACK_RESULT`tag 同 bizCallbackKey携带 requestId / bizCallbackKey / success / errorMessage / payload / attempt / maxAttemptssystem 模块消费结果并更新日志,失败且未超限时由 system 端按配置延迟重试再次投递回调消息。
4) 重试:默认 3 次、间隔 5 秒,可配置(`iwork.callback.retry.*`),手工重试仍使用 `/log/retry`,由 system 模块重新投递 MQ 消息。
5) 手工重试:需具备 iWork 模块权限;根据 requestId 将任务重新投递至回调分发器,不增加自动重试计数,可在日志详情中发起。
### 状态字面量(示例)
- `CREATE_PENDING` / `CREATE_SUCCESS` / `CREATE_FAILED`
- `CALLBACK_PENDING` / `CALLBACK_SUCCESS` / `CALLBACK_FAILED`
- `CALLBACK_RETRYING` / `CALLBACK_RETRY_FAILED`
> 实际实现可根据需要细化,唯一标识均为 requestId。
### 重试与配置
- 自动重试:默认 `maxAttempts=3``delaySeconds=5`,可配置(示例键:`iwork.callback.retry.max-attempts``iwork.callback.retry.delay-seconds`)。
- 手工重试:权限校验(沿用 iWork 模块权限前缀);仅在失败/超重试状态下开放。
- 幂等:按 requestId + bizCallbackKey 进行幂等检查,成功后不再重复分发,除非手工强制重试。
### 日志存储
- 表:`system_iwork_seal_callback_log`(示例字段)
- `requestId`PK`businessCode`(ywxtdjbh)、`bizCallbackKey``status``retryCount``lastErrorMessage``fileUrl``fileId``businessFileId``requestBody``responseBody``rawCallback`(截断保存原文)、`lastCallbackTime``creator``createTime``updateTime`
- 字段要点:
- `rawCallback`:保存回调原始文本,截断存储(无需脱敏,不注明上限)。
- 无业务附件或保存失败:写 `status=CREATE_FAILED` / `CALLBACK_FAILED` 并记录错误原因。
### 查询与展示
- 分页:沿用 `PageParam` 约束,`pageNo` 默认 1、`pageSize` 默认 10、上限 10000仅分页浏览不支持导出。
- 查询条件:`requestId``businessCode`(ywxtdjbh)、`bizCallbackKey``status`、时间范围createTime / lastCallbackTime
- 列表字段requestId、业务单号、bizCallbackKey、状态、重试次数、最后错误、更新时间。
- 详情:展示截断的回调原文(请求/响应)、错误原因、附件信息;提供“手工重试”按钮(需权限)。
---
@@ -326,8 +400,8 @@ curl -X POST -H "Content-Type: application/json" -d '{
## 小结与建议
- 在配置中补齐 `iwork.app-id``iwork.client-public-key``iwork.user-id``iwork.workflow-id` 等关键字段。
- 优先在本地通过 `IWorkIntegrationService` Java API 调试,成功后再通过 Controller 的 REST 接口对外暴露。
- 若遇到请求失败,查看应用日志(`[iWork]` 前缀的日志)与 iWork 网关返回 body,定位是注册、申请 token还是业务接口user-info/create/void失败
- 在配置中补齐 `iwork.app-id``iwork.client-public-key``iwork.user-id``iwork.workflow-id` 等关键字段,并按需配置回调重试参数(默认 3 次5 秒间隔)
- 优先在本地通过 `IWorkIntegrationService` Java API 调试,成功后再通过 Controller 的 REST 接口对外暴露;发起后请记录返回的 requestId唯一标识与 bizCallbackKey
- 若遇到请求失败,查看应用日志(`[iWork]` 前缀的日志)与 iWork 网关返回 body;若业务回调失败,可在日志页面查看截断原文并按权限发起手工重试
文档已生成并保存到:`docs/iWork集成说明.md`