PHP项目如何实现电子印章?完整开发指南与代码实践
目录导读
- 电子印章的技术原理与法律效力
- PHP实现电子印章的三种核心方案
- 基于GD库绘制自定义印章的完整代码
- 印章签章与验证的业务逻辑设计
- 常见问题问答(FAQ)
电子印章的技术原理与法律效力
在数字化办公场景中,电子印章并非简单地把图片粘贴到PDF上,根据《电子签名法》,可靠的电子印章需满足:可识别签署人身份、签署内容不可篡改、签署行为不可抵赖,实现这一目标的技术闭环包括:

- 图像生成层:使用PHP的GD库或Imagick生成圆形/椭圆形印章图片,包含单位名称、数字编号、防伪纹路
- 密码学层:对印章图片进行哈希处理,结合RSA/国密SM2算法生成数字签名
- 绑定层:将数字签名嵌入PDF或图片的元数据(如Exif、PDF注释)
PHP项目要实现电子印章,核心是解决“如何生成带防伪特征的印章图片”以及“如何将印章与文件绑定并验证”。
PHP实现电子印章的三种核心方案
| 方案 | 适用场景 | 技术栈 | 复杂度 |
|---|---|---|---|
| GD库手绘 | 轻量级Web系统 | PHP原生GD | 中 |
| 字体+SVG渲染 | 需要矢量印章 | Imagick + TrueType字体 | 低 |
| 第三方API集成 | 法律效力要求高 | 腾讯电子签/法大大等 | 低(但付费) |
对于自研项目,推荐GD库方案,因为它完全可控、无外部依赖,且能灵活实现圆章、椭圆章、五角星等样式,本文将以GD库为例,提供可直接运行的PHP代码。
基于GD库绘制自定义印章的完整代码
以下代码生成一个直径200px、包含单位名称和数字编号的圆形印章:
<?php
// 生成圆形印章
function generateSeal($companyName, $sealCode, $outputFile = 'seal.png') {
$width = 300; // 画布宽度
$height = 300; // 画布高度
$centerX = $width / 2;
$centerY = $height / 2;
$radius = 100; // 印章半径
// 1. 创建画布
$img = imagecreatetruecolor($width, $height);
imagesavealpha($img, true);
$transparent = imagecolorallocatealpha($img, 0, 0, 0, 127);
imagefill($img, 0, 0, $transparent);
// 2. 定义颜色
$red = imagecolorallocate($img, 255, 0, 0);
$black = imagecolorallocate($img, 0, 0, 0);
// 3. 绘制外圆(红色边框)
imagefilledellipse($img, $centerX, $centerY, $radius*2, $radius*2, $red);
// 内圆(白色镂空)
imagefilledellipse($img, $centerX, $centerY, $radius*2 - 8, $radius*2 - 8, $transparent);
// 4. 绘制五角星(位于圆心)
$starPoints = [];
for ($i = 0; $i < 5; $i++) {
$angle = deg2rad($i * 72 - 90);
$outerX = $centerX + 15 * cos($angle);
$outerY = $centerY + 15 * sin($angle);
$starPoints[] = $outerX;
$starPoints[] = $outerY;
$innerAngle = deg2rad(($i * 72 + 36) - 90);
$innerX = $centerX + 6 * cos($innerAngle);
$innerY = $centerY + 6 * sin($innerAngle);
$starPoints[] = $innerX;
$starPoints[] = $innerY;
}
imagefilledpolygon($img, $starPoints, 10, $red);
// 5. 绘制单位名称(沿圆弧排列)
$fontFile = 'path/to/simhei.ttf'; // 需替换为服务器上的中文字体路径
$fontSize = 18;
$text = $companyName;
$angleStep = 15; // 每个字符的角度间隔
$textLength = mb_strlen($text, 'UTF-8');
$startAngle = 180 + ($textLength * $angleStep) / 2;
for ($i = 0; $i < $textLength; $i++) {
$char = mb_substr($text, $i, 1, 'UTF-8');
$angle = deg2rad($startAngle - $i * $angleStep);
$x = $centerX + ($radius - 25) * cos($angle);
$y = $centerY + ($radius - 25) * sin($angle);
imagettftext($img, $fontSize, rad2deg($angle) + 90, $x, $y, $red, $fontFile, $char);
}
// 6. 绘制数字编号(水平居中)
$codeFontSize = 14;
$codeBox = imagettfbbox($codeFontSize, 0, $fontFile, $sealCode);
$codeWidth = $codeBox[2] - $codeBox[0];
$codeX = $centerX - $codeWidth / 2;
imagettftext($img, $codeFontSize, 0, $codeX, $centerY + 40, $red, $fontFile, $sealCode);
// 7. 输出PNG
imagepng($img, $outputFile);
imagedestroy($img);
return $outputFile;
}
// 使用示例
generateSeal('XX科技有限公司', '20240901', 'seal_output.png');
echo "印章已生成:seal_output.png";
?>
代码要点:
- 使用
imagesavealpha保持透明背景,便于后续叠加到文档 - 五角星通过
imagefilledpolygon绘制10个顶点实现 - 文字沿圆弧排列采用角度计算,适配各种长度的单位名称
印章签章与验证的业务逻辑设计
生成印章图片后,需要与文档绑定,典型的PHP签章流程如下:
签章流程
- 文档转图片:将PDF每页转为PNG(使用
Imagick或pdftoppm) - 定位签章坐标:用户在前端选择签章位置(x, y, pageNum)
- 合成图片:使用
imagecopymerge将印章图片叠加到目标坐标 - 生成数字签名:对合成后的图片内容做SHA-256哈希,用私钥加密生成签名
- 存储绑定:将签名、证书公钥、印章ID存入数据库,同时可嵌入PDF元数据
验证流程
- 提取签名:从数据库或PDF元数据获取签名和公钥
- 计算哈希:对当前文档(含印章区域)重新计算SHA-256
- 解密比对:用公钥解密签名得到原哈希,与当前哈希比对
- 视觉验证:检测文档中的印章图片是否被PS(通过像素级比对)
常见问题问答(FAQ)
Q1:生成的印章图片边缘有锯齿怎么办?
A:使用imageantialias($img, true)开启抗锯齿,并在绘制椭圆时使用imagefilledellipse代替imageellipse。
Q2:如何让印章支持国密SM2签名?
A:PHP可通过openssl_sign扩展调用SM2算法(需编译支持),或使用第三方库如gmssl-php,注意SM2签名结果需转换为DER格式。
Q3:印章图片能被轻易复制粘贴到其他文档吗? A:可以,但风险可控,建议方案:
- 在印章图片中嵌入隐形水印(如微小的像素差异)
- 将印章哈希与文档ID绑定存储,验证时检查哈希匹配
- 使用数字签名技术,确保任何图片修改都会导致验证失败
Q4:免费字体中哪种适合印章?
A:推荐使用simhei.ttf(黑体)或FangSong_GB2312.ttf(仿宋),注意版权问题,AWS的FreeFont、Google Noto Sans CJK也是合规选择。
Q5:大型PDF(100页以上)签章性能如何优化?
A:采用分页处理+异步队列(如Redis+Worker),每次只处理当前签章页,不加载整个PDF到内存,使用Swoole协程可提高并发处理能力。
生成电子印章不仅是图形绘制,更涉及数字签名、防篡改和验证体系,本文提供的PHP代码可直接用于开发环境,但生产系统建议结合TPM芯片或H SM硬件加密机,确保私钥安全,后续可扩展支持椭圆印章、多语言文字、动态防伪纹路等高级功能。