需先确认存证机构资质及接口合规性,再用hash_file('sha256')计算哈希、HMAC-SHA256签名、严格校验evidenceId与timestamp,最后叠加含查询链接的PDF水印并三层验证存证有效性。

PHP 调用区块链存证接口前,先确认你真需要链上存证
很多项目以为“上链=法律有效”,其实不是。国内司法认可的电子存证,核心是「完整证据链」+「可信时间戳」+「哈希值可验证」,不是随便调个 API 就算数。真正能被法院采信的,基本只认几家已接入最高法「司法区块链平台」的机构(如蚂蚁链、腾讯至信链、百度超级链),它们提供的是 submitEvidence 这类封装好的存证接口,不是让你自己连比特币节点。
所以第一步不是写 PHP 代码,而是:
- 确认合作存证方是否具备《电子认证服务许可证》和司法区块链节点接入资质
- 拿到他们提供的 SDK 或 REST API 文档,重点看 hashType 是否支持 sha256(法院只认这个)
- 检查返回结构里有没有 evidenceId 和 timestamp 字段——没这两个,后续无法在「人民法院司法区块链平台」官网核验
用 cURL 提交合同哈希到至信链 API 的关键写法
至信链开放平台要求你传原始合同文件的 sha256 值(不是文件本身),并签名。PHP 容易在这里翻车:
常见错误现象:401 Unauthorized(签名错)、400 Bad Request(哈希长度不对)、返回 "code":5001(时间戳超时)
实操建议:
- 哈希必须用 hash_file('sha256', $filePath) 计算,别用 md5_file 或手动读取后 hash('sha256', $content) —— 换行符、BOM 头会导致哈希不一致
- 签名用 HMAC-SHA256,密钥是平台分配的 secretKey,拼接字符串格式为 $method.$uri.$timestamp.$body(注意 body 是 JSON 字符串,不含空格)
- 请求头必须带 X-TX-Nonce(随机 8 位字符串)和 X-TX-Timestamp(秒级时间戳,误差不能超 300 秒)
- 不要用 file_get_contents 直接发 POST body,用 curl_setopt($ch, CURLOPT_POSTFIELDS, $json),否则中文会乱码
```php
$body = json_encode([
'evidenceHash' => hash_file('sha256', '/path/to/contract.pdf'),
'businessId' => 'CONTRACT_20240520_XXXX',
'fileName' => 'service_agreement_v2.pdf'
], JSON_UNESCAPED_UNICODE);
$signature = base64_encode(hash_hmac('sha256', "POST./v1/evidence/".$timestamp.$body, $secretKey, true));
```存证后怎么让合同 PDF 自动带「存证标识」水印?
用户签完合同 PDF,得让对方一眼看到「已上链存证」,否则法律效力感知弱。这不是区块链的事,是 PHP 生成 PDF 时的附加动作。
立即学习“PHP免费学习笔记(深入)”;
关键点:
- 别用 GD 库往 PDF 上画文字——GD 只处理图片,PDF 是向量格式,强行转图会失真、放大模糊
- 推荐用 setasign/fpdi + tcpdf 组合:用 FPDI 加载原 PDF,TCPDF 生成带二维码和文字的水印层,再叠加
- 二维码内容必须是存证查询地址,例如 https://ecourt.gov.cn/chain/verify?eid=xxxxx,不能是哈希值本身
- 水印位置建议加在每页右下角,透明度设为 0.15,字体用 helvetica(法院文书常用,避免用思源黑体等非预装字体导致渲染异常)
验证环节 PHP 怎么校验存证结果是否真实有效
用户上传合同后,你后台调了存证 API,但返回成功不代表链上真有记录。必须主动验证,否则出问题时甩锅无依据。
验证逻辑分两层:
- 第一层查接口:调用至信链 /v1/evidence/{evidenceId},检查返回 status === 'SUCCESS' 且 blockHeight > 0(没出块=没上链)
- 第二层核哈希:用 hash_file('sha256', $localFile) 再算一次,和返回的 evidenceHash 字符串严格比对(区分大小写)
- 第三层防篡改:把返回的 merkleRoot 和 txId 存进自己数据库,下次用户质疑时,可直接用这些值去「人民法院司法区块链平台」官网手动输入验证
- 注意:至信链接口可能返回 status === 'PENDING',这时要轮询(最多 3 次,间隔 2 秒),别一收到 pending 就告诉用户“已存证”
存证不是加个 API 调用就完事,最麻烦的是哈希一致性——本地算的、传给链的、法院平台比对的,三处必须一字不差。哪怕 PDF 里多一个空格、换行符是 \r\n 而不是 \n,哈希就全错。











