链接有效性与动态轮换策略
每次成功调用该接口,都会自动轮换该签署人的专属链接,并立即使该签署人之前获得的有效旧链接失效。请调用端获取后直接交付签署人或按需即时生成,切勿在日志中明文打印签署 URL。
请求头 (Request Headers)
本接口无特殊请求头,仅需携带标准公共请求头(无需 Idempotency-Key)。详细标头定义与 HMAC-SHA256 签名算法请参阅:公共请求头与验签规范。
请求体参数 (Request Body)
| 参数名 |
类型 |
必填 |
详细描述 |
| document_id |
string |
必填 |
签署中的文档唯一 UUID v4。 |
| signer_id |
string |
必填 |
文档详情中返回的签署人节点唯一标识(即 recipients[].recipient_id),必须为待签署状态的角色节点。
|
请求示例 (Request Example)
curl -X POST "https://api.example.com/open/documents/signUrl" \
-H "Content-Type: application/json" \
-H "X-Api-Access-Key: ak_live_d83e201048b94103" \
-H "X-Api-Timestamp: 1789461000000" \
-H "X-Api-Nonce: 00112233445566778899aabbccddeeff" \
-H "X-Api-Signature: SIGNATURE_BASE64" \
-H "X-Api-Enterprise-Id: 1002" \
-d '{
"document_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"signer_id": "0a0549da-9e8d-4b6f-b0f6-d422842f0d18"
}'
<?php
use DsignSdk\DsignClient;
$client = new DsignClient([
'base_url' => 'https://api.example.com',
'access_key' => 'ak_live_d83e201048b94103',
'secret_key' => 'sk_live_948f2038102941029',
'enterprise_id' => '1002',
]);
$result = $client->documents->signUrl([
'document_id' => '7c9e6679-7425-40de-944b-e07fc1f90ae7',
'signer_id' => '0a0549da-9e8d-4b6f-b0f6-d422842f0d18',
]);
echo "签署链接: " . $result['sign_url'];
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.UUID;
public class SignUrlDemo {
public static void main(String[] args) throws Exception {
String accessKey = "ak_live_d83e201048b94103";
String secretKey = "sk_live_948f2038102941029";
String enterpriseId = "1002";
long timestampMs = System.currentTimeMillis();
String nonce = UUID.randomUUID().toString().replace("-", "");
String jsonBody = "{\n" +
" \"document_id\": \"7c9e6679-7425-40de-944b-e07fc1f90ae7\",\n" +
" \"signer_id\": \"0a0549da-9e8d-4b6f-b0f6-d422842f0d18\"\n" +
"}";
String signature = DsignSigner.buildSignature(
secretKey, "POST", "/open/documents/signUrl", "", jsonBody,
timestampMs, nonce, enterpriseId, ""
);
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/open/documents/signUrl"))
.header("Content-Type", "application/json; charset=utf-8")
.header("X-Api-Access-Key", accessKey)
.header("X-Api-Timestamp", String.valueOf(timestampMs))
.header("X-Api-Nonce", nonce)
.header("X-Api-Signature", signature)
.header("X-Api-Enterprise-Id", enterpriseId)
.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("HTTP 状态码: " + response.statusCode());
System.out.println("签署链接响应: " + response.body());
}
}
import requests, json
resp = requests.post("https://api.example.com/open/documents/signUrl",
headers=headers,
data=json.dumps({
"document_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"signer_id": "0a0549da-9e8d-4b6f-b0f6-d422842f0d18"
})
)
print(resp.json())
const axios = require('axios');
axios.post('https://api.example.com/open/documents/signUrl', {
document_id: '7c9e6679-7425-40de-944b-e07fc1f90ae7',
signer_id: '0a0549da-9e8d-4b6f-b0f6-d422842f0d18'
}, { headers }).then(res => console.log(res.data));
响应数据结构 (Response Body)
| 字段名 |
类型 |
详细说明 |
| document_id |
string |
签署文档唯一 UUID。 |
| signer_id |
string |
签署人节点唯一 UUID。 |
| sign_url |
string |
本次生成的可供签署人点击直接打开进行电子签署的跳转短链接。
|
| expires_at |
integer |
链接失效截止时间戳(Unix 秒级,与文档有效期一致)。 |
响应示例 (Response Example)
{
"code": 0,
"message": "success",
"data": {
"document_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"signer_id": "0a0549da-9e8d-4b6f-b0f6-d422842f0d18",
"sign_url": "https://example.com/u/AbCdEf",
"expires_at": 1790000000
},
"request_id": "req_68dfb7829a10ef4"
}
相关错误码 (Error Codes)
全部公共状态码与安全拦截说明请参阅:全局错误码字典 (Error Codes)。
| HTTP 状态 |
错误码 (code) |
错误标识 (Constant) |
产生原因与排查指引 |
| 404 |
40401 |
NOT_FOUND |
文档或签署人 ID 不存在、已作废,或该签署人已完成签署。 |
| 409 |
40901 |
RESOURCE_CONFLICT |
文档当前状态非 in_progress 签署中,无法签发签署链接。 |