Files
zt-qms/doc/中铜技术文档/iWork集成说明.md
2025-12-05 14:50:57 +08:00

36 KiB
Raw Blame History

iWork 集成 API 与使用指南

本文面向 调用方后端开发者,介绍如何在 System 模块中使用现有的 iWork 集成能力:流程发起/作废、附件回调、人力组织代理与全量同步。文档按“流程调用能力 / 组织同步能力”拆分,并包含 Mermaid 流程图、字段映射表及禁用策略说明,便于快速自助集成。


背景与适用范围

  • 所有接口位于 zt-module-system-serverIWorkIntegrationController 下,统一前缀 /system/integration/iwork
  • Service 层提供 IWorkIntegrationServiceIWorkOrgRestServiceIWorkSyncService 三个 Bean可在任意业务模块注入调用。
  • 调用 iWork 之前会实时执行 register + apply-token不保留本地缓存组织同步则通过 key+ts 鉴权代理 iWork HR 接口并写入本地组织/用户表。

快速开始清单

  • application.yml 或配置中心已填写 iwork.* 参数。
  • 确认所在网络能访问 iWork register/apply-token/HR 接口。
  • 明确调用方向:流程调用 or 组织同步,两种能力可独立使用。
  • 若使用文件回调,已约定业务附件的 businessCode 与租户。
  • 管理端 admin-api/system/integration/iwork/** 已放通权限。

配置清单

YAML 示例

iwork:
  base-url: https://iwork.example.com
  app-id: my-iwork-app
  client-public-key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...
  user-id: system
  workflow:
    seal-workflow-id: 54
  paths:
    register: /api/ec/dev/auth/regist
    apply-token: /api/ec/dev/auth/applytoken
    user-info: /api/workflow/paService/getUserInfo
    create-workflow: /api/workflow/paService/doCreateRequest
    void-workflow: /api/workflow/paService/doCancelRequest
  token:
    ttl-seconds: 3600
  client:
    connect-timeout: 5s
    response-timeout: 30s
  org:
    token-seed: 5936562a-d47c-4a29-9b74-b310e6c971b7
    paths:
      subcompany-page: /api/hrm/resful/getHrmsubcompanyWithPage
      department-page: /api/hrm/resful/getHrmdepartmentWithPage
      job-title-page: /api/hrm/resful/getJobtitleInfoWithPage
      user-page: /api/hrm/resful/getHrmUserInfoWithPage
      sync-subcompany: /api/hrm/resful/synSubcompany
      sync-department: /api/hrm/resful/synDepartment
      sync-job-title: /api/hrm/resful/synJobtitle
      sync-user: /api/hrm/resful/synHrmresource
配置键 说明 必填 默认值
iwork.base-url iWork 网关地址,需与网络互通 -
iwork.app-id 平台分配的 AppId用于申请 token -
iwork.client-public-key iWork 端提供的 RSA 公钥,系统用其加密凭证 -
iwork.workflow.seal-workflow-id 盖章流程模板 ID其他流程可扩展 -
iwork.paths.* 控制器访问 iWork 的后端路由 -
iwork.token.ttl-seconds token 缓存时长,单位秒 3600
iwork.client.connect-timeout OkHttp 建连超时 5s
iwork.org.token-seed HR 组织同步签名盐值 -

流程调用 API

端到端互动图

sequenceDiagram
    participant Client as 调用方服务
    participant Gateway as ZTCloud /system 接口
    participant IWork as iWork 平台
    Client->>Gateway: POST /auth/register
    Gateway->>IWork: /api/ec/dev/auth/regist
    IWork-->>Gateway: 返回 secret + spk
    Client->>Gateway: POST /auth/token
    Gateway->>IWork: /api/ec/dev/auth/applytoken
    IWork-->>Gateway: token
    Client->>Gateway: POST /workflow/create
    Gateway->>IWork: /api/workflow/paService/doCreateRequest
    IWork-->>Gateway: requestId
    IWork-->>Gateway: 文件回调
    Gateway-->>Client: 业务附件 ID

HTTP 接口分组

功能 Method & Path 对应 iWork 接口 说明
注册凭证 POST /system/integration/iwork/auth/register /api/ec/dev/auth/regist 生成 secret + spk用于后续 token 申请
申请 token POST /system/integration/iwork/auth/token /api/ec/dev/auth/applytoken 以 secret + operatorUserId 换取 token
用户解析 POST /system/integration/iwork/user/resolve /api/workflow/paService/getUserInfo 通过工号/手机号等标识查询 iWork 用户 ID
发起流程 POST /system/integration/iwork/workflow/create /api/workflow/paService/doCreateRequest 将本地业务单推送至 iWork 指定流程
作废流程 POST /system/integration/iwork/workflow/void /api/workflow/paService/doCancelRequest 针对 requestId 触发终止/回收
文件回调 POST /system/integration/iwork/callback/file iWork 自定义回调 将 iWork 附件落地并与业务编码关联

关键参数与 VO

接口 请求体 核心字段 说明
注册凭证 IWorkAuthRegisterReqVO forceRefreshRegistration true 时会重新向 iWork 注册,常用于公钥被重置的场景
申请 token IWorkAuthTokenReqVO operatorUserIdforceRefreshToken operatorUserId 默认读取 iwork.user-id,必要时可传入办件人 ID
用户解析 IWorkUserInfoReqVO identifierKeyidentifierValue 支持 workCodemobileloginId 等键值组合
创建流程 IWorkWorkflowCreateReqVO workflowIdmainDataattachments workflowId 缺省则采用 iwork.workflow.seal-workflow-idmainData 为流程主表字段
作废流程 IWorkWorkflowVoidReqVO requestIdreason reason 最长 400 字,系统会自动截断超长字符
文件回调 IWorkFileCallbackReqVO fileUrlbusinessCode 将远程文件下载后与业务附件绑定,businessCode 对应已有 BusinessFile 记录

发起流程示例

curl -X POST https://{host}/system/integration/iwork/workflow/create ^
  -H "Content-Type: application/json" ^
  -H "Authorization: Bearer <your-token>" ^
  -d @payload.json

payload 示意:

{
  "operatorUserId": "1001",
  "forceRefreshToken": false,
  "jbr": "1001",
  "yybm": "2001",
  "fb": "3001",
  "sqsj": "2025-01-01",
  "yyqx": "寄送客户",
  "yyfkUrl": "https://oss.example.com/依据附件.pdf",
  "yysy": "与 XX 公司签订框架合同",
  "xyywjUrl": "https://oss.example.com/材料附件.pdf",
  "xyywjFileName": "材料附件.pdf",
  "yysx": "合同用印",
  "ywxtdjbh": "DJ-2025-00018"
}

Java 调用片段

IWorkWorkflowCreateReqVO req = new IWorkWorkflowCreateReqVO();
req.setWorkflowId(54);
req.setOperatorUserId("1001");
req.setMainData(Map.of("title", "盖章申请", "amount", 128000));
req.setForceRefreshToken(false);

CommonResult<IWorkOperationRespVO> resp = restTemplate.postForObject(
        baseUrl + "/system/integration/iwork/workflow/create",
        req,
        new ParameterizedTypeReference<>() {});

if (resp == null || !resp.isSuccess()) {
    throw new IllegalStateException("iWork 调用失败" + Optional.ofNullable(resp).map(CommonResult::getMsg).orElse(""));
}
String requestId = resp.getData().getRequestId();

通用请求字段IWorkBaseReqVO

字段 类型 必填 说明 示例
appId string 覆盖默认的 iWork 应用编号;为空时取配置 iwork-app
operatorUserId string 作为 iWork 操作人的用户编号;为空时取 iwork.user-id 1001
forceRefreshToken boolean true 时忽略本地缓存并强制重新申请 token false

所有接口均返回 CommonResult<T> 结构,通用包体为 { "code": 0, "data": T, "msg": "success", "traceId": "..." }。下文的响应字段默认落在 data 节点内。

流程接口字段详解

POST /system/integration/iwork/auth/register

请求字段(/auth/register
字段 类型 必填 说明
forceRefreshRegistration boolean true 时即使已有注册信息也会重新向 iWork 注册,以获取新的 secret + serverPublicKey
响应字段(/auth/register
字段 类型 说明
appId string 实际使用的 iWork 应用编号
clientPublicKey string(Base64) 系统用于加密 secret 的客户端公钥
clientPrivateKey string(Base64) 仅在动态生成公钥时回传,用于后续持久化
serverPublicKey string(Base64) iWork 返回的服务端公钥,需用于加密 secret 与 userId
secret string iWork 发放的密钥,结合公钥加密后才能申请 token
JSON 示例(/auth/register

请求:

POST /system/integration/iwork/auth/register HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer ***

{
  "forceRefreshRegistration": true
}

响应:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "code": 0,
  "msg": "success",
  "data": {
    "appId": "iwork-app",
    "clientPublicKey": "MIIBIjANBgkq...",
    "clientPrivateKey": "MIIEvAIBADANBg...",
    "serverPublicKey": "MIIBCgKCAQEAv...",
    "secret": "d9e7f3e4c5"
  },
  "traceId": "efdb73a0e9f7"
}

失败示例iWork 接口异常):

HTTP/1.1 502 Bad Gateway
Content-Type: application/json

{
  "code": 100500,
  "msg": "向 iWork 注册失败: upstream timeout",
  "data": null,
  "traceId": "c4019de7c3aa"
}

POST /system/integration/iwork/auth/token

请求字段(/auth/token
字段 类型 必填 说明
operatorUserId string 不填则取配置的默认操作者
forceRefreshToken boolean true 时忽略缓存直接调 iWork 申请新 token
forceRefreshRegistration boolean true 时在申请 token 前重新注册,以应对 serverPublicKey 失效
响应字段(/auth/token
字段 类型 说明
appId string 本次 token 绑定的应用编号
operatorUserId string 实际用于发起流程的 iWork 用户
token string iWork 访问令牌
encryptedUserId string 使用 serverPublicKey 加密后的 userId调用 iWork 接口时需要写入 Header
expiresAtEpochSecond long 预计过期时间Epoch 秒)
serverPublicKey string token 对应的 server 公钥
JSON 示例(/auth/token

请求:

POST /system/integration/iwork/auth/token HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer ***

{
  "operatorUserId": "1001",
  "forceRefreshToken": false,
  "forceRefreshRegistration": false
}

响应:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "code": 0,
  "msg": "success",
  "data": {
    "appId": "iwork-app",
    "operatorUserId": "1001",
    "token": "389a6d30-2f7a-4a1a",
    "encryptedUserId": "Q0ZCU0RmVz...",
    "expiresAtEpochSecond": 1764825600,
    "serverPublicKey": "MIIBCgKCAQEAv..."
  },
  "traceId": "9012ab34cd56"
}

失败示例secret 失效):

HTTP/1.1 200 OK
Content-Type: application/json

{
  "code": 0,
  "msg": "success",
  "data": {
    "appId": "iwork-app",
    "operatorUserId": "1001",
    "token": null,
    "encryptedUserId": null,
    "expiresAtEpochSecond": null,
    "serverPublicKey": "MIIBCgKCAQEAv...",
    "success": false,
    "message": "iWork: secret expired, please re-register"
  },
  "traceId": "70e9570f218b"
}

POST /system/integration/iwork/user/resolve

请求字段(/user/resolve
字段 类型 必填 说明
identifierKey string 写入 iWork 所需的字段名,如 workcodemobileloginid
identifierValue string 对应字段的取值
payload map 附加在请求体的扩展参数,会与识别字段一起发送
queryParams map 附加在 URL 上的查询参数
响应字段(/user/resolve
字段 类型 说明
payload map iWork 原始返回 JSON
success boolean 是否判定为成功(根据 code/success 等字段自动推断)
message string 友好提示或错误信息
userId string 从返回体解析出的 iWork 用户编号
JSON 示例(/user/resolve

请求:

POST /system/integration/iwork/user/resolve HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer ***

{
  "identifierKey": "workcode",
  "identifierValue": "A10086",
  "queryParams": {
    "tenant": "ztcloud"
  }
}

响应:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "code": 0,
  "msg": "success",
  "data": {
    "success": true,
    "message": "OK",
    "userId": "1001",
    "payload": {
      "code": "SUCCESS",
      "data": {
        "userid": "1001",
        "lastname": "张三",
        "loginid": "zhangsan"
      }
    }
  },
  "traceId": "b8c1d5fe1039"
}

失败示例(未找到用户):

HTTP/1.1 200 OK
Content-Type: application/json

{
  "code": 0,
  "msg": "success",
  "data": {
    "success": false,
    "message": "iWork 返回空数据",
    "userId": null,
    "payload": {
      "code": "SUCCESS",
      "data": []
    }
  },
  "traceId": "4ea7a1dd6281"
}

POST /system/integration/iwork/workflow/create

请求字段(/workflow/create
字段 类型 必填 说明
jbr string 用印经办人iWork 用户 ID
yybm string 用印部门 ID
fb string 用印单位(分部 ID
sqsj string(yyyy-MM-dd) 申请时间
yyqx string 用印去向/流向
yyfkUrl string 用印依据附件 URL
yysy string 用印事由
xyywjUrl string 待用印材料附件 URL系统会封装成 iWork 需要的数组结构
xyywjFileName string 待用印材料附件名称,默认从 URL 截取
yysx string 用印事项(流程标题关键字段)
ywxtdjbh string 业务系统单据编号,用于生成流程标题与追溯
响应字段(/workflow/create
字段 类型 说明
payload.code string iWork 返回的业务状态,如 SUCCESS
payload.data.requestId long iWork 流程请求编号,后续作废/查询需要使用
payload.errMsg map 错误附加信息(失败时)
payload.reqFailMsg.keyParameters map 失败时的关键参数回显
success boolean SDK 根据 code/success 判断的结果
message string 统一的提示文案
JSON 示例(/workflow/create

请求:

POST /system/integration/iwork/workflow/create HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer ***

{
  "operatorUserId": "1001",
  "forceRefreshToken": false,
  "jbr": "1001",
  "yybm": "2001",
  "fb": "3001",
  "sqsj": "2025-01-01",
  "yyqx": "寄送客户",
  "yyfkUrl": "https://oss.example.com/依据附件.pdf",
  "yysy": "与 XX 公司签订框架合同",
  "xyywjUrl": "https://oss.example.com/材料附件.pdf",
  "xyywjFileName": "材料附件.pdf",
  "yysx": "合同用印",
  "ywxtdjbh": "DJ-2025-00018"
}

响应:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "code": 0,
  "msg": "success",
  "data": {
    "success": true,
    "message": "流程创建成功",
    "payload": {
      "code": "SUCCESS",
      "data": {
        "requestid": 9623451
      },
      "errMsg": {},
      "reqFailMsg": null
    }
  },
  "traceId": "0af7c8f2c7a1"
}

失败示例(字段缺失):

HTTP/1.1 400 Bad Request
Content-Type: application/json

{
  "code": 100001,
  "msg": "参数校验失败",
  "data": {
    "success": false,
    "message": "缺少必填字段: yysx",
    "payload": {
      "code": "FAIL",
      "reqFailMsg": {
        "keyParameters": {
          "missingField": "yysx"
        },
        "msgInfo": {
          "message": "Please provide seal reason"
        }
      }
    }
  },
  "traceId": "f91c1c3772af"
}

POST /system/integration/iwork/workflow/void

请求字段(/workflow/void
字段 类型 必填 说明
requestId string 需要作废的 iWork 流程编号
reason string 作废原因,将映射到 iWork 的 remark 字段(超长会被截断)
extraParams map 直接透传给 iWork 的附加 JSON 字段
formExtras map<string,string> 会被追加到 payload 中的额外 form 字段
响应字段(/workflow/void

/workflow/create 使用的 IWorkOperationRespVO 结构完全一致。

JSON 示例(/workflow/void

请求:

POST /system/integration/iwork/workflow/void HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer ***

{
  "requestId": "REQ-9623451",
  "reason": "业务单据撤回,需终止流程"
}

响应:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "code": 0,
  "msg": "success",
  "data": {
    "success": true,
    "message": "流程已成功作废",
    "payload": {
      "code": "SUCCESS",
      "data": {
        "requestid": 9623451
      }
    }
  },
  "traceId": "5c7f0a9b1d23"
}

失败示例requestId 不存在):

HTTP/1.1 200 OK
Content-Type: application/json

{
  "code": 0,
  "msg": "success",
  "data": {
    "success": false,
    "message": "iWork 返回失败: request not found",
    "payload": {
      "code": "FAIL",
      "reqFailMsg": {
        "keyParameters": {
          "requestid": "REQ-999999"
        },
        "msgInfo": {
          "msg": "流程不存在或已处理"
        }
      }
    }
  },
  "traceId": "98d73ae0bf12"
}

POST /system/integration/iwork/callback/file

请求字段(/callback/file
字段 类型 必填 说明
fileUrl string iWork 可访问的文件下载地址
businessCode string 已存在的业务附件编码将使用该编码定位租户与业务ID
fileName string 覆盖默认文件名,不填则从 URL 末尾截取
响应字段(/callback/file
字段 类型 说明
data long 成功创建的业务附件关联 ID
JSON 示例(/callback/file

请求:

POST /system/integration/iwork/callback/file HTTP/1.1
Host: api.example.com
Content-Type: application/json

{
  "fileUrl": "https://oss.example.com/files/abc.pdf",
  "businessCode": "DJ-2025-00018",
  "fileName": "电子合同.pdf"
}

响应:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "code": 0,
  "msg": "success",
  "data": 8823451990123,
  "traceId": "6f1b0c7d8e91"
}

失败示例(业务编码不存在):

HTTP/1.1 400 Bad Request
Content-Type: application/json

{
  "code": 100210,
  "msg": "业务编码不存在,无法创建附件",
  "data": null,
  "traceId": "72e4fa109d55"
}

组织同步 API

数据流示意

flowchart LR
  IWork[(iWork HR)] -->|分页接口| RestProxy[/IWorkOrgRestService/]
  RestProxy -->|BatchResult| SyncService{{IWorkSyncService}}
  SyncService -->|Dept/Post/UserSaveReqVO| LocalDB[(ZTCloud 系统库)]
  SyncService -->|统计| 调用方

接口矩阵

功能 Method & Path 请求体 备注
分部分页 POST /system/integration/iwork/hr/subcompany/page IWorkSubcompanyQueryReqVO 透传 subcompanycode/subcompanyname 条件
部门分页 POST /system/integration/iwork/hr/department/page IWorkDepartmentQueryReqVO 支持按照 subcompanyId、名称过滤
岗位分页 POST /system/integration/iwork/hr/job-title/page IWorkJobTitleQueryReqVO 可按岗位编码、名称筛选
人员分页 POST /system/integration/iwork/hr/user/page IWorkUserQueryReqVO 支持工号、手机号、状态等组合查询
分部全量同步 POST /system/integration/iwork/hr/subcompanies/full-sync IWorkFullSyncReqVO 默认 scopes=subcompany,按分页批量落库
部门全量同步 POST /system/integration/iwork/hr/departments/full-sync IWorkFullSyncReqVO 自动处理父子依赖,多次遍历确保 parent ready
岗位全量同步 POST /system/integration/iwork/hr/job-titles/full-sync IWorkFullSyncReqVO 岗位编码固定为 IWORK_JOB_${id}
人员全量同步 POST /system/integration/iwork/hr/users/full-sync IWorkFullSyncReqVO 工号优先映射为用户名,自动建档岗位

Full Sync 请求参数

字段 默认值 说明
startPage 1 开始拉取的页码,对应 iWork curpage
pageSize 100 单页数量1-500
maxPages null 限制最大页数null 表示直到 iWork 返回空页
scopes 全量 枚举 subcompanydepartmentjobTitleuser,可多选
id null 指定单个 iWork 实体 ID主要用于补偿
includeCanceled false true 时同步 iWork 失效记录并将其禁用
allowUpdate false 是否允许更新本地已有但来源为 iWork 的记录

系统内部始终启用 createIfMissing=true,因此全量同步会自动建档缺失的分部/部门/岗位/人员。

字段映射(组织)

iWork 字段 本地字段 说明
subcompanyname / departmentname DeptDO.name 自动截断到 30 字符,缺失时使用“未命名*”
subcompanycode / departmentcode DeptDO.code 空字符串会被置空,保持与 iWork 编码一致
supsubcomid / supdepid DeptDO.parentId 优先使用部门父级,退化到分部或根节点
showorder DeptDO.sort 为空则落地 999
canceled DeptDO.status 1/true/yes 视为禁用CommonStatusEnum.DISABLE

字段映射(人员与岗位)

iWork 字段 本地字段 处理规则
jobtitleid PostDO.code=IWORK_JOB_${id} 若本地不存在则自动建档,jobtitlename 作为名称
lastname AdminUserDO.nickname 超过 30 字符会截断
workcodeloginid AdminUserDO.username 首选工号,缺失时使用登录账号,均为空则跳过
departmentidsubcompanyid1 AdminUserDO.deptIds 优先部门,空则落地分部,仍为空则允许为空继续
jobtitleid / jobtitlename AdminUserDO.postIds 通过岗位编码命中缓存,否则按名称动态创建
email / mobile AdminUserDO.email/mobile 同步时跳过重复验证,兼容历史数据
password AdminUserDO.password 直接使用 iWork 原始密码,避免哈希不一致
status AdminUserDO.status 0 视为启用,其余状态视为禁用
sex AdminUserDO.sex 自动适配 0/1/2男/女/M/F 等多种格式

组织同步禁用策略

场景 判定条件 本地处理 备注
分部/部门被禁用 canceled = 1/true/yes includeCanceled=false:跳过;否则创建/更新并设置为禁用 可通过 includeCanceled 控制是否同步
岗位被禁用 canceled 标记为真 同步后 PostDO.status=DISABLE,同时记入统计
人员离职 status0 创建/更新为 DISABLE,并统计在 disabled 数量 status 字段通常为字符串
非 iWork 数据 deptSource/userSource ≠ iWork 永远跳过修改,保证手工数据安全 相关日志输出 Skipped 提示

鉴权与签名

组织接口统一由 IWorkOrgRestService 代理,鉴权方式为:

  1. 读取 iwork.org.token-seed
  2. 运行时生成 ts = System.currentTimeMillis()
  3. 计算 key = MD5(tokenSeed + ts) 并转大写。
  4. { key, ts } 作为 token 字段写入请求体iWork 会基于相同算法校验。

请确保 ZTCloud 所在网络与 iWork 可直接互通,否则需在接口网关上放通上述 URL。

组织接口字段详解

通用分页请求字段(IWorkOrgBaseQueryReqVO

字段 类型 必填 说明
curpage integer 当前页码,默认 1
pagesize integer 每页条数,默认 20最大 500
params map 额外查询条件,直接透传给 iWork

POST /system/integration/iwork/hr/subcompany/page

请求字段subcompany/page
字段 类型 必填 说明
curpage integer 继承自通用分页字段
pagesize integer 同上
subcompanyCode string 按分部编码模糊查询
subcompanyName string 按分部名称模糊查询
响应字段(IWorkHrSubcompanyPageRespVO
字段 类型 说明
code string iWork 返回码
message string 提示信息
success boolean 是否成功
totalSize integer 总记录数
totalPage integer 总页数
pageSize integer 单页条数
pageNumber integer 当前页码
dataList[] array 分部列表

dataList[] 主要字段:

字段 类型 说明
id integer 分部 ID也是本地部门 ID
subcompanycode string 分部编码
subcompanyname string 分部名称
companyid / companyname integer/string 总部标识
supsubcomid / supsubcomname integer/string 上级分部信息
showorder integer 排序号
description string 描述
canceled string 是否失效0/1/true/false
alllevel string 层级路径
attributes map iWork 额外字段的承载容器
JSON 示例(/hr/subcompany/page

请求:

POST /system/integration/iwork/hr/subcompany/page HTTP/1.1
Host: api.example.com
Content-Type: application/json

{
  "curpage": 1,
  "pagesize": 50,
  "subcompanyCode": "HZ",
  "subcompanyName": "杭州"
}

响应:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "code": "SUCCESS",
  "message": "OK",
  "success": true,
  "totalSize": 2,
  "totalPage": 1,
  "pageSize": 50,
  "pageNumber": 1,
  "dataList": [
    {
      "id": 1001,
      "subcompanycode": "HZ01",
      "subcompanyname": "杭州总部",
      "supsubcomid": 0,
      "showorder": 1,
      "canceled": "0"
    },
    {
      "id": 1002,
      "subcompanycode": "HZ02",
      "subcompanyname": "杭州制造分部",
      "supsubcomid": 1001,
      "showorder": 2,
      "canceled": "0"
    }
  ]
}

失败示例(鉴权失败):

HTTP/1.1 200 OK
Content-Type: application/json

{
  "code": "401",
  "message": "key invalid",
  "success": false,
  "totalSize": 0,
  "totalPage": 0,
  "pageSize": 0,
  "pageNumber": 0,
  "dataList": []
}

POST /system/integration/iwork/hr/department/page

请求字段department/page
字段 类型 必填 说明
curpage integer 分页参数
pagesize integer 分页参数
departmentCode string 部门编码
departmentName string 部门名称
subcompanyId string 所属分部 ID
响应字段(IWorkHrDepartmentPageRespVO

顶层字段:

字段 类型 说明
code string iWork 返回码
message string 提示信息
success boolean 是否成功
data.totalSize integer 总记录数
data.totalPage integer 总页数
data.pageSize integer 每页条数
data.page integer 当前页码
data.dataList[] array 部门列表

data.dataList[] 关键字段:部门 IDid)、部门编码(departmentcode)、部门名称(departmentname)、所属分部(subcompanyid1 / subcompanyname)、父部门(supdepid)、显示顺序(showorder)、失效标记(canceled)等,其余原样透传在 attributes 中。

JSON 示例(/hr/department/page

请求:

POST /system/integration/iwork/hr/department/page HTTP/1.1
Host: api.example.com
Content-Type: application/json

{
  "curpage": 1,
  "pagesize": 100,
  "subcompanyId": "1001"
}

响应:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "code": "SUCCESS",
  "message": "OK",
  "success": true,
  "data": {
    "totalSize": 120,
    "totalPage": 2,
    "pageSize": 100,
    "page": 1,
    "dataList": [
      {
        "id": 2001,
        "departmentcode": "R-D",
        "departmentname": "研发一部",
        "subcompanyid1": 1001,
        "supdepid": 0,
        "showorder": 10,
        "canceled": "0"
      }
    ]
  }
}

POST /system/integration/iwork/hr/job-title/page

请求字段job-title/page
字段 类型 必填 说明
curpage integer 分页参数
pagesize integer 分页参数
jobTitleCode string 岗位编码
jobTitleName string 岗位名称
响应字段(IWorkHrJobTitlePageRespVO
字段 类型 说明
code string iWork 返回码
message string 提示信息
success boolean 是否成功
totalSize / totalPage / pageSize / pageNumber integer 分页信息
dataList[] array 岗位集合

dataList[] 字段包含 idjobtitlecodejobtitlenamejobgroupidjobgroupnamejobfunctionshowordercanceled 等,可直接映射到本地岗位表。

POST /system/integration/iwork/hr/user/page

请求字段user/page
字段 类型 必填 说明
curpage / pagesize integer 分页参数
workCode string 人员工号
lastName string 姓名模糊匹配
departmentId / subcompanyId string 组织过滤
jobTitleId string 岗位过滤
status string 人员状态0:在职,其余为非在职)
mobile / email string 联系方式过滤
响应字段(IWorkHrUserPageRespVO
字段 类型 说明
code / message / success string/string/boolean 通用响应字段
totalSize / totalPage / pageSize / pageNumber integer 分页信息
dataList[] array 人员数据

dataList[] 主要字段:idlastnameloginidworkcodesexdepartmentidsubcompanyid1jobtitleidmobileemailstatuspasswordhiredateleavedate 等,以及 attributes 中的扩展数据。同步服务会根据这些字段计算用户名、岗位与状态。

JSON 示例(/hr/user/page

请求:

POST /system/integration/iwork/hr/user/page HTTP/1.1
Host: api.example.com
Content-Type: application/json

{
  "curpage": 1,
  "pagesize": 100,
  "departmentId": "2001",
  "status": "0"
}

响应:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "code": "SUCCESS",
  "message": "OK",
  "success": true,
  "totalSize": 320,
  "totalPage": 4,
  "pageSize": 100,
  "pageNumber": 1,
  "dataList": [
    {
      "id": 30001,
      "lastname": "李四",
      "loginid": "lisi",
      "workcode": "A10086",
      "departmentid": 2001,
      "subcompanyid1": 1001,
      "jobtitleid": 5001,
      "mobile": "13800001111",
      "email": "lisi@example.com",
      "status": "0",
      "password": "4a7d1ed414934d1c4b"
    }
  ]
}

Full Sync 请求参数(IWorkFullSyncReqVO

字段 类型 默认值 说明
startPage integer 1 起始页码,对应 iWork curpage
pageSize integer 100 单页记录数 (1-500)
maxPages integer null 限制最大处理页数null 表示遍历至空页
scopes array<string> ["subcompany","department","jobTitle","user"] 指定同步范围
id string null 仅同步指定 iWork 主键,常用于补偿
includeCanceled boolean false true 时会同步并禁用 iWork 标记为失效的数据
allowUpdate boolean false true 时允许覆盖已有的 iWork 来源记录

系统内部始终启用 createIfMissing=true,因此全量同步会自动建档缺失的分部/部门/岗位/人员。

Full Sync 响应字段(IWorkFullSyncRespVO

字段 类型 说明
processedPages integer 实际处理的页数总和
pageSize integer 每批次请求的页大小回显
subcompanyStat / departmentStat / jobTitleStat / userStat IWorkSyncEntityStatVO 各实体的累计统计
batches[] IWorkSyncBatchStatVO 每个分页批次的明细

IWorkSyncEntityStatVO 字段:pulled(拉取条数)、created(新建)、skippedExisting(跳过)、disabled(禁用)、failed(失败)。

IWorkSyncBatchStatVO 字段:entityTypesubcompany/department/job_title/userpageNumberpulledcreatedskippedExistingdisabledfailed。借助这些字段可以直观看到失败批次并进行定向补偿。

JSON 示例(/hr/users/full-sync

请求:

POST /system/integration/iwork/hr/users/full-sync HTTP/1.1
Host: api.example.com
Content-Type: application/json

{
  "startPage": 1,
  "pageSize": 200,
  "scopes": ["department", "user"],
  "includeCanceled": false,
  "allowUpdate": true
}

响应:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "code": 0,
  "msg": "success",
  "data": {
    "processedPages": 6,
    "pageSize": 200,
    "departmentStat": {
      "pulled": 600,
      "created": 120,
      "skippedExisting": 470,
      "disabled": 5,
      "failed": 5
    },
    "userStat": {
      "pulled": 1200,
      "created": 320,
      "skippedExisting": 780,
      "disabled": 60,
      "failed": 40
    },
    "batches": [
      {
        "entityType": "DEPARTMENT",
        "pageNumber": 1,
        "pulled": 200,
        "created": 40,
        "skippedExisting": 150,
        "disabled": 2,
        "failed": 8
      }
    ]
  },
  "traceId": "0cc5de912f40"
}

失败示例iWork 远端异常):

HTTP/1.1 500 Internal Server Error
Content-Type: application/json

{
  "code": 200501,
  "msg": "调用 iWork 失败: 拉取人员接口超时",
  "data": {
    "processedPages": 3,
    "pageSize": 200,
    "userStat": {
      "pulled": 600,
      "created": 160,
      "failed": 20
    },
    "batches": [
      {
        "entityType": "USER",
        "pageNumber": 3,
        "pulled": 200,
        "failed": 20
      }
    ]
  },
  "traceId": "ab771c30d4ee"
}

故障排查与常见问题

1. Token 申请失败

  • 现象:IWORK_APPLY_TOKEN_FAILED,日志提示 “返回缺少 token”。
  • 处理:
    1. 确认 iwork.base-url 是否指向正式域名;
    2. 核对 appId、client 公钥是否与 iWork 后台一致;
    3. 如需重新注册,将 /auth/register/auth/tokenforceRefreshRegistration=trueforceRefreshToken=true 同时置为 true。

2. 组织分页 401 或“key 无效”

  • 现象iWork 返回 code=401success=falsemessage 包含 key invalid
  • 处理:
    • 校验服务器时间是否与 iWork 相差 < 60s
    • 确保 token-seed 未被误填为空;
    • 通过日志中输出的 cURL[iWork-Org] curl)复现请求,核对 key/ts 是否被代理层篡改。

3. 人员同步缺少岗位

  • 现象:BatchResultfailed 大量增加,日志提示 “岗位缺少标识”。
  • 处理:
    • 确认先执行岗位全量同步;
    • 若 iWork 未维护岗位,可在本地预建岗位并记录在字典,再由 iWork 返回 jobtitlename 供系统创建。

4. 附件回调 404

  • 现象iWork 回调 /callback/file 返回 “业务编码不能为空”。
  • 处理:
    • 需要提前在业务流程中调用 BusinessFileApi 建立 businessCode
    • 回调只接受 POST JSON并且必须包含 fileUrlbusinessCode

诊断 checklist

  1. 查看 logs/system/iwork*.log,定位请求链路与响应体;
  2. 通过 IWorkFullSyncRespVObatches 字段复盘每页统计;
  3. 若同步停在某一批次,可使用 id + scopes 方式做定向补偿;
  4. 启用 includeCanceled=true 可帮助确认 iWork 的状态标记是否准确。