Appearance
凭预授权 Token 签名
POST
/openapi/v3/esign/sign-grants/sign
预授权签署(两步调用)的第二步:携创建预授权意愿后取得的额度 Token(grantToken),对文件摘要同步签名——签名值随本接口响应直接返回,无需终端用户逐次确认,不设签名结果回调,也无需轮询查询意愿结果。
额度按调用次数扣减(有限次数);不限次数不扣减
有限次数预授权(usageLimitEnable=true):一次调用扣减 1 次额度,与本次携带的 files 文件数无关,剩余额度随响应 usageRemaining 返回,也可经查询预授权状态对账。
不限次数预授权(usageLimitEnable=false,2026-09-04 新增):不扣减次数、只校验额度状态与有效期,同一 Token 在有效期内可并发、反复签名;响应不含 usageRemaining,勿把该字段缺失当作剩余 0。
本接口是签名接口,不返回 usageLimitEnable:次数模式在创建预授权时已定,请以查询预授权状态、查询意愿结果或预授权完成回调中的 usageLimitEnable 为准。
X-ES-Request-ID 必填
本接口为幂等创建类接口,请求头必须携带 X-ES-Request-ID 作为幂等键。同一幂等键重试会复用首次的签名结果,不会重复扣减额度;同一幂等键携带不同的请求体重试会被上游终态拒绝(HTTP 409)。
Body 参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| grantToken | string | 是 | 预授权额度 Token。终端用户完成授权后由云签交付 CertCloud(预授权完成回调 + 意愿查询双通道),调用方经领取预授权 Token按 grantId 拉取。请按敏感凭据管理,勿记录到日志 |
| certId | string | 是 | 云签证书 ID,须与预授权时一致 |
| signTaskId | string | 是 | 签署任务号,须与预授权时一致(非 CertCloud 订单号,见创建预授权意愿)。2026-08-03 起由 orderNo 更名而来,旧名不再接受 |
| signerId | string | 是 | 签署人 ID,须与预授权时一致 |
| files | array | 是 | 待签署文件列表 |
| files[].fileName | string | 否 | 文件名,用于存证及结果对应 |
| files[].dataHash | string | 是 | 文件摘要(十六进制小写),必须使用本请求 hashAlg 声明的算法计算。SM2 证书须提交 e 值(e = SM3(Z_A ‖ 文件原文)),而非裸 SM3(文件原文);RSA 证书即 SHA256/384/512(文件原文)。见下方说明与签名数据格式与验签 |
| hashAlg | string | 是 | 摘要算法:SM3 / SHA256 / SHA384 / SHA512。必须与证书密钥类型匹配——SM2 证书仅支持 SM3,RSA 证书仅支持 SHA 族 |
SM2 证书的 dataHash 不是裸 SM3(文件原文)
SM2 签名的输入是 GM/T 0003 定义的 e 值,dataHash 必须按下列两步计算:
- 按 GM/T 0009 计算
Z_A——输入为默认用户标识1234567812345678、SM2 曲线参数与签名者证书公钥坐标; e = SM3(Z_A ‖ 文件原文),取十六进制小写作为dataHash。
直接提交 SM3(文件原文) 时,本接口与云签都会正常返回签名成功,但该签名值事后用证书公钥验不过——问题只会在验签或出证环节暴露。两侧校验都只看格式、不看口径,长度合法即放行。请在联调阶段先自验一次,步骤见调用方验签步骤。
RSA 证书无此步骤。
响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
| grantId | string | 本次签名所用的预授权 ID,与创建预授权意愿对应的 grantId 同值;请妥善保存,见下 |
| signId | string | 本次签名记录 ID |
| certSerialNumber | string | 实际签名所用证书的序列号 |
| signatures | array | 逐文件的签名结果,顺序与请求 files 一致 |
| signatures[].fileName | string | 文件名,回显请求中的 files[].fileName;请求未传时为空字符串 |
| signatures[].dataHash | string | 文件摘要,回显请求中的 files[].dataHash(SM2 证书为提交时的 e 值) |
| signatures[].signature | string | 该文件摘要的签名值(Base64 编码) |
| usageRemaining | string | 本次扣减后的剩余可用次数(长整型一律字符串,见通用说明)。仅有限次数返回;不限次数不扣减、该字段缺省。本接口不返回 usageLimitEnable,次数模式以查询预授权状态为准 |
| signedAt | string | 签名时间(毫秒时间戳字符串) |
| tsToken | string | 签名时间戳凭据:将本批签名结果与云签侧记录的签名时间绑定,供存证留存。按不透明字符串处理,签名完成时间以 signedAt 为准。仅签名成功后返回 |
请保存响应中的 grantId
grantId 首个入口是回调 + 主动查询双通道:预授权生效时经预授权完成回调 esign:grant_ready 送达(与 Token 一并),或经查询意愿结果按创建预授权时的 willId 主动查询取得(businessStatus=SUCCEEDED 后即可,不含 Token);首次携 Token 签名成功后,本响应中也返回同一 grantId。后续查询预授权状态、领取预授权 Token与撤销预授权均以 grantId 定位,请在业务侧妥善保存。usageRemaining / signedAt 为字符串(长整型一律字符串,见通用说明)。
signature 是 Base64 原始签名值:SM2 为 ASN.1 DER SEQUENCE { r, s }(非 64 字节裸拼接)、RSA 为 PKCS#1 v1.5,解析与验签见签名数据格式与验签。
请求示例
bash
curl -X POST 'https://api.certcloud.cn/openapi/v3/esign/sign-grants/sign' \
-H 'Content-Type: application/json' \
-H 'X-CC-Auth-Key: your-auth-key' \
-H 'X-CC-Key-ID: your-key-id' \
-H 'X-ES-Request-ID: 6a1b2c3d-4e5f-6789-abcd-ef0123456789' \
-d '{
"grantToken": "<GRANT_TOKEN_PLACEHOLDER>",
"certId": "esign-cert-xxx",
"signTaskId": "task-20260721-001",
"signerId": "signer-xxx",
"files": [
{
"fileName": "contract.pdf",
"dataHash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
}
],
"hashAlg": "SM3"
}'响应示例
错误码
| HTTP 状态码 | code | 说明 |
|---|---|---|
| 400 | esign_request_id_required | X-ES-Request-ID 缺失,或其值不合规——去除首尾空白后必须非空、不超过 64 个字符,且只能由字母、数字、连字符 - 与下划线 _ 组成;空白、控制字符及其他符号(:、.、/、+、中文等)均非法 |
| 400 | esign_hash_alg_required | 缺少 hashAlg 摘要算法 |
| 400 | esign_invalid_body | 请求体非法:JSON 语法错误或字段类型不符(整数字段传字符串、字符串字段传数字等),请求体未被解析 |
| 400 | esign_invalid_request | 请求参数非法(如 grantToken 缺失、files 缺失或为空数组、certId / signTaskId / signerId 缺失) |
| 404 | esign_cert_not_found | 证书不存在 |
| 403 | esign_cross_account_denied | 证书不属于当前账户 |
| 409 | esign_upstream_rejected | 当前请求被云签终态拒绝;error 为 [上游码] 文案,仅供人工排查、不可据其编程。见上游错误响应与重试及下方回落说明 |
| 409 | esign_upstream_error | 云签暂时性失败;可使用相同 X-ES-Request-ID 稍后安全重试。见上游错误响应与重试 |
