- 新增完整的 iWork 用印流程集成开发文档 - 包含整体架构图和完整流程时序图 - 详细说明数据库设计和状态流转机制 - 提供 API 接口说明和请求参数定义 - 描述 MQ 消息机制和消息格式定义 - 编写业务模块接入指南和消费者实现示例 - 说明重试机制配置和手工重试接口 - 提供本地开发调试和常见问题解决方案 - 列出相关代码位置便于查阅和维护
22 KiB
22 KiB
iWork 用印流程集成开发文档
1. 概述
本文档描述了 ZT Cloud 平台与 iWork 系统的用印流程集成方案,包括流程发起、回调处理、消息通知及重试机制。
1.1 功能特性
- 流程发起:支持用印专用流程和通用流程两种创建方式
- 回调处理:接收 iWork 回调,自动通知业务模块
- 消息队列:基于 RocketMQ 的异步消息通知机制
- 自动重试:失败回调自动重试,支持配置重试次数和间隔
- 日志追踪:完整记录流程创建和回调处理全生命周期
1.2 整体架构
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 业务系统 │────▶│ System 模块 │────▶│ iWork 系统 │
│ (调用方) │ │ (集成层) │ │ (OA 流程) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
▲ ▲ │
│ │ │
│ └───────────────────────┘
│ iWork 流程完成后回调
│ ┌─────────────────┐
│ │ RocketMQ │
│ │ (消息队列) │
└───────────────┴─────────────────┘
1.3 完整流程时序图
┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐
│ 业务系统 │ │ System │ │ iWork │ │RocketMQ│ │业务消费者│
└───┬────┘ └───┬────┘ └───┬────┘ └───┬────┘ └───┬────┘
│ │ │ │ │
│ 1.发起用印流程 │ │ │ │
│──────────────▶│ │ │ │
│ │ 2.创建流程 │ │ │
│ │──────────────▶│ │ │
│ │ 返回requestId│ │ │
│ │◀──────────────│ │ │
│ 返回结果 │ │ │ │
│◀──────────────│ │ │ │
│ │ │ │ │
│ │ │ 3.OA流程审批 │ │
│ │ │ (异步进行) │ │
│ │ │ │ │
│ │ 4.流程完成回调 │ │ │
│ │◀──────────────│ │ │
│ │ │ │ │
│ │ 5.发送MQ消息 │ │ │
│ │──────────────────────────────▶│ │
│ │ │ │ 6.投递消息 │
│ │ │ │──────────────▶│
│ │ │ │ │
│ │ │ │ 7.返回处理结果 │
│ │ │ │◀──────────────│
│ │ 8.接收结果 │ │ │
│ │◀──────────────────────────────│ │
│ │ │ │ │
│ │ 9.更新日志状态 │ │ │
│ │ (成功/重试) │ │ │
└───────────────┴───────────────┴───────────────┴───────────────┘
流程说明:
- 发起流程:业务系统调用 System 模块的流程创建接口
- 创建流程:System 模块调用 iWork API 创建 OA 流程,获取
requestId - OA 审批:流程在 iWork 系统中流转(审批、签章等),此过程异步进行
- iWork 回调:流程完成后,iWork 系统主动回调 System 模块的回调接口
- MQ 通知:System 模块将回调数据通过 RocketMQ 发送给业务消费者
- 业务处理:业务消费者接收消息并处理(如保存签章文件、更新业务状态)
- 返回结果:业务消费者处理完成后,发送处理结果消息
- 接收结果:System 模块接收处理结果
- 状态更新:根据结果更新日志状态,失败则触发重试机制
2. 数据库设计
2.1 流程日志表 (system_iwork_workflow_log)
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | 主键 |
| request_id | VARCHAR(128) | iWork 请求编号(唯一) |
| workflow_id | BIGINT | 流程模板 ID |
| business_code | VARCHAR(128) | 业务编码 |
| biz_callback_key | VARCHAR(255) | 业务回调标识(MQ tag) |
| raw_request | VARCHAR(2000) | 创建请求原文 |
| status | VARCHAR(32) | 流程状态 |
| callback_status | INTEGER | 回调处理状态 |
| retry_count | INTEGER | 已重试次数 |
| max_retry | INTEGER | 最大重试次数 |
| last_error_message | VARCHAR(512) | 最后错误信息 |
| raw_callback | VARCHAR(2000) | 回调原文 |
| last_callback_time | TIMESTAMP | 最近回调时间 |
| tenant_id | BIGINT | 租户编号 |
2.2 回调状态枚举 (callback_status)
| 值 | 状态 | 说明 |
|---|---|---|
| 0 | CREATE_PENDING | 创建中 |
| 1 | CREATE_SUCCESS | 创建成功 |
| 2 | CREATE_FAILED | 创建失败 |
| 3 | CALLBACK_PENDING | 回调待处理 |
| 4 | CALLBACK_SUCCESS | 回调处理成功 |
| 5 | CALLBACK_FAILED | 回调处理失败 |
| 6 | CALLBACK_RETRYING | 回调重试中 |
| 7 | CALLBACK_RETRY_FAILED | 回调重试失败 |
2.3 状态流转图
┌─────────────────────────────────────────────────────┐
│ 流程创建阶段 │
│ ┌──────────┐ 成功 ┌──────────┐ │
│ │ PENDING │ ─────────▶ │ SUCCESS │ │
│ │ (0) │ │ (1) │ │
│ └──────────┘ └──────────┘ │
│ │ │
│ │ 失败 │
│ ▼ │
│ ┌──────────┐ │
│ │ FAILED │ │
│ │ (2) │ │
│ └──────────┘ │
└─────────────────────────────────────────────────────┘
│
│ iWork 回调
▼
┌─────────────────────────────────────────────────────┐
│ 回调处理阶段 │
│ ┌──────────┐ 成功 ┌──────────┐ │
│ │ CALLBACK │ ─────────▶ │ CALLBACK │ │
│ │ PENDING │ │ SUCCESS │ │
│ │ (3) │ │ (4) │ │
│ └──────────┘ └──────────┘ │
│ │ │
│ │ 失败 │
│ ▼ │
│ ┌──────────┐ 重试中 ┌──────────┐ │
│ │ CALLBACK │ ◀───────▶ │ CALLBACK │ │
│ │ FAILED │ │ RETRYING │ │
│ │ (5) │ │ (6) │ │
│ └──────────┘ └──────────┘ │
│ │ │
│ │ 重试次数耗尽 │
│ ▼ │
│ ┌──────────┐ │
│ │ RETRY │ │
│ │ FAILED(7)│ │
│ └──────────┘ │
└─────────────────────────────────────────────────────┘
3. API 接口说明
3.1 用印流程创建
接口地址:POST /admin-api/system/integration/iwork/workflow/create
请求参数:
{
"operatorUserId": "1001",
"jbr": "1001",
"yybm": "2001",
"fb": "3001",
"sqsj": "2025-01-30",
"yyqx": "内部使用",
"yyfkUrl": "https://example.com/attachment.pdf",
"yysy": "合同盖章",
"xyywjUrl": "https://example.com/contract.pdf",
"yysx": "公章",
"ywxtdjbh": "DJ-2025-0001",
"bizCallbackKey": "seal-callback"
}
| 参数 | 必填 | 说明 |
|---|---|---|
| operatorUserId | 是 | 操作人 iWork 用户 ID |
| jbr | 是 | 用印申请人 |
| yybm | 是 | 用印部门 ID |
| fb | 是 | 用印单位(分部 ID) |
| sqsj | 是 | 申请时间 (yyyy-MM-dd) |
| yyqx | 是 | 用印去向 |
| xyywjUrl | 是 | 用印材料附件 URL |
| yysx | 是 | 用印事项 |
| ywxtdjbh | 是 | 业务系统单据编号 |
| bizCallbackKey | 否 | 业务回调标识 |
| yyfkUrl | 否 | 用印依据附件 URL |
| yysy | 否 | 用印事由 |
3.2 通用流程创建
接口地址:POST /admin-api/system/integration/iwork/workflow/create-generic
请求参数:
{
"operatorUserId": "1001",
"workflowId": 54,
"payload": {
"requestName": "用印-DJ-2025-0001",
"mainData": [
{"fieldName": "jbr", "fieldValue": "1001"},
{"fieldName": "yybm", "fieldValue": "2001"}
]
},
"ywxtdjbh": "DJ-2025-0001",
"bizCallbackKey": "seal-callback"
}
| 参数 | 必填 | 说明 |
|---|---|---|
| operatorUserId | 是 | 操作人 iWork 用户 ID |
| workflowId | 是 | 流程模板 ID |
| payload | 是 | 透传给 iWork 的业务参数 |
| ywxtdjbh | 否 | 业务编码 |
| bizCallbackKey | 否 | 业务回调标识 |
3.3 iWork 回调接口
接口地址:POST /admin-api/system/integration/iwork/callback/file
说明:此接口供 iWork 系统回调,无需认证(@PermitAll, @TenantIgnore)
iWork 侧配置:需要在 iWork 系统中配置回调地址,当流程完成时自动调用此接口。
请求参数:
{
"requestId": "3603649",
"businessCode": "DJ-2025-0001",
"fileUrl": "https://iwork.example.com/signed-file.pdf",
"fileName": "已签章合同.pdf",
"status": "COMPLETED"
}
| 参数 | 必填 | 说明 |
|---|---|---|
| requestId | 是 | iWork 请求编号(与创建流程时返回的一致) |
| businessCode | 是 | 业务编码(与创建流程时传入的 ywxtdjbh 一致) |
| fileUrl | 是 | 签章后文件 URL |
| fileName | 否 | 文件名称 |
| status | 否 | 业务状态 |
回调处理逻辑:
- 根据
requestId查询流程创建日志,获取bizCallbackKey - 更新日志状态为
CALLBACK_PENDING - 发送 MQ 消息通知业务模块(仅当
bizCallbackKey存在时) - 返回处理结果
4. MQ 消息机制
4.1 消息流程图
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ iWork 回调 │───▶│ System 模块 │───▶│ RocketMQ │───▶│ 业务消费者 │
│ │ │ (Producer) │ │ │ │ │
└──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘
│
▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 更新日志状态 │◀───│ System 模块 │◀───│ RocketMQ │◀───│ 返回处理结果 │
│ │ │ (Listener) │ │ │ │ │
└──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘
4.2 Topic 定义
| Topic | 说明 |
|---|---|
| SYSTEM_IWORK_BIZ_CALLBACK | 回调通知消息(System → 业务模块) |
| SYSTEM_IWORK_BIZ_CALLBACK_RESULT | 处理结果消息(业务模块 → System) |
4.3 回调通知消息 (IWorkBizCallbackMessage)
{
"requestId": "3603649",
"bizCallbackKey": "seal-callback",
"payload": { /* 回调原始数据 */ },
"attempt": 0,
"maxAttempts": 3
}
Tag 规则:消息 tag = bizCallbackKey,业务模块按 tag 订阅
4.4 处理结果消息 (IWorkBizCallbackResultMessage)
{
"requestId": "3603649",
"bizCallbackKey": "seal-callback",
"success": true,
"errorMessage": null,
"attempt": 0,
"maxAttempts": 3,
"payload": { /* 原始数据,用于重试 */ }
}
5. 业务模块接入指南
5.1 添加依赖
<dependency>
<groupId>com.zt.plat</groupId>
<artifactId>zt-module-system-api</artifactId>
</dependency>
5.2 实现消费者
@Slf4j
@Component
@RequiredArgsConstructor
@RocketMQMessageListener(
topic = IWorkBizCallbackMessage.TOPIC,
consumerGroup = IWorkBizCallbackMessage.TOPIC + "_YOUR_BIZ_KEY",
selectorExpression = "your-biz-callback-key" // 与 bizCallbackKey 一致
)
public class YourBizCallbackConsumer implements RocketMQListener<IWorkBizCallbackMessage> {
private final RocketMQTemplate rocketMQTemplate;
@Override
public void onMessage(IWorkBizCallbackMessage message) {
log.info("收到 iWork 回调: requestId={}", message.getRequestId());
IWorkBizCallbackResultMessage result;
try {
// 处理业务逻辑
processCallback(message);
result = IWorkBizCallbackResultMessage.builder()
.requestId(message.getRequestId())
.bizCallbackKey(message.getBizCallbackKey())
.success(true)
.attempt(message.getAttempt())
.maxAttempts(message.getMaxAttempts())
.payload(message.getPayload())
.build();
} catch (Exception e) {
log.error("处理回调失败", e);
result = IWorkBizCallbackResultMessage.builder()
.requestId(message.getRequestId())
.bizCallbackKey(message.getBizCallbackKey())
.success(false)
.errorMessage(e.getMessage())
.attempt(message.getAttempt())
.maxAttempts(message.getMaxAttempts())
.payload(message.getPayload())
.build();
}
// 发送处理结果
rocketMQTemplate.syncSend(IWorkBizCallbackResultMessage.TOPIC, result);
}
private void processCallback(IWorkBizCallbackMessage message) {
// 业务处理逻辑
// 1. 解析 payload 获取回调数据
// 2. 更新业务状态
// 3. 保存签章文件等
}
}
5.3 关键配置项
| 配置项 | 说明 |
|---|---|
| consumerGroup | 消费者组,建议格式:TOPIC + "_" + bizCallbackKey |
| selectorExpression | Tag 过滤,必须与发起流程时的 bizCallbackKey 一致 |
5.4 注意事项
- bizCallbackKey 唯一性:每个业务场景使用独立的 bizCallbackKey
- 幂等处理:消费者需实现幂等,同一 requestId 可能重复投递
- 必须返回结果:处理完成后必须发送
IWorkBizCallbackResultMessage - 错误信息:失败时填写 errorMessage,便于问题排查
6. 重试机制
6.1 重试流程
业务处理失败 → 返回 success=false → System Listener 接收
↓
检查 attempt < maxAttempts?
↓ ↓
是 否
↓ ↓
延迟后重新投递 标记最终失败
6.2 配置参数
iwork:
callback:
retry:
max-attempts: 3 # 最大重试次数
delay-seconds: 5 # 重试间隔(秒)
6.3 手工重试
接口地址:POST /admin-api/system/integration/iwork/log/retry
{
"requestId": "3603649"
}
7. 日志查询
7.1 分页查询接口
接口地址:POST /admin-api/system/integration/iwork/log/page
请求参数:
{
"requestId": "3603649",
"businessCode": "DJ-2025-0001",
"bizCallbackKey": "seal-callback",
"status": 4,
"pageNo": 1,
"pageSize": 10
}
8. 本地开发调试
8.1 隔离测试环境
为避免与测试环境消息冲突,本地开发时需修改:
- Listener 消费者组:添加本地标识后缀
consumerGroup = IWorkBizCallbackResultMessage.TOPIC + "_CONSUMER_local"
- Listener Tag 过滤:使用本地专用 tag
selectorExpression = "local_test"
- 业务消费者:同样使用本地专用 bizCallbackKey
selectorExpression = "your-biz-key_local"
- 数据库记录:将
biz_callback_key设为本地专用值
8.2 调试建议
- 使用独立的
bizCallbackKey避免消息串扰 - 检查 RocketMQ 控制台确认消息投递情况
- 关注日志中的
requestId进行链路追踪
9. 常见问题
Q1: 业务消费者收不到消息?
检查项:
selectorExpression是否与bizCallbackKey一致- 消费者组名是否正确
- RocketMQ 连接是否正常
Q2: 收到重复消息?
可能原因:
- 多个环境的 Listener 都在消费同一 topic
- 解决:使用独立的消费者组和 tag 过滤
Q3: 重试不生效?
检查项:
- 是否正确返回了
IWorkBizCallbackResultMessage success字段是否为false- 配置的
max-attempts是否大于当前attempt
10. 相关代码位置
| 组件 | 路径 |
|---|---|
| Controller | zt-module-system-server/.../controller/admin/integration/iwork/IWorkIntegrationController.java |
| Service | zt-module-system-server/.../service/integration/iwork/impl/IWorkIntegrationServiceImpl.java |
| 日志 Service | zt-module-system-server/.../service/integration/iwork/impl/IWorkWorkflowLogServiceImpl.java |
| MQ Producer | zt-module-system-server/.../mq/iwork/IWorkBizCallbackProducer.java |
| MQ Listener | zt-module-system-server/.../mq/iwork/IWorkBizCallbackListener.java |
| 消息定义 | zt-module-system-api/.../mq/iwork/IWorkBizCallbackMessage.java |
| 配置类 | zt-module-system-server/.../framework/integration/iwork/config/IWorkProperties.java |