本文目录导读:

在PHP项目中实现电子合同功能,通常需要结合前端签名、后端逻辑、存储与存证几个环节,以下是完整的实现思路和关键步骤:
功能需求分析
一个基本的电子合同系统需要:
- 合同模板管理:生成固定格式(如PDF)的合同
- 在线签署:支持手写签名、印章或确认勾选
- 签署验证:时间戳、哈希校验、第三方存证(可选)
- 合同存储:PDF/DOC文件储存并绑定签署记录
- 司法认可:符合《电子签名法》要求(可靠电子签名)
技术选型建议
| 模块 | 推荐技术/库 |
|---|---|
| PDF处理 | TCPDF / FPDI(免费)、PDFlib(付费) |
| 手写签名 | Signature Pad(前端JS库) |
| 电子印章 | Seal SVG / 后端生成印章图片 |
| 文件存储 | 阿里云OSS / 腾讯COS / 本地文件系统 |
| 时间戳 | 对接国家授时中心API或第三方时间戳服务 |
| 签署验证 | 计算文件SHA-256 / 对接第三方存证平台(如法大大、e签宝) |
| 前后端通信 | RESTful API + JWT认证 |
核心实现流程
1 合同创建与模板
// 使用TCPDF生成PDF合同
require_once('tcpdf/tcpdf.php');
$pdf = new TCPDF();
$pdf->AddPage();
$html = '<h1>租赁合同</h1><p>甲方:'.$partyA.',乙方:'.$partyB.'</p>';
$pdf->writeHTML($html);
$pdf->Output('contract_draft.pdf', 'F');
2 签署流程(前端)
<!-- 使用Signature Pad -->
<canvas id="signaturePad"></canvas>
<button onclick="saveSignature()">确认签署</button>
<script src="signature_pad.min.js"></script>
<script>
const canvas = document.getElementById('signaturePad');
const pad = new SignaturePad(canvas);
function saveSignature() {
const dataUrl = pad.toDataURL(); // 获取base64签名数据
fetch('save_signature.php', {
method: 'POST',
body: JSON.stringify({ signature: dataUrl, contractId: 123 })
});
}
</script>
3 后端签名处理与PDF合成
// save_signature.php
$data = json_decode(file_get_contents('php://input'), true);
$base64 = $data['signature'];
$contractId = $data['contractId'];
// 1. 保存签名图片
$img = base64_decode(explode(',', $base64)[1]);
file_put_contents("signatures/{$contractId}.png", $img);
// 2. 叠加签名到PDF(使用FPDI)
$pdf = new \setasign\Fpdi\Fpdi();
$pageCount = $pdf->setSourceFile("contracts/draft_{$contractId}.pdf");
for ($i=1; $i<=$pageCount; $i++) {
$tplIdx = $pdf->importPage($i);
$pdf->AddPage();
$pdf->useTemplate($tplIdx);
}
// 在最后一页添加签名图片
$pdf->Image("signatures/{$contractId}.png", 100, 200, 40, 20);
$pdf->Output("contracts/final_{$contractId}.pdf", 'F');
// 3. 写入签署记录
$db->insert('sign_log', [
'contract_id' => $contractId,
'signer' => $_SESSION['user_id'],
'sign_time' => date('Y-m-d H:i:s'),
'file_hash' => hash_file('sha256', "contracts/final_{$contractId}.pdf")
]);
增强司法效力(可选但推荐)
1 数字证书签名(使用开放X.509)
# 安装phpseclib composer require phpseclib/phpseclib
use phpseclib3\Crypt\RSA;
use phpseclib3\Crypt\PublicKeyLoader;
$privateKey = file_get_contents('path/to/private.pem');
$rsa = PublicKeyLoader::load($privateKey);
$pdfContent = file_get_contents('contract.pdf');
$signature = $rsa->sign($pdfContent);
file_put_contents('contract_signed.pdf', $pdfContent . "\n" . base64_encode($signature));
2 对接第三方CA(简化版)
- e签宝 / 法大大 / 契约锁:提供完整API,PHP SDK示例
// 以e签宝为例(伪代码) $tsingClient = new TsingClient($appId, $appSecret); $response = $tsingClient->createSignFlow([ 'docs' => ['templateId' => 'xxx'], 'signers' => [ ['name' => '张三', 'mobile' => '138xxxx'] ] ]);
3 法院认可的存证(区块链/哈希上链)
- 将最终PDF的SHA-256值提交到区块链存证平台(如蚂蚁链、百度超级链)
- 或使用时间戳服务(中国金融认证中心CFCA)
完整项目目录结构建议
project/
├── public/
│ ├── index.php // 合同列表
│ └── sign.php // 签署页面(含Signature Pad)
├── src/
│ ├── Controller/
│ │ └── ContractController.php
│ ├── Service/
│ │ ├── PdfService.php
│ │ └── SignService.php
│ └── Model/
│ └── Contract.php
├── templates/
│ └── contract_template.html // 合同模板
├── storage/
│ ├── drafts/ // 未签署合同
│ ├── signed/ // 已签署合同
│ └── signatures/ // 签名图片
└── vendor/ // Composer依赖
注意事项(避坑指南)
- 签名与合同内容的绑定:必须将签名图片嵌入PDF,而非单独存储,防止篡改。
- 用户身份认证:签署前强制完成实名认证(身份证/银行卡四要素/人脸识别)。
- 不可篡改性:最终PDF计算SHA-256并保存到数据库,定期比对。
- 法律风险:若需求严格司法效力,建议直接集成第三方电子签约平台(成本低、合规性高)。
- 前端签名兼容性:所有主流浏览器均支持Canvas,但移动端建议使用touch事件替代鼠标事件。
第三方集成方案(简化开发)
| 服务商 | PHP SDK | 特点 |
|---|---|---|
| 法大大 | 成熟 | 支持合同模板、自动签署 |
| e签宝 | 完善 | 支持小程序、H5签署 |
| 契约锁 | 企业级 | 本地化部署可选 |
如果预算有限且非强司法场景,用 TCPDF + Signature Pad + SHA-256 完全够用;如果需要法律认可的完整电子签约,推荐直接使用 e签宝 / 法大大 等成熟服务,PHP集成也只需调用几个HTTP接口。