PHP项目电子印章如何对接后端生成

wen PHP项目 30

本文目录导读:

PHP项目电子印章如何对接后端生成

  1. 整体架构设计
  2. 核心技术实现
  3. 印章生成实现
  4. 密钥管理
  5. 安全性考虑
  6. 数据库设计
  7. 部署注意事项

我来详细说明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
);

部署注意事项

  1. 使用HTTPS:所有API请求必须使用HTTPS
  2. API限流:防止暴力破解
  3. 证书管理:定期更换签名证书
  4. 备份策略:定期备份印章数据和密钥
  5. 合规性:遵守当地电子签名法规定(如《电子签名法》)

这个方案提供了完整的电子印章后端对接实现,包括生成、签署、验证和安全措施,实际开发中可以根据具体需求进行调整。

抱歉,评论功能暂时关闭!