服务端调用
合同生成接口:四步接完
你只需要服务地址和授权码。先拉取可用名称,再提交生成,等待任务完成,最后领取合同成品。
授权码只能保存在你自己的后端。
不能写进网页、小程序、客户端安装包、前端代码或公开仓库。前端先请求你自己的后端,再由后端调用本接口。
- 1拉目录获取能用的模板、分组、企业和字段
- 2提交生成单个模板或整个分组二选一
- 3等结果用返回的任务编号轮询状态
- 4领成品每个文件只允许成功领取一次
全部接口
| 方法 | 地址 | 用途 |
|---|---|---|
| GET | /api/v1/catalog | 获取当前授权范围 |
| POST | /api/v1/generate | 生成单个模板或整个分组 |
| GET | /api/v1/generation-jobs/{jobId} | 查询一份合同的任务状态 |
| GET | /api/v1/generation-jobs | 查询当前授权码的历史任务 |
| GET | /api/v1/generation-files/{fileId}/download | 领取指定成品文件 |
| GET | /api/v1/generation-jobs/{jobId}/download | 领取任务的第一个成品文件 |
接入时必须遵守
- 所有名称和字段都从最新目录获取,不自己猜。
- 模板名称和分组名称只能提交一个。
- 字段直接使用中文名称,例如“剧目名称”。
- 同一笔业务始终使用同一个幂等键。
- 整组生成要保存返回的全部任务编号。
- 文件首次领取成功后立即保存,不能再次下载。
完整可运行代码
下面代码包含目录校验、单个或整组生成、状态轮询和成品保存。修改开头的模式、名称、企业和字段即可运行。
Node.js 20 及以上版本
运行方式
设置授权码并运行
# Windows PowerShell
$env:CONTRACT_API_KEY="管理员给你的完整授权码"
node contract-client.js
# Linux
CONTRACT_API_KEY="管理员给你的完整授权码" node contract-client.js
第一步:拉取目录
每次打开生成页面时调用一次。目录里有什么,你就只能展示和提交什么。
请求
响应重点
{
"groups": [
{
"name": "腾讯",
"contractCount": 2,
"fields": [
{ "key": "{剧目名称}", "label": "剧目名称", "required": true },
{ "key": "{集数}", "label": "集数", "required": true }
],
"formats": ["pdf", "image"]
}
],
"templates": [
{
"name": "腾讯-承诺函",
"groupName": "腾讯",
"fields": [
{ "key": "{剧目名称}", "label": "剧目名称", "required": true }
],
"formats": ["pdf", "image"]
}
],
"companies": [
{ "name": "示例文化科技有限公司" }
],
"catalogVersion": "e8a9e147f2e064c1"
}
| 要做什么 | 使用哪个值 |
|---|---|
| 生成单个模板 | 提交 templates[].name 为 templateName |
| 生成整个分组 | 提交 groups[].name 为 groupName |
| 选择企业 | 提交 companies[].name 为 companyName |
| 显示输入框 | 使用所选模板或分组的 fields |
| 提交字段 | 使用 fields[].label 作为字段名,最简单 |
公司名称、税号和签署日期不用提交。
这些资料由合同服务器根据所选企业自动填写。目录中没返回的字段不要提交。
第二步:提交生成
接口地址固定为 POST /api/v1/generate。单个模板和整个分组只能选择一种。
生成单个模板
生成整个分组
请求规则
| 参数 | 规则 |
|---|---|
templateName | 单个生成时必填,必须和目录名称完全一致 |
groupName | 整组生成时必填,必须和目录名称完全一致 |
companyName | 必填,必须和目录中的企业名称完全一致 |
fields | 必填;没有需要填写的字段时传空对象 {} |
outputFormat | pdf 或 image,不传时默认 PDF |
Idempotency-Key | 请求头;使用你自己的订单号,同一笔业务重试时不能更换 |
受理成功
{
"mode": "group",
"groupName": "腾讯",
"companyName": "示例文化科技有限公司",
"results": [
{ "jobId": "job_example_1", "status": "queued" },
{ "jobId": "job_example_2", "status": "queued" }
],
"total": 2,
"alreadyExists": false
}
202 表示新任务已受理;200 且 alreadyExists=true 表示相同幂等键的任务已经存在。两种情况都继续使用响应中的任务编号。
第三步:等待结果
遍历生成响应中的全部 jobId。建议等待 1 秒、2 秒、4 秒,然后每 5 秒查询一次。
查询任务
queued:排队中→running:生成中→succeeded:成功或failed:失败
| 状态 | 处理方式 |
|---|---|
queued | 继续等待,不要重复提交生成 |
running | 继续等待,不要重复提交生成 |
succeeded | 遍历响应中的 files 并领取全部文件 |
failed | 停止轮询,记录并展示 errorMessage |
成功任务响应
{
"id": "job_example_1",
"status": "succeeded",
"outputFormat": "pdf",
"errorMessage": null,
"files": [
{
"id": "file_example_1",
"fileName": "示例剧目-合同成品.pdf",
"mimeType": "application/pdf",
"fileSize": 245812
}
]
}
第四步:领取成品
每个成品文件只能成功领取一次。
服务器完整发送响应后立即删除文件,不需要另行确认。传输中断时文件会保留,可重新请求。
按文件编号领取
- PDF 通常只有一个文件,图片格式可能有多个 PNG 文件。
- 必须遍历每个成功任务的
files,再逐个领取。 - 不要先试下载再正式下载,试下载也会消耗唯一一次领取机会。
- 不要只调用任务下载地址处理多页图片,否则可能只拿到第一页。
- 同一文件正在发送时,重复请求返回 409;等待当前请求结束后再决定是否重试。
- 未领取文件最长保留 30 天;领取后立即从服务器删除。
报错怎么处理
| 状态码 | 常见原因 | 直接处理 |
|---|---|---|
400 | 缺字段、字段名错误、同时传模板和分组、企业资料缺税号 | 按 error 修正;企业资料缺失时联系管理员补资料 |
401 | 授权码错误、停用、过期或已重置 | 停止请求,换管理员提供的新授权码 |
403 | 名称不存在、已改名、未授权或格式不允许 | 立即重新拉目录;目录中没有就不能使用 |
404 | 任务不存在,或成品已被领取 | 检查任务编号;已领取文件不能恢复下载 |
409 | 名称重复、幂等任务不完整,或同一文件正在发送 | 按错误信息处理;文件发送中应等待当前请求结束 |
429 | 一分钟请求超过 10 次,或生成额度用完 | 按 Retry-After 等待;额度用完联系管理员 |
500 | 服务器临时错误 | 使用原来的幂等键重试,不能换新键 |
需要反馈问题时一次性提供这些信息
问题信息模板
发生时间:
调用接口:
HTTP 状态码:
响应 error:
任务 jobId:
模板名或分组名:
企业名称:
授权码前 7 位:
不要发送完整授权码。
权限更新
管理员新增模板、改名、改字段、调整企业权限或停用内容后,目录接口会立即反映最新结果。
- 打开生成页面时重新拉取目录。
- 页面长时间打开时,每 60 秒刷新一次目录。
- 生成返回 403 时,立即刷新目录,不要继续提交旧名称。
- 可以保存响应头
ETag,下次携带If-None-Match;返回 304 表示目录没变。 - 授权码停用、到期或重置后,下一次请求直接返回 401。
安全边界
接口能看到
- 当前授权的模板名称和分组名称。
- 当前授权的企业名称和需要填写的字段。
- 自己的任务状态、错误信息和合同成品。
接口看不到
- 模板内容、模板源文件和内部模板编号。
- 原始印章文件、印章路径和盖章坐标。
- 企业税号、账号、印章配置和服务器路径。
- 可编辑的 DOCX 成品。
成品合同中的印章本来就会显示,收件人可以截图或裁剪;系统只能保护原始印章文件不被接口下载。
旧版兼容
旧系统仍可使用 POST /api/v1/generation-jobs/batch、combinationId 和 companyId。新接入不要使用旧编号,统一调用 POST /api/v1/generate 并传名称。