Appearance
发起签名意愿
POST
/openapi/v3/esign/sign-wills
对指定文件的摘要发起云签署名意愿。接口返回 confirmUrl,需转发给证书归属的终端用户打开、完成人脸核验等意愿确认动作,之后再通过查询意愿结果轮询签名结果。
X-ES-Request-ID 必填
本接口为幂等创建类接口,请求头必须携带 X-ES-Request-ID 作为幂等键。同一幂等键重试会复用首次发起的意愿,不会重复发起。
Body 参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| certId | string | 是 | 云签证书 ID,可通过证书标识映射查询获取 |
| signerId | string | 否 | 签署人 ID。不传则由服务端推导为该证书的默认签署人(企业证书为经办人,个人证书为订户本人)。传值时的接受范围:个人证书必须等于订户本人 ID;企业证书可传经办人 ID,也可传当前对该证书持有生效委托授权的委托人 delegateId(由新增委托人返回,用于委托代签)。均不满足时返回 403 esign_person_not_in_scope |
| 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(兼容 SHA-256 / SHA-384 / SHA-512 带横线写法)。必须与证书密钥类型匹配——SM2 证书仅支持 SM3,RSA 证书仅支持 SHA 族;不匹配将被云签平台拒绝 |
| willDescription | string | 否 | 签署告知文案,最长 1000 字符。强烈建议传入——它是终端用户在意愿页知情「本次在签什么」的核心内容,会按固定句式展示并纳入意愿存证与审计。不传时意愿页没有业务说明 |
| allowedModes | array | 否 | 要求意愿页支持的核验方式,可选 SMS / TENCENT_SMART_WITNESS / PIN / TOTP。收紧语义:显式传入时其中每一种方式都必须对该场景与人员实际可用,任一不可用则整笔意愿创建失败;不传表示按实际可用方式全部开放。空数组、空字符串元素与汇总态 MIXED 均非法 |
| successRedirectUrl | string | 否 | 意愿完成后的跳转地址,最长 1024 字符,须为合法的 http/https 地址(否则 409 esign_upstream_rejected,上游码 [-5025])。高等级人脸核验场景下该地址会原样作为腾讯 H5 的回跳地址,腾讯完成后带 code / msg / orderNo 等参数回跳;回跳只代表页面流程结束,签名结果仍须以查询意愿结果为准 |
| endRedirectUrl | string | 否 | 意愿流程结束后的返回地址,最长 1024 字符,同样须为合法的 http/https 地址 |
| pageOptions | object | 否 | 意愿页展示选项,见下 |
| pageOptions.language | string | 否 | 页面语言,封闭枚举:zh-CN / zh-HK / en / jp,其他取值被云签拒绝(-1002)。⚠️ 当前传入不改变页面语言——意愿页服务端文案、错误提示与协议正文恒为中文,多语言渲染未实现,该字段现阶段仅透传留痕 |
| pageOptions.themeColor | string | 否 | 主题色,#RRGGBB 形式 |
| pageOptions.hideHeader | boolean | 否 | 是否隐藏页面头部 |
SM2 证书的 dataHash 不是裸 SM3(文件原文)
SM2 签名的输入是 GM/T 0003 定义的 e 值,dataHash 必须按下列两步计算:
- 按 GM/T 0009 计算
Z_A——输入为默认用户标识1234567812345678、SM2 曲线参数与签名者证书公钥坐标; e = SM3(Z_A ‖ 文件原文),取十六进制小写作为dataHash。
直接提交 SM3(文件原文) 时,本接口与云签都会正常返回签名成功,但该签名值事后用证书公钥验不过——问题只会在验签或出证环节暴露。两侧校验都只看格式、不看口径,长度合法即放行。请在联调阶段先自验一次,步骤见调用方验签步骤。
RSA 证书无此步骤。
allowedModes 参与幂等,其余可选字段不参与
allowedModes 决定终端用户被要求「怎么核验」,属于请求语义的一部分:复用同一 X-ES-Request-ID 但改动 allowedModes,会返回 409 esign_idempotency_conflict,须换新的幂等键。
willDescription、两个跳转地址与 pageOptions 只影响页面展示,不参与幂等指纹:同一幂等键改动这些字段重试,会回放首次创建的意愿(连同首次的文案与跳转地址),不会创建新意愿、也不会报错。需要新的文案请换新的 X-ES-Request-ID。
pageOptions 的取值不在 CertCloud 侧校验
language 与 themeColor 的具体取值由云签平台校验,CertCloud 原样透传。取值不受支持时返回 409 esign_upstream_rejected。
响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
| willId | string | 意愿 ID,用于经查询意愿结果按 willId 轮询签名结果 |
| confirmUrl | string | 转发给证书归属的终端用户(签署人)打开、完成意愿确认的一次性链接,规则同意愿模型说明(云签域名、原样透传、请勿缓存或记录日志) |
| expireAt | string | 意愿过期时间(毫秒时间戳字符串,长整型一律字符串,见通用说明)。超过该时间后意愿转为过期终态 |
| willStatus | string | 意愿当前状态,创建成功后通常为待确认态 PENDING;取值见查询意愿结果 |
请求示例
bash
curl -X POST 'https://api.certcloud.cn/openapi/v3/esign/sign-wills' \
-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: 8f14e45f-ceea-4d1a-9a0c-6f6a3b1f0a11' \
-d '{
"certId": "esign-cert-xxx",
"files": [
{
"fileName": "contract.pdf",
"dataHash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
}
],
"hashAlg": "SM3",
"willDescription": "您正在签署《2026 年度采购合同》,共 1 份文件",
"allowedModes": ["SMS", "PIN"],
"successRedirectUrl": "https://your-app.example.com/sign/done"
}'上例只用到常用的三个可选字段。全部可选字段一并传入时的请求体形态:
json
{
"certId": "esign-cert-xxx",
"signerId": "signer-xxx",
"files": [
{ "fileName": "contract.pdf", "dataHash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08" },
{ "fileName": "appendix.pdf", "dataHash": "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b" }
],
"hashAlg": "SM3",
"willDescription": "您正在签署《2026 年度采购合同》及附件,共 2 份文件",
"allowedModes": ["SMS", "PIN"],
"successRedirectUrl": "https://your-app.example.com/sign/done",
"endRedirectUrl": "https://your-app.example.com/sign/exit",
"pageOptions": {
"language": "zh-CN",
"themeColor": "#1677FF",
"hideHeader": false
}
}不需要的可选字段请整个省略,不要传 null、空字符串或空数组——空数组形式的 allowedModes 会被判为非法参数(400 esign_invalid_request)。
响应示例
错误码
| 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 | 请求参数非法:files 缺失或为空数组;willDescription 超过 1000 字符;successRedirectUrl / endRedirectUrl 超过 1024 字符;allowedModes 为空数组、含空字符串或含汇总态 MIXED |
| 404 | esign_cert_not_found | 证书不存在 |
| 403 | esign_cross_account_denied | 证书不属于当前账户 |
| 403 | esign_person_not_in_scope | signerId 既不是该证书的默认签署人,也不是对该证书持有生效委托授权的委托人(委托授权已过期 / 已撤销 / 尚未生效时同样返回本码) |
| 409 | esign_idempotency_conflict | 复用同一 X-ES-Request-ID 但请求体的语义字段(certId / signerId / hashAlg / 文件摘要集合 / allowedModes)与首次发起不一致;不回放旧意愿、也不创建新意愿,请改用新的 X-ES-Request-ID。见X-ES-Request-ID 幂等键 |
| 409 | esign_upstream_rejected | 当前请求被云签终态拒绝;error 为 [上游码] 文案,仅供人工排查、不可据其编程。修正输入或证书状态后,使用新的 X-ES-Request-ID 再发起。见上游错误响应与重试 |
| 409 | esign_upstream_error | 云签暂时性失败;error 为 [上游码] 文案,仅供人工排查、不可据其编程。可使用相同 X-ES-Request-ID 稍后安全重试。见上游错误响应与重试 |
files 元素校验
CertCloud 当前仅在门面校验 files 数组必须非空;files[].dataHash 的格式与非空校验由云签平台执行。缺少或传入非法 dataHash 时,可能返回 409 esign_upstream_rejected。
