Реалізація електронного підпису (малювання/введення) на сайті

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Реалізація електронного підпису (малювання/введення) на сайті
Проста
від 1 робочого дня до 3 робочих днів
Часті питання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Реалізація електронного підпису (рисування/введення) на веб-сайті

Електронний підпис у форматі "намалювати або надрукувати" — це найпростіший спосіб отримати згоду користувача на документ. Не плутати з кваліфікованим електронним підписом (КЕП): тут йдеться про візуальний підпис без криптографії, який використовується в контрактах, угодах, актах виконаних робіт.

Три варіанти введення підпису

Намалювати — користувач малює підпис мишею або стилусом на canvas. Найзвичніший формат для більшості користувачів.

Надрукувати — ввести ім'я, відображається вибраним "рукописним" шрифтом (Caveat, Dancing Script, Pacifico).

Завантажити зображення — завантажити фото/сканування власного підпису.

Реалізація через signature_pad

Бібліотека signature_pad — стандарт для canvas-підпису:

import SignaturePad from 'signature_pad';
import { useRef, useEffect, useState } from 'react';

function SignatureCanvas({ onSave, onClear }) {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const padRef = useRef<SignaturePad | null>(null);

  useEffect(() => {
    const canvas = canvasRef.current!;
    padRef.current = new SignaturePad(canvas, {
      backgroundColor: 'rgb(255, 255, 255)',
      penColor: 'rgb(0, 0, 0)',
      minWidth: 0.5,
      maxWidth: 2.5,
      throttle: 16,  // ~60fps
    });

    // Масштабування для Retina дисплеїв
    function resizeCanvas() {
      const ratio = Math.max(window.devicePixelRatio || 1, 1);
      canvas.width = canvas.offsetWidth * ratio;
      canvas.height = canvas.offsetHeight * ratio;
      const ctx = canvas.getContext('2d')!;
      ctx.scale(ratio, ratio);
      padRef.current!.clear();
    }

    resizeCanvas();
    window.addEventListener('resize', resizeCanvas);
    return () => window.removeEventListener('resize', resizeCanvas);
  }, []);

  const handleSave = () => {
    if (padRef.current!.isEmpty()) return;
    const dataUrl = padRef.current!.toDataURL('image/png');
    onSave(dataUrl);
  };

  return (
    <div className="border-2 border-dashed border-gray-300 rounded-lg">
      <canvas
        ref={canvasRef}
        className="w-full h-40 touch-none"  // touch-none важливо для мобільних
      />
      <div className="flex gap-2 p-2">
        <button onClick={() => { padRef.current!.clear(); onClear(); }}>Очистити</button>
        <button onClick={handleSave} className="btn-primary">Підписати</button>
      </div>
    </div>
  );
}

Введення текстового підпису

const SIGNATURE_FONTS = [
  { name: 'Caveat', label: 'Рукописний 1' },
  { name: 'Dancing Script', label: 'Рукописний 2' },
  { name: 'Pacifico', label: 'Каліграфія' },
];

function TextSignature({ name, onSave }) {
  const [selectedFont, setSelectedFont] = useState(SIGNATURE_FONTS[0]);
  const canvasRef = useRef<HTMLCanvasElement>(null);

  const renderToCanvas = (font: string, text: string) => {
    const canvas = canvasRef.current!;
    const ctx = canvas.getContext('2d')!;
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.font = `48px "${font}"`;
    ctx.fillStyle = '#1a1a1a';
    ctx.fillText(text, 20, 70);
    return canvas.toDataURL('image/png');
  };

  return (
    <div>
      <div className="flex gap-2 mb-3">
        {SIGNATURE_FONTS.map(font => (
          <button
            key={font.name}
            style={{ fontFamily: font.name }}
            onClick={() => setSelectedFont(font)}
            className={selectedFont.name === font.name ? 'border-blue-500 border-2' : ''}
          >
            {name}
          </button>
        ))}
      </div>
      <canvas ref={canvasRef} width={400} height={100} className="border rounded" />
      <button onClick={() => onSave(renderToCanvas(selectedFont.name, name))}>
        Застосувати підпис
      </button>
    </div>
  );
}

Вбудовування підпису в документ

Після отримання підпису як base64 PNG вбудовуємо його в документ. Для PDF — через PDF-lib:

import { PDFDocument } from 'pdf-lib';

async function embedSignatureInPdf(pdfBytes, signatureDataUrl, position) {
  const pdfDoc = await PDFDocument.load(pdfBytes);
  const pages = pdfDoc.getPages();
  const targetPage = pages[position.page];

  const signatureBytes = Buffer.from(signatureDataUrl.split(',')[1], 'base64');
  const signatureImage = await pdfDoc.embedPng(signatureBytes);

  targetPage.drawImage(signatureImage, {
    x: position.x,
    y: position.y,
    width: position.width,
    height: position.height,
  });

  return await pdfDoc.save();
}

Зберігання та аудит

Підпис як зображення зберігається в S3. В БД фіксуються: user_id, timestamp, IP-адреса, user-agent, document_id, хеш документа. Це забезпечує базовий аудит-слід.

Терміни

Компонент з трьома методами підпису (рисування, текст, завантаження) та вбудовуванням у PDF — 2–3 дні.