本文目录导读:

我来详细说明PHP项目中电子印章的后端对接方案。
整体架构设计
前端应用 → API接口 → 后端PHP服务 → 印章生成引擎
↓
PDF文档/图片签名
核心技术实现
1 印章数据结构
<?php
// 印章数据结构
class StampData {
public $type; // 印章类型:company(公章), personal(私章), contract(合同章)
public $companyName; // 公司名称
public $personName; // 个人姓名
public $number; // 编号/税号
public $style; // 样式:circle(圆形), oval(椭圆形), square(方形)
public $color; // 颜色:red(红色), blue(蓝色)
public $size; // 尺寸
}
2 后端接口设计
<?php
// API接口示例
class StampController {
/**
* 生成电子印章
* @POST /api/stamp/generate
*/
public function generateStamp($request) {
// 1. 验证权限
$this->checkPermission($request->user);
// 2. 参数验证
$validator = Validator::make($request->all(), [
'type' => 'required|in:company,personal,contract',
'company_name' => 'required_if:type,company|max:50',
'person_name' => 'required_if:type,personal|max:20',
'number' => 'nullable|max:30',
'style' => 'required|in:circle,oval,square',
'color' => 'required|in:red,blue',
'size' => 'required|integer|min:50|max:300'
]);
if ($validator->fails()) {
return response()->json(['error' => $validator->errors()], 400);
}
// 3. 生成印章图片
$stampService = new StampService();
$stampImage = $stampService->createStamp($request->all());
// 4. 保存到存储系统
$storage = Storage::disk('local');
$fileName = 'stamps/' . uniqid() . '.png';
$storage->put($fileName, $stampImage);
// 5. 记录数据库
$stampRecord = Stamp::create([
'user_id' => $request->user->id,
'type' => $request->type,
'file_path' => $fileName,
'hash' => hash('sha256', $stampImage)
]);
return response()->json([
'success' => true,
'stamp_id' => $stampRecord->id,
'image_url' => url('api/stamp/download/' . $stampRecord->id),
'hash' => $stampRecord->hash
]);
}
/**
* 印章签署文档
* @POST /api/stamp/sign
*/
public function signDocument($request) {
// 1. 验证印章存在
$stamp = Stamp::findOrFail($request->stamp_id);
// 2. 验证文档权限
$document = Document::findOrFail($request->document_id);
$this->checkDocumentPermission($request->user, $document);
// 3. 执行签署
$signService = new SignService();
$signedPdf = $signService->applyStamp(
$document->file_path,
$stamp->file_path,
$request->position_x,
$request->position_y,
$request->page_number
);
// 4. 生成签名值
$signatureValue = $this->generateSignatureValue(
$signedPdf,
$request->user->private_key
);
// 5. 保存签署记录
$signRecord = SignRecord::create([
'document_id' => $document->id,
'stamp_id' => $stamp->id,
'user_id' => $request->user->id,
'signed_file' => $signedPdf,
'signature_value' => $signatureValue,
'timestamp' => time()
]);
return response()->json([
'success' => true,
'record_id' => $signRecord->id,
'signature' => $signatureValue
]);
}
}
印章生成实现
1 使用GD库生成印章
<?php
class StampService {
/**
* 生成圆形印章
*/
public function createCircularStamp($data) {
$size = $data['size'];
$image = imagecreatetruecolor($size, $size);
// 设置背景透明
imagealphablending($image, false);
imagesavealpha($image, true);
$transparent = imagecolorallocatealpha($image, 255, 255, 255, 127);
imagefill($image, 0, 0, $transparent);
// 设置颜色
$red = $data['color'] === 'red' ? 255 : 0;
$green = 0;
$blue = $data['color'] === 'blue' ? 255 : 0;
$stampColor = imagecolorallocate($image, $red, $green, $blue);
// 绘制外圆
$center = $size / 2;
$radius = $size / 2 - 5;
imageellipse($image, $center, $center, $radius * 2, $radius * 2, $stampColor);
// 绘制内圆
$innerRadius = $radius - 15;
imageellipse($image, $center, $center, $innerRadius * 2, $innerRadius * 2, $stampColor);
// 添加文字(公司名称)
$text = $data['companyName'];
$fontSize = 10;
$fontPath = 'path/to/your/font.ttf'; // 确保字体文件存在
// 计算文字弧度
$textWidth = strlen($text) * $fontSize;
$arcAngle = ($textWidth / ($radius - 10)) * (180 / M_PI);
$startAngle = 90 + ($arcAngle / 2);
// 沿弧线绘制文字
for ($i = 0; $i < strlen($text); $i++) {
$char = $text[$i];
$angle = $startAngle - ($i * $arcAngle / strlen($text));
$radians = deg2rad($angle);
$x = $center + ($radius - 25) * cos($radians);
$y = $center - ($radius - 25) * sin($radians);
imagettftext(
$image, $fontSize, 90 - $angle,
$x, $y, $stampColor, $fontPath, $char
);
}
// 添加中间文字(五角星)
$starSize = 20;
$this->drawStar($image, $center, $center, $starSize, $stampColor);
// 输出图片
ob_start();
imagepng($image);
$imageData = ob_get_clean();
imagedestroy($image);
return $imageData;
}
/**
* 绘制五角星
*/
private function drawStar($image, $cx, $cy, $size, $color) {
$points = [];
for ($i = 0; $i < 5; $i++) {
$angle = deg2rad(90 - $i * 72);
$points[] = $cx + $size * cos($angle);
$points[] = $cy - $size * sin($angle);
$angle = deg2rad(90 - ($i * 72 + 36));
$innerSize = $size * 0.4;
$points[] = $cx + $innerSize * cos($angle);
$points[] = $cy - $innerSize * sin($angle);
}
imagefilledpolygon($image, $points, 10, $color);
}
}
2 使用PDF库签署文档
<?php
// 使用FPDI/Mpdf库处理PDF
use setasign\Fpdi\Fpdi;
class SignService {
/**
* 在PDF上应用印章
*/
public function applyStamp($pdfPath, $stampPath, $x, $y, $page) {
$pdf = new Fpdi();
$pageCount = $pdf->setSourceFile($pdfPath);
for ($i = 1; $i <= $pageCount; $i++) {
$template = $pdf->importPage($i);
$size = $pdf->getTemplateSize($template);
$pdf->AddPage($size['orientation'], [$size['width'], $size['height']]);
$pdf->useTemplate($template);
// 仅在指定页面添加印章
if ($i == $page) {
$stampInfo = getimagesize($stampPath);
$pdf->Image($stampPath, $x, $y, $stampInfo[0] * 0.75, $stampInfo[1] * 0.75);
}
}
// 输出签署后的PDF
$outputPath = tempnam(sys_get_temp_dir(), 'signed_') . '.pdf';
$pdf->Output($outputPath, 'F');
return $outputPath;
}
/**
* 生成签名值
*/
public function generateSignatureValue($pdfPath, $privateKey) {
$pdfContent = file_get_contents($pdfPath);
$hash = hash('sha256', $pdfContent, true);
// 使用私钥签名
openssl_sign($hash, $signature, $privateKey, OPENSSL_ALGO_SHA256);
return base64_encode($signature);
}
}
密钥管理
<?php
class KeyManager {
/**
* 生成密钥对
*/
public function generateKeyPair() {
$config = [
'digest_alg' => 'sha256',
'private_key_bits' => 2048,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
];
$resource = openssl_pkey_new($config);
openssl_pkey_export($resource, $privateKey);
$publicKey = openssl_pkey_get_details($resource)['key'];
return [
'private_key' => $privateKey,
'public_key' => $publicKey
];
}
/**
* 使用HSM存储密钥(硬件安全模块)
*/
public function storeKeyWithHSM($keyId, $privateKey) {
// 使用加密机或云HSM服务
// 阿里云KMS、腾讯云HSM
}
}
安全性考虑
1 防伪造措施
<?php
class SecurityService {
/**
* 验证印章真实性
*/
public function verifyStamp($stampFile, $stampRecord) {
// 1. 验证哈希
$currentHash = hash('sha256', file_get_contents($stampFile));
if ($currentHash !== $stampRecord->hash) {
return false;
}
// 2. 验证数字签名
$signature = $stampRecord->signature_value;
$publicKey = $stampRecord->user->public_key;
return openssl_verify(
$stampFile,
base64_decode($signature),
$publicKey,
OPENSSL_ALGO_SHA256
);
}
/**
* 时间戳服务
*/
public function getTimestamp() {
// 调用第三方时间戳服务(如:天威诚信、CFCA)
$tsaUrl = 'https://timestamp.example.com/timestamp';
$hash = hash('sha256', $data, true);
// 发送时间戳请求
$response = Http::post($tsaUrl, [
'hash' => base64_encode($hash),
'algorithm' => 'sha256'
]);
return $response->timestamp;
}
}
2 日志审计
<?php
class AuditService {
/**
* 记录所有印章操作
*/
public function logOperation($userId, $operation, $stampId, $details) {
AuditLog::create([
'user_id' => $userId,
'operation' => $operation, // generate, sign, verify, revoke
'stamp_id' => $stampId,
'ip_address' => request()->ip(),
'user_agent' => request()->userAgent(),
'details' => json_encode($details),
'timestamp' => time()
]);
}
}
数据库设计
-- 印章表
CREATE TABLE stamps (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
type ENUM('company', 'personal', 'contract') NOT NULL,
file_path VARCHAR(255) NOT NULL,
hash VARCHAR(64) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
status ENUM('active', 'revoked', 'expired') DEFAULT 'active',
FOREIGN KEY (user_id) REFERENCES users(id)
);
-- 签署记录表
CREATE TABLE sign_records (
id INT PRIMARY KEY AUTO_INCREMENT,
document_id INT NOT NULL,
stamp_id INT NOT NULL,
user_id INT NOT NULL,
signed_file VARCHAR(255) NOT NULL,
signature_value TEXT,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
verification_status ENUM('valid', 'invalid', 'not_verified') DEFAULT 'not_verified'
);
-- 审计日志表
CREATE TABLE audit_logs (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
operation VARCHAR(50) NOT NULL,
stamp_id INT,
ip_address VARCHAR(45),
user_agent VARCHAR(255),
details JSON,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
部署注意事项
- 使用HTTPS:所有API请求必须使用HTTPS
- API限流:防止暴力破解
- 证书管理:定期更换签名证书
- 备份策略:定期备份印章数据和密钥
- 合规性:遵守当地电子签名法规定(如《电子签名法》)
这个方案提供了完整的电子印章后端对接实现,包括生成、签署、验证和安全措施,实际开发中可以根据具体需求进行调整。