Реалізація підписання документів через браузер на сайті

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

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

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

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

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Реалізація підписання документів через браузер на сайті
Середня
~3-5 робочих днів
Часті питання

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

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

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

  • 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

Реалізація підписання документів через браузер на веб-сайті

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

Рівні електронного підпису

Простий ЕП — підтвердження особистості через логін/пароль або SMS-код. Юридично слабка, підходить для внутрішніх документів та згод.

Посилений неквалістичний ЕП — створюється з допомогою ключів, але без сертифікату акредитованого УЦ. Використовується в b2b за наявності угоди сторін про ЕДО.

Посилений кваліфікований ЕП (КЕП) — повна юридична значимість. Потребує сертифікованого СКЗІ.

Більшість сценаріїв "підписання в браузері" — це простий або посилений неквалітичний ЕП.

Процес підписання

Користувач відкриває документ
  ↓
Перегляд PDF/HTML документу
  ↓
Введення підпису (рисування, текст або SMS)
  ↓
Хеш документа + метаданні → сервер
  ↓
Сервер створює підписану версію
  ↓
Сповіщення + збереження

Перегляд PDF у браузері

Перед підписанням користувач повинен прочитати документ. Вбудовуємо переглядач PDF:

import { Viewer, Worker } from '@react-pdf-viewer/core';
import { defaultLayoutPlugin } from '@react-pdf-viewer/default-layout';
import '@react-pdf-viewer/core/lib/styles/index.css';

function DocumentViewer({ pdfUrl, onDocumentRead }) {
  const [pagesRead, setPagesRead] = useState(new Set<number>());
  const totalPagesRef = useRef(0);

  const handlePageChange = ({ currentPage }: { currentPage: number }) => {
    setPagesRead(prev => {
      const updated = new Set(prev).add(currentPage);
      if (updated.size >= totalPagesRef.current) {
        onDocumentRead(); // Розблокуємо кнопку підпису
      }
      return updated;
    });
  };

  return (
    <Worker workerUrl="/pdf.worker.min.js">
      <Viewer
        fileUrl={pdfUrl}
        plugins={[defaultLayoutPlugin()]}
        onPageChange={handlePageChange}
        onDocumentLoad={({ doc }) => { totalPagesRef.current = doc.numPages; }}
      />
    </Worker>
  );
}

Застосування підпису до PDF

Після отримання підпису користувача вбудовуємо його в PDF та створюємо підписану версію:

// Backend: обробка підписаного документа
async function processDocumentSignature(documentId, userId, signatureDataUrl, metadata) {
  const document = await db.documents.findByPk(documentId);

  // 1. Завантажуємо оригінальний PDF
  const originalPdf = await s3.getObject({ Bucket: BUCKET, Key: document.s3Key }).promise();

  // 2. Обчислюємо хеш для аудит-лога
  const originalHash = crypto.createHash('sha256').update(originalPdf.Body).digest('hex');

  // 3. Вбудовуємо підпис
  const { PDFDocument, rgb } = require('pdf-lib');
  const pdfDoc = await PDFDocument.load(originalPdf.Body);
  const lastPage = pdfDoc.getPages().at(-1);

  // Додаємо зображення підпису
  const signatureImage = await pdfDoc.embedPng(
    Buffer.from(signatureDataUrl.replace(/^data:image\/png;base64,/, ''), 'base64')
  );
  lastPage.drawImage(signatureImage, { x: 60, y: 50, width: 150, height: 50 });

  // Додаємо текстовий штамп
  const font = await pdfDoc.embedFont('Helvetica');
  lastPage.drawText(
    `Підписано: ${metadata.signerName}\n${metadata.signedAt.toISOString()}\nIP: ${metadata.ip}`,
    { x: 60, y: 30, size: 8, font, color: rgb(0.4, 0.4, 0.4) }
  );

  const signedPdfBytes = await pdfDoc.save();

  // 4. Зберігаємо підписану версію
  const signedKey = `signed/${documentId}/${userId}.pdf`;
  await s3.putObject({ Bucket: BUCKET, Key: signedKey, Body: signedPdfBytes }).promise();

  // 5. Фіксуємо в БД
  await db.documentSignatures.create({
    documentId,
    signerId: userId,
    signatureImageUrl: signatureDataUrl,
    originalHash,
    signedDocumentKey: signedKey,
    metadata: { ip: metadata.ip, userAgent: metadata.userAgent, signedAt: new Date() },
  });

  return signedKey;
}

SMS-підтвердження як простий ЕП

Для юридично значимих згод — підтвердження номером телефону:

// Генерація та відправка коду
async function initiateSmsSigning(documentId, userId, phone) {
  const code = Math.random().toString(36).substring(2, 8).toUpperCase();
  const codeHash = bcrypt.hashSync(code, 10);

  await redis.setex(
    `sms_sign:${documentId}:${userId}`,
    300, // 5 хвилин
    JSON.stringify({ codeHash, phone, attempts: 0 })
  );

  await smsService.send(phone, `Код підписання документа: ${code}. Дійсний 5 хвилин.`);
}

// Перевірка коду та фіксація підпису
async function confirmSmsSigning(documentId, userId, code) {
  const stored = JSON.parse(await redis.get(`sms_sign:${documentId}:${userId}`));
  if (!stored || !bcrypt.compareSync(code, stored.codeHash)) {
    throw new Error('Невірний код');
  }

  await redis.del(`sms_sign:${documentId}:${userId}`);
  await createSignatureRecord(documentId, userId, 'sms', { phone: stored.phone });
}

Мультиподписання

Документи часто потребують підписів від кількох сторін (контракт між клієнтом та виконавцем). Процес:

  1. Сторона А підписує → документ отримує статус partially_signed
  2. Сповіщення стороні Б + посилання на підписання
  3. Сторона Б підписує → статус fully_signed
  4. Обидві сторони отримують фіналь документ по email

Терміни

Перегляд PDF + намальований підпис + вбудовування в PDF + аудит-лог — 4–5 днів. SMS-підтвердження — 1–2 дні. Мультиподписання з процесом — 3–4 дні.