____ _ ____ _
/ ___| ___ __ _| | / ___| _ _ ___| |_ ___ _ __ ___
\___ \ / _ \/ _` | | \___ \| | | / __| __/ _ \ '_ ` _ \
___) | __/ (_| | | ___) | |_| \__ \ || __/ | | | | |
|____/ \___|\__,_|_| |____/ \__, |___/\__\___|_| |_| |_|
|___/ | 能力 | 说明 |
|---|---|
| 合同签署 | 基于模板创建签署任务,支持多方签署 |
| 签署页面 | 提供开箱即用的签署页面(seal-core),支持 iframe / WebView 嵌入 |
| 状态通知 | 通过 Webhook 实时推送签署状态变更 |
| 文件管理 | 合同 PDF 生成、签章合成、已签署文件下载 |
| 安全保障 | 多种认证模式、数据隔离、IP 白名单、请求限流 |
┌─────────────────────────────────────────────────────────────────────┐
│ │
│ 你的系统 Contract.Pro 开放平台 │
│ │
│ ┌──────────────┐ ┌──────────────────────────────┐ │
│ │ 业务系统 │ API / SDK │ Open API 服务 │ │
│ │ (你开发) │ ──────────────→ │ - 签署任务管理 │ │
│ │ │ ←────────────── │ - Webhook 回调 │ │
│ └──────┬───────┘ │ - 文件下载 │ │
│ │ └──────────┬───────────────────┘ │
│ │ 嵌入 signUrl │ │
│ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────────────────────┐ │
│ │ 你的前端页面 │ iframe / │ 签署页面 (seal-core) │ │
│ │ (你开发) │ WebView │ (Contract.Pro 提供,开箱即用) │ │
│ └──────────────┘ └──────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘| 项目 | 说明 |
|---|---|
| Base URL | https://your-domain.com/open-api |
| 协议 | HTTPS |
| 数据格式 | JSON |
| 字符编码 | UTF-8 |
| 接入方式 | 接入难度 | 开发周期 | 适用场景 | 签署页面 | 当前状态 |
|---|---|---|---|---|---|
| API 对接 | ★★☆ | 1-3 天 | 已有业务系统,需要嵌入签署能力 | 使用 Contract.Pro 提供的签署页面(seal-core) | ✅ 已支持 |
| SDK 对接(Spring Boot Starter) | ★☆☆ | 0.5-1 天 | Spring Boot 项目深度集成,将签署能力嵌入自己的系统 | 使用 Contract.Pro 提供的签署页面(seal-core) | ✅ 已支持 |
| 私有化部署 | ★★★★ | 1-2 周 | 数据安全要求极高,需完全自主可控 | 全部自有 | 📋 企业版 |
┌─────────────────────────────────────────────────────────────────┐
│ 你需要开发的部分 │
│ │
│ ┌──────────────┐ HTTP API ┌──────────────────────────┐ │
│ │ 你的业务系统 │ ─────────────→ │ Contract.Pro Open API │ │
│ │ │ ←───────────── │ (后端服务) │ │
│ │ - 调用 API │ └──────────┬───────────────┘ │
│ │ - 处理回调 │ │ │
│ │ - 业务页面 │ │ │
│ └──────┬───────┘ │ │
│ │ │ │
│ │ 嵌入 signUrl │ │
│ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────────────────┐ │
│ │ 你的前端页面 │ iframe / │ 签署页面 (seal-core) │ │
│ │ (合同列表等) │ WebView │ ← Contract.Pro 提供 │ │
│ └──────────────┘ │ ← 你不需要开发这部分 │ │
│ └──────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘notifyChannel: "platform" 模式下由平台自动发送)yudao-module-seal-spring-boot-starter,将完整的电子签署能力嵌入你的 Spring Boot 项目。Seal 模块的 Controller、Service、数据访问层全部通过 Spring Boot 自动配置注册到你的应用中,数据存储在你自己的数据库里。本质上,SDK 对接 = 把 Seal 模块跑在你自己的 JVM 里,用你自己的数据库和存储。与 API 对接的区别是:API 对接调用的是远程服务,SDK 对接是本地方法调用。
┌─────────────────────────────────────────────────────────────────┐
│ 你的 Spring Boot 项目 │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 1. 添加 Maven 依赖 │ │
│ │ yudao-module-seal-spring-boot-starter │ │
│ │ (自动传递依赖 seal-api + seal-biz) │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 2. 配置 application.yml(可选,Starter 已内置默认配置) │ │
│ │ yudao.seal.auth.type=jwt / oauth2 / custom │ │
│ │ yudao.seal.storage.type=local / oss / minio │ │
│ │ │ │
│ │ ℹ️ mode=starter 由 Starter JAR 内置配置自动设置, │ │
│ │ 你不需要手动配置这个值 │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 3. (可选) 实现自定义 SPI 接口 │ │
│ │ @Component │ │
│ │ class MyAuthProvider implements SealAuthProvider {...} │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 自动装配流程(引入 Starter 后自动完成) │ │
│ │ │ │
│ │ Starter JAR 内置 mode=starter │ │
│ │ ↓ 触发 │ │
│ │ SealAutoConfiguration 生效 │ │
│ │ ↓ 扫描并注册 │ │
│ │ ┌────────────┐ ┌────────────┐ ┌────────────────────┐ │ │
│ │ │ 认证适配器 │→ │ Controller │→ │ Service + 数据层 │ │ │
│ │ │ 存储适配器 │ │ 自动暴露 │ │ 自动注册 │ │ │
│ │ │ 用户验证器 │ │ │ │ │ │ │
│ │ └────────────┘ └────────────┘ └────────────────────┘ │ │
│ │ │ │
│ │ 同时,seal-biz 通过 SealConfigurationLoader 自动加载 │ │
│ │ application-seal.yaml(模块默认配置) │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ 你的数据库 (MySQL) │ 你的缓存 (Redis) │ 你的存储 (本地/OSS) │
└─────────────────────────────────────────────────────────────────┘| 内部模式(direct) | Starter 模式(starter) | |
|---|---|---|
| 使用者 | Contract.Pro 自身(yudao-seal-server) | 第三方客户 |
| 依赖方式 | 直接依赖 seal-biz | 依赖 seal-spring-boot-starter |
| 模式值 | mode=direct(默认值,不设置即生效) | mode=starter(Starter JAR 内置,自动生效) |
| 自动配置 | SealAutoConfiguration 不生效 | SealAutoConfiguration 生效 |
| 认证方式 | Ruoyi Security 框架 | Starter 提供的适配器(JWT/OAuth2/自定义) |
| 配置加载 | application-seal.yaml(通过 SealConfigurationLoader) | application-seal.yaml + Starter 内置 application.yml |
mode的切换是自动的:引入 Starter 依赖 → Starter JAR 里的application.yml设置了mode: starter→SealAutoConfiguration的@ConditionalOnProperty条件满足 → 自动配置生效。你不需要手动设置mode。
sql/ 目录)seal-api 和 seal-biz):<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-seal-spring-boot-starter</artifactId>
<version>${seal.version}</version>
</dependency>seal-api模块是开源的,包含所有 SPI 接口定义和标准 DTO。seal-biz和seal-spring-boot-starter是闭源的商业模块。
mode: starter 由 Starter JAR 内置配置自动设置,你不需要手动配置。你只需要根据自己的需求配置认证方式和存储方式:配置优先级:你的 application.yml> Starter 内置application.yml>application-seal.yaml(模块默认配置)。你在自己的配置文件中设置的值会覆盖 Starter 和模块的默认值。
SealAuthProvider 接口: ____ _ ____ _
/ ___| ___ __ _| | / ___| _ _ ___| |_ ___ _ __ ___
\___ \ / _ \/ _` | | \___ \| | | / __| __/ _ \ '_ ` _ \
___) | __/ (_| | | ___) | |_| \__ \ || __/ | | | | |
|____/ \___|\__,_|_| |____/ \__, |___/\__\___|_| |_| |_|
|___/
:: Seal电子印章系统 :: (v2.0.0)
Seal 模块配置信息:
- 集成模式: starter (Starter自动配置已启用)
- 认证方式: jwt
- 存储方式: localseal-api 模块,开源):| 接口 | 说明 | 内置实现 |
|---|---|---|
SealAuthProvider | 认证提供者,从 SealAuthContext 中提取用户信息 | JwtAuthAdapter、OAuth2AuthAdapter、RuoyiAuthAdapter |
SealStorageProvider | 文件存储,管理合同 PDF / 印章图片等文件 | LocalStorageAdapter、OssStorageAdapter、MinioStorageAdapter、RuoyiFileClientAdapter |
SealUserValidator | 用户验证器,校验 userId 是否存在且可用 | RuoyiUserValidator、NoOpUserValidator |
SealQuotaValidator | 配额验证器,校验签署 配额是否充足 | RuoyiQuotaValidator、NoOpQuotaValidator |
SealSignTaskApi | 签署任务 API,可在代码中直接调用(创建任务、查询状态、下载文件) | 框架内置实现 |
| 适配器 | 装配条件 | 适用场景 |
|---|---|---|
JwtAuthAdapter | yudao.seal.auth.type=jwt | 标准 JWT Token 认证,从 Authorization: Bearer {jwt} 提取,JWT Payload 需包含 userId、tenantId |
OAuth2AuthAdapter | yudao.seal.auth.type=oauth2 | Spring Security OAuth2 项目,从 SecurityContextHolder 获取认证信息 |
RuoyiAuthAdapter | classpath 中存在 SecurityFrameworkUtils 类时自动启用 | Ruoyi-Vue-Pro 框架项目,直接从 Ruoyi 的 SecurityContext 获取 LoginUser |
| 自定义 | 实现 SealAuthProvider 接口并注册为 @Component | 以上都不满足时,自行实现认证逻辑 |
注意: RuoyiAuthAdapter的装配条件是@ConditionalOnClass(检测 classpath),不是配置项。如果你的项目引入了 Ruoyi Security 模块,它会自动生效,优先级高于配置的 type。
| 适配器 | 装配条件 | 说明 |
|---|---|---|
LocalStorageAdapter | yudao.seal.storage.type=local | 本地磁盘存储,适合开发测试 |
OssStorageAdapter | yudao.seal.storage.type=oss | 阿里云 OSS,需配置 endpoint / accessKeyId / accessKeySecret / bucketName |
MinioStorageAdapter | yudao.seal.storage.type=minio | MinIO 对象存储,支持私有化部署,自动创建 Bucket |
RuoyiFileClientAdapter | 手动注入(需要 Ruoyi 的 FileClient Bean) | 复用 Ruoyi 框架的文件存储体系(支持 S3、FTP、SFTP、DB 等) |
| 对比项 | API 对接 | SDK 对接(Spring Boot Starter) |
|---|---|---|
| 集成方式 | HTTP RESTful 调用远程服务 | Maven 依赖,嵌入你的应用进程 |
| 认证处理 | 自行管理 AppKey/SecretKey/Token | SPI 接口自动适配你的认证体系 |
| 数据存储 | 数据在 Contract.Pro 平台 | 数据在你自己的数据库 |
| 文件存储 | 由平台管理 | 你自己选择存储方式(本地/OSS/MinIO) |
| 签署页面 | 使用 seal-core(不变) | 使用 seal-core(不变) |
| 适用语言 | 任何语言(HTTP 调用) | 仅 Java(Spring Boot 2.7.x) |
| 扩展性 | 受限于 API 能力 | 可深度定制(5 个 SPI 接口可扩展) |
| 数据隔离 | 按 AppKey 隔离 | 按你的租户体系隔离(tenantId) |
| 运维 | 无需运维签署服务 | 需要自行运维(数据库、Redis、存储) |
SealSignTaskApi):SealSignTaskApi 调用签署能力,无需走 HTTP:GET /actuator/health/seal 可查看 Seal 模块状态examples/ 目录下提供了 5 个开箱即用的示例项目:| 示例 | 难度 | 认证方式 | 文件存储 | 适用场景 |
|---|---|---|---|---|
example-minimal | ⭐ | JWT | 本地 | 快速验证,3 分钟启动 |
example-springboot | ⭐⭐ | JWT | 阿里云 OSS | 标准 Spring Boot 生产项目 |
example-ruoyi | ⭐⭐ | Ruoyi(自动检测) | Ruoyi FileClient | Ruoyi-Vue-Pro 项目无缝集成 |
example-microservice | ⭐⭐⭐ | OAuth2 | OSS | Spring Cloud 微服务架构 |
example-docker | ⭐⭐ | JWT | 本地/OSS | Docker Compose 一键部署 |
详细的 SDK 集成指南请参考 COMMERCIAL_INTEGRATION_GUIDE.md,示例项目说明请参考examples/README.md。
examples/example-docker/ 中的 Docker Compose 示例快速 搭建一套完整环境进行评估。私有化部署方案请联系商务团队:shawn@leepm.com
你有自己的业务系统,想嵌入签署能力?
└─ 是 → 你的项目是 Spring Boot 吗?
│ └─ 是 → 方式二:SDK 对接(Spring Boot Starter,最省事)
│ └─ 否 → 方式一:API 对接(通用方案,支持任何语言)
└─ 否 → 你需要完全自主可控?
└─ 是 → 方式三:私有化部署
└─ 否 → 直接使用 Contract.Pro 平台即可,无需对接本文档后续内容以「方式一:API 对接」为主。SDK 对接的详细指南请参考 COMMERCIAL_INTEGRATION_GUIDE.md和examples/README.md。
https://your-domain.com/adminseal:api-key:create、seal:template:create 等权限如果你是第三方开发者,请联系 Contract.Pro 的运营方为你开通管理后台账号并分配相应权限。
HR系统对接、CRM集成),用于标识这组密钥的用途| 字段 | 格式示例 | 说明 |
|---|---|---|
| AppKey | ak_xxxxxxxxxxxxxxxx | API 密钥标识,可多次查看 |
| SecretKey | sk_xxxxxxxxxxxxxxxx | API 密钥密码,仅创建时展示一次 |
⚠️ 重要提醒: SecretKey 仅在创建时展示一次,之后无法再次查看。请在创建后立即复制并妥善保存到安全的地方(如密钥管理系统、加密配置文件)。如果遗失,只能删除后重新创建。
| 状态值 | 说明 | 影响 |
|---|---|---|
| 0 | 启用(默认) | 正常调用 API |
| 1 | 禁用 | 所有使用该密钥的请求将返回 API_KEY_DISABLED 错误 |
| 字段 | 说明 |
|---|---|
| templateId | 模板 ID(数字),创建签署任务时需要传入 |
| 表单字段名列表 | 模板中定义的可填充字段名,用于 formData 参数 |
| 签署方列表 | 模板中定义的签署方角色名(如 「甲方」「乙方」),用于 participants.signatoryName 参数 |
模板中的表单字段名和签署方角色名,在调用 API 创建签署任务时需要精确匹配。建议在模板创建完成后,记录这些信息供开发时使用。
| 格式 | 示例 | 说明 |
|---|---|---|
| 单个 IP | 203.0.113.50 | 精确匹配一个 IP |
| CIDR 网段 | 203.0.113.0/24 | 匹配一个网段内的所有 IP |
如果不配置 IP 白名单,则不限制来源 IP(所有 IP 均可访问)。生产环境强烈建议配置。
| 要求 | 说明 |
|---|---|
| 协议 | 建议 HTTPS,支持 HTTP |
| 方法 | POST |
| 响应时间 | 必须在 10 秒内返回 HTTP 2xx |
| 公网可达 | 回调地址必须能被 Contract.Pro 服务器访问到 |
Webhook 配置可以在创建签署任务时通过 callbackUrl参数指定(任务级别),也可以通过 API 配置全局 Webhook。详见 Webhook 回调 章节。
✅ 拥有管理后台账号,且有 API 密钥管理权限
✅ 已创建 API 密钥,拿到 AppKey(ak_xxx)和 SecretKey(sk_xxx)
✅ 已创建合同模板,拿到 templateId
✅ 已记录模板中的表单字段名和签署方角色名
✅ (可选)已配置 IP 白名单
✅ (可选)已准备好 Webhook 回调接口
✅ 确认你的服务器能访问 Contract.Pro 的 Open API 地址Step 1. 选择认证方式 → 简单模式 / Token 模式 / 签名模式(三选一)
Step 2. 创建签署任务 → POST /api/v1/seal/sign-tasks
Step 3. 嵌入签署页面 → 将响应中的 signUrl 嵌入 iframe / WebView
Step 4. 接收签署结果 → Webhook 回调 或 主动轮询
Step 5. 下载签署文件 → GET /api/v1/seal/sign-tasks/{taskId}/download注意: templateId和signatoryName必须与管理后台创建的模板一致,否则会报错。
| 模式 | 安全级别 | 适用场景 | 前置条件 |
|---|---|---|---|
| 简单模式 | ★★☆ | 测试、内网系统 | AppKey + SecretKey |
| Token 模式 | ★★★ | 生产环境推荐 | AppKey + SecretKey |
| 签名模式 | ★★★★ | 高安全要求(金融等) | AppKey + SecretKey + 签名算法实现 |
三种模式都需要先在管理后台创建 API 密钥(见 前置条件二)。
| Header 名 | 必填 | 示例值 | 说明 |
|---|---|---|---|
Seal-Api-Key | 是 | ak_xxxxxxxxxxxxxxxx | 管理后台创建的 AppKey |
Seal-Secret-Key | 是 | sk_xxxxxxxxxxxxxxxx | 管理后台创建的 SecretKey |
POST /api/v1/seal/auth/token
Content-Type: application/x-www-form-urlencoded| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| apiKey | string | 是 | 管理后台创建的 AppKey(ak_xxx 格 式) |
| secretKey | string | 是 | 管理后台创建的 SecretKey(sk_xxx 格式) |
| nonce | string | 是 | 随机字符串(如 UUID),防重放攻击,10 分钟内不可重复 |
{
"code": 0,
"data": {
"accessToken": "eyJhbGciOiJIUzI1NiJ9...",
"tokenType": "Bearer",
"expiresIn": 300
}
}| 响应字段 | 说明 |
|---|---|
| accessToken | 访问令牌,后续请求使用 |
| tokenType | 令牌类型,固定为 Bearer |
| expiresIn | 有效期(秒),默认 300 秒(5 分钟) |
| Header 名 | 必填 | 示例值 | 说明 |
|---|---|---|---|
Seal-Token | 是 | eyJhbGciOiJIUzI1NiJ9... | Step 1 获取的 accessToken |
| Header 名 | 必填 | 示例值 | 说明 |
|---|---|---|---|
Seal-Api-Key | 是 | ak_xxxxxxxxxxxxxxxx | 管理后台创建的 AppKey |
Seal-Sign | 是 | 5A8F3D2E1B4C7A9F... | 请求参数签名(大写 MD5) |
Seal-Timestamp | 是 | 1708000000 | 当前时间戳(秒),签名有效期 5 分钟 |
1. 收集所有请求参数(Query 参数 + Seal- 开头的请求头)
2. 按参数名 ASCII 字典序排序
3. 拼接为 key1=value1&key2=value2&...&key=sk_xxx(末尾拼接 SecretKey)
4. 对拼接字符串计算 MD5,转大写 → 即为签名值Seal-Timestamp),超时返回签名无效notifyChannel 字段控制平台是否自动发送短信通知给签署人。| 值 | 说明 | 行为 |
|---|---|---|
platform(默认) | 由平台通知 | 创建任务后,平台自动发送短信给所有签署人,短信中包含签署短链接 |
caller | 由调用方通知 | 平台不发送任何短信,调用方通过 GET /sign-tasks/{taskId}/sign-links 获取签署链接后自行通知 |
| 场景 | 推荐值 | 原因 |
|---|---|---|
| 快速集成,不想处理通知逻辑 | platform | 开箱即用,签署人自动收到短信 |
| 有自己的通知渠道(企业微信、钉钉、邮件等) | caller | 完全控制通知体验和内容 |
| 需要自定义短信内容 | caller | 平台短信模板固定,自行发送可自定义 |
| 内部系统,签署人通过系统内跳转 | caller | 无需短信,直接在系统内嵌入签署页面 |
caller 模式的完整流程:1. 创建签署任务时设置 notifyChannel: "caller"
2. 从创建响应中获取各参与人的 signUrl
3. 通过你自己的渠道将 signUrl 发送给签署人
4. 签署人点击链接完成签署{
"name": "劳动合同",
"templateId": 1,
"notifyChannel": "caller",
"participants": [
{
"signatoryName": "甲方",
"userName": "张三",
"userMobile": "13800138000"
}
]
}注意:即使设置 notifyChannel: "caller",签署过程中的状态变更通知(如签署完成)仍由平台发送。notifyChannel仅控制创建任务时的初始邀请通知。
POST /api/v1/seal/sign-taskstemplateId{
"name": "XX公司劳动合同",
"templateId": 1024,
"deadline": "2026-03-01 00:00:00",
"formData": {
"employeeName": "李四",
"salary": "15000",
"startDate": "2026-03-01"
},
"participants": [
{
"signatoryName": "甲方(公司)",
"type": "enterprise",
"companyName": "XX科技有限公司",
"userName": "王总",
"userMobile": "13900139000"
},
{
"signatoryName": "乙方(员工)",
"type": "personal",
"userName": "李四",
"userMobile": "13800138000"
}
],
"signSecurityLevel": 0,
"notifyChannel": "platform",
"callbackUrl": "https://your-system.com/webhook/sign"
}| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| name | string | 是 | - | 任务名称,用于展示和检索 |
| templateId | long | 是 | - | 合同模板 ID(管理后台创建模板后获得) |
| deadline | string | 否 | 无 | 截止时间,格式 yyyy-MM-dd HH:mm:ss,超时自动过期 |
| formData | object | 否 | 无 | 模板表单填充数据,key 必须与模板中定义的字段名一致 |
| participants | array | 是 | - | 签署参与人列表,至少 1 人 |
| signSecurityLevel | int | 否 | 0 | 0-快捷签署(点链接直接签),1-登录签署(需登录后签) |
| notifyChannel | string | 否 | platform | 通知策略,详见 通知策略 |
| callbackUrl | string | 否 | 无 | 单任务回调地址(优先级高于全局 Webhook) |
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| signatoryName | string | 是 | 签署方角色名称,必须与模板中定义的签署方名称一致(如「甲方」「乙方」) |
| type | string | 否 | personal(个 人,默认)或 enterprise(企业) |
| companyName | string | 条件必填 | 企业名称,type=enterprise 时必须填写 |
| userName | string | 是 | 签署人真实姓名 |
| userMobile | string | 是 | 签署人手机号(用于身份匹配和通知) |
| signatoryId | long | 否 | 模板签署方 ID,用于精确匹配模板中的签署位(不传则按 signatoryName 匹配) |
{
"code": 0,
"data": {
"taskId": 1024,
"name": "XX公司劳动合同",
"status": 2,
"statusName": "签署中",
"needFormFilling": false,
"deadline": "2026-03-01 00:00:00",
"createTime": "2026-02-12 10:30:00",
"participants": [
{
"participantId": 1,
"signatoryName": "甲方(公司)",
"type": "enterprise",
"userName": "王总",
"userMobile": "139****9000",
"status": 0,
"signUrl": "https://seal.example.com/s/abc123"
},
{
"participantId": 2,
"signatoryName": "乙方(员工)",
"type": "personal",
"userName": "李四",
"userMobile": "138****8000",
"status": 0,
"signUrl": "https://seal.example.com/s/def456"
}
]
}
}手机号在响应中自动脱敏(中间 4 位替换为 ****)。signUrl可直接嵌入 iframe 或在 WebView 中打开。
| 错误 | 原因 | 解决方案 |
|---|---|---|
| 合同模板ID不能为空 | 未传 templateId | 检查请求体 |
| 模板不存在 | templateId 不正确 | 在管理后台确认模板 ID |
| 签署方角色名称不匹配 | signatoryName 与模板不一致 | 在管理后台查看模板的签署方配置 |
| 签署参与人列表不能为空 | participants 为空 | 至少传入 1 个参与人 |
GET /api/v1/seal/sign-tasks/{taskId}| 参数 | 类型 | 说明 |
|---|---|---|
| taskId | long | 签署任务 ID(创建任务时返回的 taskId) |
{
"code": 0,
"data": {
"taskId": 1024,
"name": "XX公司劳动合同",
"status": 3,
"statusName": "已完成",
"createTime": "2026-02-12 10:30:00",
"signedFileUrl": "https://oss.example.com/signed/contract-1024.pdf",
"participants": [
{
"participantId": 1,
"signatoryName": "甲方(公司)",
"userName": "王总",
"status": 1,
"signTime": "2026-02-12 11:00:00"
}
]
}
}| status | 说明 | 可执行操作 |
|---|---|---|
| 2 | 签署中 | 可撤销、可获取签署链接 |
| 3 | 已完成(所有人签署完毕) | 可下载签署文件 |
| 4 | 已撤销 | 无 |
| 5 | 已拒签 | 无 |
| 6 | 已过期 | 无 |
| 7 | 表单填写中 | 等待表单填写完成 |
| status | 说明 |
|---|---|
| 0 | 待签署 |
| 1 | 已签署 |
| 2 | 已拒签 |
POST /api/v1/seal/sign-tasks/{taskId}/cancel{ "code": 0, "data": true }GET /api/v1/seal/sign-tasks/{taskId}/sign-linksnotifyChannel: "caller" 模式下,获取链接后通过自己的渠道发送{
"code": 0,
"data": [
{
"participantId": 2,
"signatoryName": "乙方(员工)",
"userName": "李四",
"status": 0,
"signUrl": "https://seal.example.com/s/new-link-789"
}
]
}已签署的参与人不会出现在响应中。
GET /api/v1/seal/sign-tasks/{taskId}/download{
"code": 0,
"data": "https://oss.example.com/signed/contract-1024.pdf"
}返回的 URL 为 OSS 预签名地址,有一定有效期。建议获取后尽快下载或转存。
| 方式 | 配置方法 | 生效范围 | 优先级 |
|---|---|---|---|
| 任务级别 | 创建签署任务时传入 callbackUrl 参数 | 仅对该任务生效 | 高 |
| 全局级别 | 调用 Webhook 配置 API | 对该 AppKey 下所有任务生效 | 低 |
如果同时配置了两种,任务 级别的 callbackUrl优先。
POST /api/v1/seal/webhooks
Content-Type: application/json{
"callbackUrl": "https://your-system.com/webhook/seal",
"secret": "your-hmac-secret",
"subscribedEvents": "sign_completed,sign_rejected,sign_cancelled"
}| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| callbackUrl | string | 是 | 回调地址,建议 HTTPS |
| secret | string | 否 | HMAC-SHA256 签名密钥,为空则系统自动生成(建议自行指定) |
| subscribedEvents | string | 否 | 订阅事件(逗号分隔),为空则订阅全部事件 |
GET /api/v1/seal/webhooksDELETE /api/v1/seal/webhooks| 事件 | 说明 | 触发时机 |
|---|---|---|
sign_completed | 签署完成 | 所有参与人完成签署 |
sign_rejected | 签署拒绝 | 任一参与人拒签 |
sign_cancelled | 签署撤销 | 发起人撤销任务 |
| Header | 说明 |
|---|---|
Content-Type | application/json |
X-Seal-Signature | HMAC-SHA256 签名(用于验证请求来源) |
X-Seal-Event | 事件类型(如 sign_completed) |
X-Seal-Timestamp | 时间戳(毫秒) |
{
"eventType": "sign_completed",
"taskId": 1024,
"taskName": "XX公司劳动合同",
"status": 3,
"timestamp": 1707724800000,
"signedFileUrl": "https://oss.example.com/signed/contract-1024.pdf"
}signedFileUrl仅在sign_completed事件中返回。
X-Seal-Signature。secret 对请求体(原始 JSON 字符串)进行 HMAC-SHA256 计算,与 X-Seal-Signature 比对。| 次数 | 延迟 | 说明 |
|---|---|---|
| 第 1 次重试 | 1 分钟后 | 首次失败后 |
| 第 2 次重试 | 5 分钟后 | 指数退避 |
| 第 3 次重试 | 30 分钟后 | 最后一次 |
GET /api/v1/seal/sign-tasks/{taskId} 主动轮询最终状态作为兜底方案。signUrl,将此 URL 嵌入你的系统即可。signUrlallow="camera; microphone"用于支持人脸识别等高级验证场景。
signSecurityLevel 控制签署人的验证方式:| 级别 | 值 | 用户体验 | 适用场景 |
|---|---|---|---|
| 快捷签署 | 0 | 点击链接直接进入签署页,无需登录 | 内部合同、低风险场景 |
| 登录签署 | 1 | 需要登录 + 实名认证后才能签署 | 外部合同、高安全要求 |
AUTH_IP_NOT_ALLOWED 错误| 维度 | 限制 | 说明 |
|---|---|---|
| 单接口 | 10 req/s | 每个 AppKey 对单个接口的请求频率 |
| 全局 | 50 req/s | 每个 AppKey 的总请求频率 |
AUTH_RATE_LIMIT_EXCEEDED 错误(HTTP 429)。建议客户端实现指数退避重试。nonce 参数在 10 分钟内不可重复使用,防止请求被截获后重放。{
"code": 0,
"msg": "",
"data": {}
}code = 0:成功code != 0:失败,msg 包含错误描述| code | 说明 | 常见原因 | 处理建议 |
|---|---|---|---|
| 0 | 成功 | - | - |
| 400 | 请求参数错误 | 缺少必填字段、格式不正确 | 检查请求体字段 |
| 401 | 认证失败 | Token 无效/过期、AppKey/SecretKey 错误 | 检查凭证,重新获取 Token |
| 403 | 无权限 | 任务不属于当前 AppKey、IP 不在白名单 | 检查数据归属和 IP 配置 |
| 404 | 资源不存在 | taskId 不存在或已被删除 | 检查 taskId |
| 429 | 请求频率超限 | 超过限流阈值 | 降低请求频率,实现退避重试 |
| 500 | 服务器内部错误 | 系统异常 | 联系技术支持 |
| 错误标识 | 说明 | 处理建议 |
|---|---|---|
API_KEY_NOT_EXISTS | AppKey 不存在 | 检查 Seal-Api-Key header 值是否正确 |
API_KEY_DISABLED | AppKey 已被禁用 | 联系管理员在后台启用 |
AUTH_TOKEN_INVALID | Token 无效或已过期 | 重新调用 /auth/token 获取新 Token |
AUTH_SIGNATURE_INVALID | 签名验证失败 | 检查签名算法实现和 SecretKey |
AUTH_IP_NOT_ALLOWED | IP 不在白名单 | 联系管理员添加你的服务器 IP |
AUTH_RATE_LIMIT_EXCEEDED | 请求频率超限 | 降低请求频率 |
AUTH_PARAM_MISSING | 缺少认证参数 | 检查是否携带了认证 Header |
pip install requests,已获取 AppKey、SecretKey、templateIdtemplateId。如果还没有模板,需要先创建。详见 前置条件三。| 场景 | 推荐模式 |
|---|---|
| 测试阶段、快速验证 | 简单 模式 |
| 生产环境 | Token 模式(推荐) |
| 金融、法律等高安全场景 | 签名模式 |
POST /api/v1/seal/auth/token 获取新 Token。建议在过期前 1 分钟刷新。Token 有效期 5 分钟(300 秒)。notifyChannel 参数:caller,平台不会发短信,需要你自己获取签署链接并通知签署人platform(或不传),平台会自动发短信platform 模式仍未收到,请检查手机号是否正确sign_completed 事件(推荐,实时性好)GET /sign-tasks/{taskId} 查看 status 是否变为 3GET /sign-tasks/{taskId}/sign-links 重新获取。templateId 引用。后续版本将支持直接上传 PDF。participants 中的 signatoryName 必须与模板中定义的签署方名称完全一致。请在管理后台查看模板的签署方配置,确认角色名称(如「甲方」「乙方」)是否匹配。Seal-Api-Key header 的值是否正确。确认:ak_xxxSeal-Api-Key(注意大小写和连字符)https://your-domain.com/doc.html