Перейти до вмісту

Накладення електронного підпису за допомогою електронного підпису Приват24

Матеріал з K2 ERP Wiki Ukraine — База знань з автоматизації та санкцій в Україні
Версія від 14:36, 7 травня 2026, створена R (обговорення | внесок) (Створена сторінка: {{DISPLAYTITLE:Технічне завдання: Накладення електронного підпису за допомогою Приват24 / SmartID для Python}} {{SEO |title=Технічне завдання: Накладення електронного підпису за допомогою Приват24 / SmartID для Python |description=Технічне завдання на реалізацію Python-сервісу для накл...)
(різн.) ← Попередня версія | Поточна версія (різн.) | Новіша версія → (різн.)


SEO title: Технічне завдання: Накладення електронного підпису за допомогою Приват24 / SmartID для Python SEO description: Технічне завдання на реалізацію Python-сервісу для накладення електронного підпису за допомогою КЕП ПриватБанку / SmartID: документи, hash, сесії підписання, callback, p7s, перевірка підпису, журналювання, dashboard та безпека. SEO keywords: Python, Приват24, ПриватБанк, SmartID, КЕП, електронний підпис, хмарний підпис, підписання документів, FastAPI, K2 ERP, p7s, електронний документообіг Alternative to:



Головна ідея: розробити Python-сервіс, який дозволяє користувачам підписувати документи за допомогою електронного підпису ПриватБанку / SmartID / Приват24 із подальшим збереженням документа, файлу підпису, статусу підписання, журналу дій і результату перевірки підпису.

Критично важливо: система не повинна зберігати пароль користувача до КЕП, приватний ключ або секрети підпису. Користувач підтверджує підписання у Приват24 / SmartID, а Python-сервіс зберігає тільки результат підписання, технічний статус, audit log і файл підпису.

Важливо: точні API endpoint-и, криптографічні формати, правила шифрування запитів, параметри сесії та callback потрібно брати з офіційної технічної документації ПриватБанку / SmartID, яку надають після підключення до сервісу.

Технічний стек: Python 3.11+, FastAPI, PostgreSQL, SQLAlchemy, Alembic, httpx, Pydantic, Celery/RQ/APScheduler, Redis, Docker, S3-compatible file storage.

Управлінський результат: відповідальна особа повинна бачити, які документи очікують підпису через Приват24 / SmartID, які підписані, які відхилені, які прострочені, які мають помилки підписання, які потребують повтору або ручної перевірки.

1. Мета

Метою задачі є створення Python-сервісу для накладення електронного підпису за допомогою КЕП ПриватБанку / SmartID / Приват24.

Сервіс повинен забезпечити:

  • створення заявки на підписання документа;
  • підготовку документа до підпису;
  • розрахунок hash документа;
  • створення сесії підписання;
  • передачу документа або hash у сервіс підписання;
  • ініціацію підтвердження підпису користувачем у Приват24 / SmartID;
  • отримання результату підписання;
  • збереження файлу підпису;
  • збереження підписаного контейнера, якщо він повертається сервісом;
  • перевірку підпису;
  • перевірку цілісності документа;
  • оновлення статусу документа в K2 ERP або іншій системі;
  • журналювання всіх подій;
  • контроль помилок;
  • dashboard для відповідальних осіб.

2. Область застосування

Інтеграція може використовуватись для:

  • договорів;
  • актів виконаних робіт;
  • рахунків;
  • заяв;
  • анкет;
  • кадрових документів;
  • первинних документів;
  • податкових і бухгалтерських документів;
  • документів ЕДО;
  • документів K2 ERP;
  • документів CRM;
  • документів особистого кабінету клієнта;
  • підтвердження юридично значущих дій користувача.

3. Що таке SmartID / електронний підпис Приват24 у межах інтеграції

SmartID у межах цього ТЗ розглядається як хмарний КЕП ПриватБанку, який користувач створює та використовує через Приват24.

Параметр Опис
Тип сервісу Хмарний кваліфікований електронний підпис.
Канал користувача Приват24 / Приват24 для бізнесу / SmartID.
Основний сценарій Користувач підтверджує підписання у Приват24, а Python-сервіс отримує результат.
Результат Файл підпису, підписаний об'єкт або інший результат згідно з API SmartID.
Кінцева система K2 ERP / CRM / документообіг / сайт / мобільний застосунок.

ПриватБанк описує SmartID як КЕП, що може використовуватись для підписання документів, звітів, підтвердження особистості й отримання послуг онлайн. :contentReference[oaicite:1]{index=1}

4. Передумови

Для реалізації задачі необхідно отримати:

  • доступ до сервісу SmartID / хмарного КЕП ПриватБанку;
  • офіційну технічну документацію API;
  • тестове середовище, якщо доступне;
  • ідентифікатор партнера / клієнта API;
  • технічні ключі або сертифікати сервісу;
  • правила авторизації;
  • правила шифрування запитів;
  • правила отримання сесії підписання;
  • правила формування запиту на підпис;
  • правила отримання результату;
  • правила перевірки підпису;
  • допустимі формати документів;
  • максимальний розмір документа;
  • callback URL або polling-сценарій;
  • контакт технічної підтримки ПриватБанку.

Критично важливо: якщо офіційний API SmartID недоступний для конкретного бізнес-сценарію, потрібно передбачити альтернативний режим: користувач підписує документ вручну у Приват24 / SmartID, а система приймає підписаний файл або p7s на завантаження та виконує перевірку підпису.

5. Варіанти реалізації

5.1. Варіант 1. Пряма API-інтеграція зі SmartID

Python-сервіс напряму інтегрується з API SmartID.

Параметр Опис
Підходить для Автоматизованого підписання документів у бізнес-процесі K2 ERP.
Переваги Контроль статусів, сесій, результатів і callback.
Обмеження Потрібен офіційний доступ до API, технічна документація і тестове середовище.
Рекомендація Основний production-сценарій, якщо API доступний.

5.2. Варіант 2. Ручне підписання у Приват24 + завантаження підпису в систему

Користувач сам підписує документ через Приват24 або SmartID, а потім завантажує підписаний документ / файл підпису в K2 ERP.

Параметр Опис
Підходить для MVP без прямого API або резервного сценарію.
Переваги Не потребує повної інтеграції з API SmartID.
Обмеження Менше автоматизації, більше ручних дій.
Рекомендація Використовувати як fallback-сценарій.

5.3. Варіант 3. Комбінована схема

Система підтримує обидва режими:

  • автоматичне створення сесії підписання через SmartID API;
  • ручне завантаження підписаного документа, якщо API недоступне або користувач підписав документ поза системою.

Рекомендовано для K2 ERP: реалізувати основний режим через API SmartID, а також резервний режим ручного завантаження p7s / підписаного контейнера з подальшою перевіркою.

6. Основні сценарії інтеграції

6.1. Підписання одного документа

Користувач відкриває документ у K2 ERP або на сайті та натискає кнопку «Підписати через Приват24 / SmartID».

Система:

  • створює запис документа;
  • створює версію документа;
  • розраховує hash;
  • створює заявку на підпис;
  • створює сесію SmartID;
  • очікує підтвердження користувачем;
  • отримує результат підписання;
  • зберігає підпис;
  • перевіряє підпис;
  • змінює статус документа на VERIFIED.

6.2. Підписання пакета документів

Користувач підписує декілька документів в одному бізнес-процесі.

Система повинна:

  • створити пакет документів;
  • перевірити всі документи;
  • створити окрему заявку на кожен документ або одну пакетну заявку, якщо це підтримується API;
  • отримати результат по кожному документу;
  • показати частково підписані або помилкові документи;
  • не втратити статус окремого документа.

6.3. Підписання документа клієнтом

Клієнт отримує посилання на документ.

Система:

  • відкриває сторінку підписання;
  • показує коротку інформацію про документ;
  • запускає сценарій підпису через Приват24 / SmartID;
  • клієнт підтверджує підписання;
  • система отримує результат;
  • документ стає підписаним клієнтом.

6.4. Підписання документа співробітником

Співробітник компанії підписує внутрішній документ.

Система:

  • створює задачу на підпис;
  • показує її у списку задач K2 ERP;
  • контролює строк підписання;
  • нагадує про прострочення;
  • зберігає аудит дій.

6.5. Ручне завантаження підпису

Користувач підписує документ поза системою, наприклад у Приват24, і завантажує результат.

Система:

  • приймає файл підпису або підписаний контейнер;
  • перевіряє hash вихідного документа;
  • перевіряє підпис;
  • визначає підписанта;
  • змінює статус документа;
  • зберігає результат перевірки.

7. Основні сутності

Сутність Опис
Signature Integration Налаштування підключення до SmartID / Приват24.
Document Документ, який потрібно підписати.
Document Version Версія документа, яка передана на підпис.
Signature Request Заявка на підписання.
Signature Session Сесія взаємодії зі SmartID.
Signer Підписант.
Callback Event Подія, отримана від сервісу підпису.
Signature File Файл підпису або підписаний контейнер.
Verification Result Результат перевірки підпису.
Audit Event Подія журналу.

8. User Story

8.1. Користувач підписує документ

Як користувач, я хочу натиснути кнопку «Підписати через Приват24 / SmartID», щоб підписати документ без завантаження приватного ключа в систему.

8.2. Менеджер контролює підписання

Як менеджер, я хочу бачити статус підписання документа, щоб знати, чи клієнт або співробітник підписав документ.

8.3. Адміністратор перевіряє помилки

Як адміністратор, я хочу бачити callback-и, помилки API та технічний журнал, щоб швидко знаходити причини невдалого підписання.

8.4. Керівник бачить dashboard

Як керівник, я хочу бачити кількість документів на підписі, підписаних, відхилених і прострочених, щоб контролювати документообіг.

9. Статуси документа

Статус Код Опис Колір
Чернетка DRAFT Документ створений, але ще не готовий до підпису. Сірий
Готовий до підпису READY_TO_SIGN Документ перевірено і можна створювати заявку. Блакитний
Очікує підпису WAITING_SIGNATURE Створено заявку на підпис. Жовтий
Підписується SIGNING Користувач проходить підтвердження у Приват24 / SmartID. Блакитний
Підписано SIGNED Підпис успішно отримано і збережено. Зелений
Підпис перевірено VERIFIED Підпис пройшов перевірку. Зелений
Відхилено користувачем DECLINED_BY_USER Користувач не підтвердив підписання. Помаранчевий
Прострочено EXPIRED Строк сесії підписання минув. Помаранчевий
Помилка підписання SIGN_ERROR Помилка під час підписання. Червоний
Помилка перевірки VERIFY_ERROR Підпис отримано, але перевірка не пройдена. Червоний
Ручна перевірка MANUAL_REVIEW Потрібна перевірка адміністратором. Фіолетовий

10. Статуси сесії підписання

Статус Код Опис Колір
Створюється CREATING Система створює сесію підписання. Блакитний
Активна ACTIVE Сесія створена та очікує дії користувача. Жовтий
Очікує підтвердження WAITING_USER_CONFIRMATION Користувач має підтвердити підпис у Приват24 / SmartID. Жовтий
Очікує результат WAITING_RESULT Підписання підтверджено, система очікує результат. Жовтий
Завершена COMPLETED Сесія завершена успішно. Зелений
Відхилена DECLINED Користувач відхилив дію. Помаранчевий
Прострочена EXPIRED Сесія не завершена у строк. Помаранчевий
Помилка ERROR Технічна помилка. Червоний

11. Єдина логіка кольорів

Колір HTML Значення Де використовується
Зелений #c8e6c9 Успішно: підписано, перевірено, завершено. Dashboard, список документів, картка документа.
Блакитний #bbdefb Операція виконується. Створення сесії, підписання.
Жовтий #fff9c4 Очікування дії користувача або результату. Очікує підпису, активна сесія.
Помаранчевий #ffcc80 Потрібна дія або є ризик. Відхилено, прострочено.
Червоний #ef9a9a Помилка або негативний результат. Помилка підписання, помилка перевірки.
Фіолетовий #f3e5f5 Ручна перевірка або нестандартний сценарій. MANUAL_REVIEW.
Сірий #eeeeee Чернетка або архів. DRAFT, archived.

12. Архітектура рішення

12.1. Загальна схема

K2 ERP / CRM / Website
        |
        | 1. Документ на підпис
        v
Python Privat24 / SmartID Signature Service
        |
        | 2. Валідація, hash, створення заявки
        v
SmartID Adapter
        |
        | 3. API SmartID / ПриватБанк
        v
Приват24 / SmartID
        |
        | 4. Користувач підтверджує підписання
        v
Callback або polling Python-сервісу
        |
        | 5. Результат підписання
        v
Signature Storage + Verification Service
        |
        | 6. Збереження, перевірка, статус
        v
K2 ERP / Dashboard / Документообіг

12.2. Основні компоненти Python-сервісу

Компонент Опис
API Layer REST API для створення заявок на підпис.
Document Service Робота з документами та версіями.
Signature Request Service Створення заявки на підписання.
SmartID Client Python-клієнт для API SmartID.
Confirmation Service Керує сесією підтвердження підпису користувачем.
Callback Controller Прийом callback, якщо API його підтримує.
Polling Worker Періодична перевірка статусу, якщо callback не використовується.
Signature Storage Зберігання підпису, контейнера, документа.
Verification Service Перевірка підпису та цілісності.
Status Sync Service Оновлення статусів у K2 ERP.
Audit Logger Журнал подій, callback-ів, помилок.
Dashboard API Дані для керівника та відповідальних осіб.

13. SmartID Client

13.1. Призначення

SmartID Client — це Python-клас або пакет, який інкапсулює роботу з API ПриватБанку / SmartID.

13.2. Основні методи

class SmartIDSignatureClient:
    def check_connection(self) -> "ConnectionStatus":
        pass

    def get_service_certificate(self) -> "ServiceCertificateResponse":
        pass

    def create_session(self, payload: "CreateSessionPayload") -> "SignatureSessionResponse":
        pass

    def create_signature_request(self, session_id: str, payload: "SignaturePayload") -> "SignatureRequestResponse":
        pass

    def get_session_status(self, session_id: str) -> "SignatureSessionStatusResponse":
        pass

    def get_signature_result(self, session_id: str) -> "SignatureResultResponse":
        pass

    def cancel_session(self, session_id: str) -> "CancelSessionResponse":
        pass

Важливо: назви методів у Python-клієнті є внутрішньою абстракцією. Реальні endpoint-и, шифрування, payload і response потрібно взяти з офіційної документації ПриватБанку / SmartID.

14. Конфігурація

from pydantic_settings import BaseSettings


class SmartIDSignatureSettings(BaseSettings):
    base_url: str
    partner_id: str
    partner_secret: str | None = None
    service_certificate_path: str | None = None
    private_key_path: str | None = None
    callback_url: str | None = None
    timeout_seconds: int = 30
    retry_count: int = 3
    retry_backoff_seconds: int = 5
    verify_ssl: bool = True
    session_ttl_minutes: int = 15
    max_document_size_mb: int = 10

Приклад `.env`:

SMARTID_BASE_URL=https://acsk.privatbank.ua/cloud/api/back
SMARTID_PARTNER_ID=********
SMARTID_PARTNER_SECRET=********
SMARTID_SERVICE_CERTIFICATE_PATH=/run/secrets/smartid_service_cert.pem
SMARTID_PRIVATE_KEY_PATH=/run/secrets/smartid_private_key.pem
SMARTID_CALLBACK_URL=https://example.com/api/v1/smartid/callback
SMARTID_TIMEOUT_SECONDS=30
SMARTID_RETRY_COUNT=3
SMARTID_SESSION_TTL_MINUTES=15
SMARTID_MAX_DOCUMENT_SIZE_MB=10

Заборонено: зберігати partner_secret, приватні ключі, токени, callback secrets, паролі КЕП або інші секрети у коді, Git-репозиторії, frontend-змінних або відкритих логах.

15. API Python-сервісу

15.1. Створення інтеграції

POST /api/v1/smartid-signature/integrations

15.2. Перевірка підключення

POST /api/v1/smartid-signature/integrations/{integration_id}/check-connection

15.3. Створення документа

POST /api/v1/smartid-signature/documents

15.4. Створення заявки на підпис

POST /api/v1/smartid-signature/documents/{document_id}/signature-requests

15.5. Отримання статусу заявки

GET /api/v1/smartid-signature/signature-requests/{request_id}/status

15.6. Callback від SmartID

POST /api/v1/smartid-signature/callback

15.7. Завантаження підписаного документа

GET /api/v1/smartid-signature/documents/{document_id}/signed-file

15.8. Завантаження файлу підпису

GET /api/v1/smartid-signature/documents/{document_id}/signature-file

15.9. Ручне завантаження підпису

POST /api/v1/smartid-signature/documents/{document_id}/upload-signature

15.10. Перевірка підпису

POST /api/v1/smartid-signature/documents/{document_id}/verify

15.11. Dashboard

GET /api/v1/smartid-signature/dashboard?date_from=2026-05-01&date_to=2026-05-31

16. Приклад запиту на створення заявки на підпис

{
  "external_document_id": "K2-DOC-2026-000123",
  "idempotency_key": "K2-DOC-2026-000123-smartid-sign-v1",
  "document_type": "CONTRACT",
  "document_name": "Договір поставки №123",
  "document_number": "123",
  "document_date": "2026-05-07",
  "file_id": "file-001",
  "file_name": "contract_123.pdf",
  "file_mime_type": "application/pdf",
  "signer": {
    "external_signer_id": "CLIENT-001",
    "full_name": "Іван Петренко",
    "phone": "+380671112233",
    "email": "client@example.com",
    "tax_id": "1234567890"
  },
  "callback_context": {
    "k2_entity": "contract",
    "k2_entity_id": "contract-001"
  },
  "expires_at": "2026-05-07T14:30:00+03:00"
}

17. Валідація документа перед підписом

Перед створенням заявки система повинна перевірити:

  • наявність external_document_id;
  • наявність idempotency_key;
  • наявність файлу документа;
  • файл доступний у сховищі;
  • файл не порожній;
  • розмір файлу не перевищує ліміт;
  • MIME type дозволений;
  • документ не був змінений після створення заявки;
  • hash документа збережений;
  • підписант визначений;
  • строк підписання не минув;
  • документ ще не підписаний цим підписантом;
  • бізнес-процес дозволяє підписання;
  • користувач має право ініціювати підписання;
  • телефон або ідентифікатор підписанта відповідає даним користувача, якщо це потрібно для SmartID-сценарію.

Критично важливо: якщо документ змінено після створення заявки на підпис, попередня заявка повинна бути скасована або переведена в статус INVALIDATED. Не можна підписувати старий hash для нової версії документа.

18. Hash документа і версії

Для кожного документа потрібно зберігати:

Поле Опис
document_version_id ID версії документа.
file_hash_sha256 Hash файлу.
file_size Розмір файлу.
mime_type MIME type.
created_at Дата створення версії.
created_by Хто створив версію.

Приклад hash:

sha256(file_bytes)

19. Callback або polling

19.1. Callback-сценарій

Callback endpoint повинен:

  • приймати тільки HTTPS-запити;
  • перевіряти підпис або секрет callback, якщо передбачено API;
  • перевіряти session_id;
  • перевіряти request_id;
  • перевіряти idempotency callback;
  • зберігати raw payload;
  • оновлювати статус сесії;
  • зберігати файл підпису або посилання на результат;
  • запускати перевірку підпису;
  • повертати коректний HTTP status.

19.2. Polling-сценарій

Якщо API не надсилає callback, Python-сервіс повинен періодично перевіряти статус сесії.

1. Створити сесію підписання.
2. Перевести заявку у WAITING_SIGNATURE.
3. Запустити polling worker.
4. Перевіряти статус кожні N секунд.
5. Після отримання фінального статусу зберегти результат.
6. Запустити перевірку підпису.
7. Оновити K2 ERP.

Критично важливо: callback і polling повинні бути ідемпотентними. Повторне отримання одного й того самого результату не повинно дублювати підпис або некоректно змінювати фінальний статус.

20. Перевірка підпису

Після отримання результату підписання система повинна виконати перевірку.

Перевіряється:

  • цілісність документа;
  • відповідність підпису конкретній версії документа;
  • валідність підпису;
  • валідність сертифіката;
  • дані підписанта;
  • час підписання;
  • статус відкликання сертифіката, якщо доступно;
  • чи відповідає підписант очікуваному користувачу;
  • чи не минув строк сесії;
  • чи не змінювався документ після підпису.

Можливі результати:

Результат Код Опис Колір
Валідний VALID Підпис пройшов перевірку. Зелений
Невалідний INVALID Підпис не пройшов перевірку. Червоний
Не той документ HASH_MISMATCH Hash документа не збігається. Червоний
Не той підписант SIGNER_MISMATCH Підписант не відповідає очікуваному. Червоний
Прострочений сертифікат CERT_EXPIRED Сертифікат підписанта недійсний на момент перевірки. Червоний
Потребує ручної перевірки MANUAL_REVIEW Неможливо автоматично визначити результат. Фіолетовий

21. Дедублікація

Система повинна не допускати дублювання заявок і підписів.

Ключі дедублікації:

Ключ Призначення
external_document_id ID документа в K2 ERP.
document_version_id Версія документа.
signer_id Підписант.
idempotency_key Унікальний ключ заявки.
smartid_session_id ID сесії SmartID.
callback_event_id ID callback-події, якщо надається.
file_hash_sha256 Hash документа.

22. Черга обробки

22.1. Логіка черги

1. K2 ERP створює документ.
2. Користувач натискає «Підписати через Приват24 / SmartID».
3. Python-сервіс перевіряє документ.
4. Створюється signature_request.
5. Створюється signature_session.
6. Користувач підтверджує підпис у Приват24 / SmartID.
7. Callback Controller або Polling Worker отримує результат.
8. Signature Storage зберігає підпис.
9. Verification Service перевіряє підпис.
10. K2 ERP отримує фінальний статус.

22.2. Пріоритети задач

Задача Пріоритет Коментар
Прийом callback Критичний Не можна втрачати результат підписання.
Збереження підпису Критичний Юридично значущий результат.
Перевірка підпису Високий Потрібна для фінального статусу.
Створення сесії Високий Основний сценарій користувача.
Polling статусу Середній Потрібен, якщо callback недоступний.
Оновлення dashboard Середній Контроль.
Нагадування про прострочення Низький Фоновий процес.

23. Модель даних

23.1. smartid_signature_integrations

Поле Тип Опис
id uuid ID інтеграції.
provider varchar privatbank_smartid.
name varchar Назва інтеграції.
base_url varchar URL API.
partner_id varchar ID партнера.
partner_secret_encrypted text Зашифрований секрет.
service_certificate_path varchar Шлях до сертифіката сервісу.
callback_url varchar Callback URL.
is_active boolean Активність.
created_at timestamp Дата створення.
updated_at timestamp Дата оновлення.

23.2. sign_documents

Поле Тип Опис
id uuid ID документа.
external_document_id varchar ID документа в K2 ERP.
document_type varchar CONTRACT, ACT, APPLICATION тощо.
document_name varchar Назва документа.
document_number varchar Номер документа.
document_date date Дата документа.
current_version_id uuid Поточна версія.
status varchar Статус документа.
created_at timestamp Дата створення.

23.3. sign_document_versions

Поле Тип Опис
id uuid ID версії.
document_id uuid ID документа.
file_id uuid Файл документа.
file_name varchar Назва файлу.
mime_type varchar MIME type.
file_size integer Розмір файлу.
file_hash_sha256 varchar Hash файлу.
version_number integer Номер версії.
created_at timestamp Дата створення.

23.4. signature_requests

Поле Тип Опис
id uuid ID заявки.
document_id uuid Документ.
document_version_id uuid Версія документа.
signer_id uuid Підписант.
idempotency_key varchar Ключ дедублікації.
status varchar Статус заявки.
expires_at timestamp Строк дії.
created_by uuid Хто створив заявку.
created_at timestamp Дата створення.

23.5. signature_sessions

Поле Тип Опис
id uuid ID сесії.
signature_request_id uuid Заявка.
smartid_session_id varchar ID сесії SmartID.
status varchar Статус сесії.
raw_request jsonb Запит до SmartID.
raw_response jsonb Відповідь SmartID.
created_at timestamp Дата створення.
expires_at timestamp Дата завершення.

23.6. signature_files

Поле Тип Опис
id uuid ID файлу підпису.
signature_request_id uuid Заявка.
file_id uuid Файл у сховищі.
file_type varchar signature, signed_container, signed_pdf.
file_hash_sha256 varchar Hash файлу.
source varchar SMARTID_API або MANUAL_UPLOAD.
created_at timestamp Дата створення.

23.7. signature_verifications

Поле Тип Опис
id uuid ID перевірки.
signature_request_id uuid Заявка.
result varchar VALID, INVALID, HASH_MISMATCH тощо.
signer_name varchar ПІБ підписанта з сертифіката.
signer_identifier varchar Ідентифікатор підписанта, якщо доступний.
signed_at timestamp Час підписання.
certificate_info jsonb Дані сертифіката.
raw_result jsonb Повний результат перевірки.
created_at timestamp Дата перевірки.

23.8. signature_events

Поле Тип Опис
id uuid ID події.
entity_type varchar document, request, session, callback, verification.
entity_id uuid ID сутності.
event_type varchar Тип події.
old_status varchar Попередній статус.
new_status varchar Новий статус.
source varchar K2_ERP, PYTHON_SERVICE, SMARTID, USER.
payload jsonb Технічні дані.
created_at timestamp Дата події.

24. Приклад Python-логіки

24.1. Створення заявки на підпис

def create_signature_request(command: "CreateSignatureRequestCommand", db: "Session") -> "SignatureRequest":
    existing = signature_request_repository.get_by_idempotency_key(
        db=db,
        idempotency_key=command.idempotency_key,
    )

    if existing:
        return existing

    document = document_repository.get_by_external_id(
        db=db,
        external_document_id=command.external_document_id,
    )

    signature_validator.validate_document_for_signing(document, command)

    request = signature_request_repository.create(
        db=db,
        data={
            "document_id": document.id,
            "document_version_id": document.current_version_id,
            "signer_id": command.signer_id,
            "idempotency_key": command.idempotency_key,
            "status": "CREATING",
            "expires_at": command.expires_at,
        },
    )

    signature_queue.enqueue(
        task_name="create_smartid_signature_session",
        payload={"signature_request_id": str(request.id)},
    )

    audit_logger.log(
        entity_type="signature_request",
        entity_id=request.id,
        event_type="SIGNATURE_REQUEST_CREATED",
        new_status="CREATING",
        payload={"external_document_id": command.external_document_id},
    )

    db.commit()
    return request

24.2. Створення сесії SmartID

async def create_smartid_signature_session(signature_request_id: str, db: "Session") -> None:
    request = signature_request_repository.get_by_id(db, signature_request_id)
    document_version = document_version_repository.get_by_id(db, request.document_version_id)

    try:
        payload = smartid_mapper.to_signature_session_payload(
            request=request,
            document_version=document_version,
        )

        response = await smartid_client.create_session(payload)

        session = signature_session_repository.create(
            db=db,
            data={
                "signature_request_id": request.id,
                "smartid_session_id": response.session_id,
                "status": "ACTIVE",
                "raw_request": payload,
                "raw_response": response.raw_payload,
                "expires_at": response.expires_at,
            },
        )

        request.status = "WAITING_SIGNATURE"

        audit_logger.log(
            entity_type="signature_session",
            entity_id=session.id,
            event_type="SMARTID_SIGNATURE_SESSION_CREATED",
            new_status="ACTIVE",
            payload={"smartid_session_id": response.session_id},
        )

    except Exception as exc:
        request.status = "SIGN_ERROR"
        audit_logger.log(
            entity_type="signature_request",
            entity_id=request.id,
            event_type="SMARTID_SIGNATURE_SESSION_ERROR",
            new_status="SIGN_ERROR",
            payload={"error": str(exc)},
        )

    finally:
        db.commit()

24.3. Polling статусу сесії

async def poll_smartid_session(signature_session_id: str, db: "Session") -> None:
    session = signature_session_repository.get_by_id(db, signature_session_id)

    if session.status in ["COMPLETED", "DECLINED", "EXPIRED", "ERROR"]:
        return

    status_response = await smartid_client.get_session_status(session.smartid_session_id)

    new_status = smartid_status_mapper.from_api(status_response.status)

    if new_status == "COMPLETED":
        result = await smartid_client.get_signature_result(session.smartid_session_id)
        signature_file = signature_storage.save_signature_result(
            signature_request_id=session.signature_request_id,
            payload=result.raw_payload,
        )

        session.status = "COMPLETED"
        session.signature_request.status = "SIGNED"

        verification_queue.enqueue(
            task_name="verify_signature",
            payload={
                "signature_request_id": str(session.signature_request_id),
                "signature_file_id": str(signature_file.id),
            },
        )

    elif new_status in ["DECLINED", "EXPIRED", "ERROR"]:
        session.status = new_status
        session.signature_request.status = smartid_status_mapper.to_request_status(new_status)

    db.commit()

24.4. Callback controller

from fastapi import APIRouter, Request, HTTPException

router = APIRouter()


@router.post("/api/v1/smartid-signature/callback")
async def smartid_signature_callback(request: Request):
    payload = await request.json()

    # Перевірка callback signature / secret залежить від офіційної документації SmartID.
    if not callback_security_service.is_valid(request, payload):
        raise HTTPException(status_code=401, detail="Invalid callback signature")

    callback_id = callback_service.get_callback_id(payload)

    if callback_repository.exists(callback_id):
        return {"status": "already_processed"}

    callback_event = callback_repository.create_raw_event(payload)

    signature_session = signature_session_repository.get_by_smartid_session_id(
        smartid_session_id=payload["session_id"],
    )

    if not signature_session:
        callback_event.status = "UNKNOWN_SESSION"
        return {"status": "unknown_session"}

    callback_processor.process_signature_result(
        signature_session=signature_session,
        payload=payload,
    )

    return {"status": "ok"}

24.5. Ручне завантаження підпису

def upload_manual_signature(
    document_id: str,
    signature_file: "UploadedFile",
    current_user: "User",
    db: "Session",
) -> "SignatureFile":
    document = document_repository.get_by_id(db, document_id)

    if document.status not in ["READY_TO_SIGN", "WAITING_SIGNATURE", "SIGN_ERROR"]:
        raise BusinessError("Document cannot accept signature in current status")

    stored_file = file_storage.save(signature_file)

    signature_record = signature_file_repository.create(
        db=db,
        data={
            "signature_request_id": None,
            "file_id": stored_file.id,
            "file_type": "signature",
            "file_hash_sha256": stored_file.sha256,
            "source": "MANUAL_UPLOAD",
        },
    )

    verification_queue.enqueue(
        task_name="verify_manual_signature",
        payload={
            "document_id": str(document.id),
            "signature_file_id": str(signature_record.id),
        },
    )

    audit_logger.log(
        entity_type="document",
        entity_id=document.id,
        event_type="MANUAL_SIGNATURE_UPLOADED",
        payload={"uploaded_by": str(current_user.id)},
    )

    db.commit()
    return signature_record

24.6. Перевірка підпису

def verify_signature(signature_request_id: str, signature_file_id: str, db: "Session") -> None:
    request = signature_request_repository.get_by_id(db, signature_request_id)
    document_version = document_version_repository.get_by_id(db, request.document_version_id)
    signature_file = signature_file_repository.get_by_id(db, signature_file_id)

    try:
        result = signature_verifier.verify(
            document_file_id=document_version.file_id,
            signature_file_id=signature_file.file_id,
            expected_hash=document_version.file_hash_sha256,
        )

        signature_verification_repository.create(
            db=db,
            data={
                "signature_request_id": request.id,
                "result": result.code,
                "signer_name": result.signer_name,
                "signer_identifier": result.signer_identifier,
                "signed_at": result.signed_at,
                "certificate_info": result.certificate_info,
                "raw_result": result.raw,
            },
        )

        if result.code == "VALID":
            request.status = "VERIFIED"
            request.document.status = "VERIFIED"
        else:
            request.status = "VERIFY_ERROR"

    except Exception as exc:
        request.status = "MANUAL_REVIEW"
        audit_logger.log(
            entity_type="signature_request",
            entity_id=request.id,
            event_type="SIGNATURE_VERIFY_EXCEPTION",
            new_status="MANUAL_REVIEW",
            payload={"error": str(exc)},
        )

    finally:
        db.commit()

25. Обробка помилок

Тип помилки Опис Дія системи
ValidationError Документ або підписант невалідний. Не створювати сесію.
AuthError Невірні credentials SmartID. Зупинити інтеграцію і повідомити адміністратора.
EncryptionError Помилка шифрування або підготовки запиту. Перевести в SIGN_ERROR.
DocumentChangedError Документ змінено після заявки. Скасувати заявку або створити нову.
FileTooLargeError Документ перевищує ліміт. Показати користувачу помилку.
SessionExpiredError Сесія підписання прострочена. Статус EXPIRED, дозволити створити нову.
CallbackValidationError Callback не пройшов перевірку. Відхилити callback і записати подію.
SignatureResultError Не вдалося отримати результат підпису. Перевести в SIGN_ERROR або NEEDS_RETRY.
VerificationError Підпис не пройшов перевірку. Статус VERIFY_ERROR.
SignerMismatchError Підписант не відповідає очікуваному. Статус MANUAL_REVIEW або VERIFY_ERROR.
TimeoutError API недоступне або timeout. Retry, якщо безпечно.

26. Retry-логіка

Retry дозволений для:

  • timeout;
  • HTTP 429;
  • HTTP 500;
  • HTTP 502;
  • HTTP 503;
  • HTTP 504;
  • тимчасової помилки створення сесії;
  • тимчасової помилки отримання статусу;
  • тимчасової помилки отримання результату;
  • тимчасової помилки перевірки підпису;
  • повторного callback з тим самим callback_id.

Retry заборонений для:

  • невалідного документа;
  • документа, який змінився;
  • простроченої сесії;
  • відхилення користувачем;
  • невірного callback signature;
  • невідповідності підписанта;
  • вже фінального статусу VERIFIED.

27. Dashboard керівника

27.1. Основні KPI

KPI Опис Колір
Документів створено Загальна кількість документів. Інформація
Очікують підпису Документи з активною сесією. Увага
Підписано Підпис отримано. Норма
Перевірено Підпис пройшов перевірку. Норма
Відхилено Користувач відмовився. Потрібна дія
Прострочено Сесія не завершена вчасно. Потрібна дія
Помилки Помилки підписання або callback. Критично
Ручна перевірка Потрібне втручання адміністратора. Контроль
Ручне завантаження Підписи, завантажені користувачем вручну. Інформація

27.2. Приклад dashboard

Показник Значення Стан
Документів за день 184 Інформація
Очікують підпису 32 Увага
Підписано через SmartID 118 Норма
Завантажено вручну 10 Інформація
Перевірено 126 Норма
Відхилено 8 Потрібна дія
Прострочено 10 Потрібна дія
Помилки callback/API 3 Критично
Ручна перевірка 2 Контроль

27.3. Проблемні документи

Дата Документ Підписант Статус Причина Дія
07.05.2026 Договір №123 Іван Петренко Прострочено Користувач не завершив підписання Створити нову заявку
07.05.2026 Акт №45 Олена Сидоренко Помилка перевірки Hash документа не збігається Ручна перевірка
07.05.2026 Заява №77 ТОВ «Альфа» Ручна перевірка Неможливо автоматично визначити підписанта Перевірити сертифікат

28. Безпека

Система повинна забезпечити:

  • HTTPS для всіх endpoint-ів;
  • перевірку SSL;
  • зберігання секретів тільки в secret storage;
  • шифрування файлів підпису;
  • шифрування документів або контроль доступу до них;
  • обмеження доступу до callback endpoint;
  • перевірку callback signature / secret;
  • ідемпотентність callback;
  • журнал усіх дій;
  • маскування персональних даних у логах;
  • контроль доступу до документів;
  • окремі права на створення заявки;
  • окремі права на повторне підписання;
  • окремі права на ручне завантаження підпису;
  • окремі права на ручну перевірку;
  • заборону підписання зміненої версії документа;
  • заборону зберігання пароля користувача до SmartID.

29. Логування та аудит

Система повинна логувати:

Подія Що зберігати
Створення документа Тип, номер, версія, hash.
Створення заявки Підписант, строк дії, ініціатор.
Створення сесії SmartID smartid_session_id, статус, expires_at.
Підтвердження користувачем Статус сесії, час.
Callback callback_id, raw payload, статус перевірки.
Polling статусу Старий статус, новий статус.
Отримання підпису file_id, hash підпису, час.
Ручне завантаження Хто завантажив, файл, hash.
Перевірка підпису результат, підписант, сертифікат.
Помилка код, повідомлення, stack trace без секретів.
Ручна перевірка хто перевірив, рішення, коментар.

30. Acceptance Criteria

30.1. Інтеграція

Критерій Очікуваний результат
AC-1 Адміністратор створює інтеграцію SmartID. Інтеграція зберігається в системі.
AC-2 Адміністратор перевіряє підключення. Система повертає успішний або помилковий статус.
AC-3 Credentials неправильні. Система показує AuthError і не створює сесії.

30.2. Документ

Критерій Очікуваний результат
AC-4 Документ валідний. Система створює заявку на підпис.
AC-5 Документ перевищує ліміт розміру. Заявка не створюється.
AC-6 Документ змінено після створення заявки. Попередня заявка стає INVALIDATED або скасовується.

30.3. Підписання

Критерій Очікуваний результат
AC-7 Користувач натискає «Підписати через Приват24 / SmartID». Система створює сесію підписання.
AC-8 Користувач підтверджує підпис. Система отримує результат і зберігає підпис.
AC-9 Користувач відхиляє підписання. Статус стає DECLINED_BY_USER.
AC-10 Сесія прострочена. Статус стає EXPIRED.

30.4. Ручне завантаження

Критерій Очікуваний результат
AC-11 Користувач завантажує p7s або підписаний контейнер. Система зберігає файл і запускає перевірку.
AC-12 Підпис відповідає документу. Статус стає VERIFIED.
AC-13 Підпис не відповідає документу. Статус стає HASH_MISMATCH або VERIFY_ERROR.

30.5. Перевірка

Критерій Очікуваний результат
AC-14 Підпис валідний. Статус стає VERIFIED.
AC-15 Hash документа не збігається. Статус стає VERIFY_ERROR.
AC-16 Підписант не відповідає очікуваному. Статус стає MANUAL_REVIEW або VERIFY_ERROR.

30.6. Callback / polling

Критерій Очікуваний результат
AC-17 Callback має правильний підпис/секрет. Система приймає callback.
AC-18 Callback повторився. Система не дублює результат.
AC-19 Callback невалідний. Система повертає помилку і записує подію.
AC-20 Callback недоступний, але polling увімкнений. Система отримує статус через polling worker.

30.7. Dashboard

Критерій Очікуваний результат
AC-21 Керівник відкриває dashboard. Він бачить документи, підписи, помилки, прострочення.
AC-22 Є помилки підписання. Вони підсвічуються червоним.
AC-23 Є прострочені заявки. Вони підсвічуються помаранчевим.
AC-24 Є документи на ручній перевірці. Вони підсвічуються фіолетовим.

31. MVP

До MVP входить:

  • створення інтеграції SmartID / Приват24;
  • перевірка підключення;
  • створення документа;
  • збереження версії документа;
  • розрахунок hash;
  • створення заявки на підпис;
  • створення сесії підписання, якщо доступний API;
  • polling або callback для отримання результату;
  • збереження результату підписання;
  • ручне завантаження p7s / підписаного контейнера як fallback;
  • базова перевірка підпису;
  • статуси документа;
  • журнал подій;
  • dashboard API;
  • retry для технічних помилок;
  • ідемпотентність callback / polling;
  • unit-тести;
  • mock SmartID client.

До MVP не входить:

  • масове підписання великого пакета документів;
  • складний UI документообігу;
  • власний кваліфікований надавач електронних довірчих послуг;
  • повна юридична експертиза документів;
  • інтеграція з усіма зовнішніми ЕДО-системами;
  • автоматичне виправлення документів;
  • архів довгострокового зберігання за окремими регламентами.

32. Етапи реалізації

Етап 1. Аналіз інтеграції SmartID

  • отримати офіційну технічну документацію;
  • отримати тестові credentials;
  • погодити callback URL або polling-сценарій;
  • перевірити тестовий сценарій;
  • визначити формат результату підписання;
  • визначити правила перевірки підпису.

Етап 2. Базовий Python-сервіс

  • створити FastAPI-проєкт;
  • налаштувати PostgreSQL;
  • створити моделі документів, заявок, сесій, підписів;
  • налаштувати Alembic;
  • реалізувати healthcheck.

Етап 3. SmartID Client

  • реалізувати get_service_certificate;
  • реалізувати create_session;
  • реалізувати create_signature_request;
  • реалізувати get_session_status;
  • реалізувати get_signature_result;
  • реалізувати обробку помилок.

Етап 4. Документи

  • реалізувати завантаження документа;
  • реалізувати версіонування;
  • реалізувати hash;
  • реалізувати валідацію;
  • реалізувати дедублікацію.

Етап 5. Callback / polling та підпис

  • реалізувати callback endpoint;
  • реалізувати polling worker;
  • реалізувати перевірку callback;
  • реалізувати збереження результату;
  • реалізувати ідемпотентність;
  • реалізувати raw event storage.

Етап 6. Ручне завантаження підпису

  • реалізувати upload endpoint;
  • реалізувати перевірку типу файлу;
  • реалізувати збереження p7s / контейнера;
  • реалізувати зв'язок із документом;
  • реалізувати перевірку підпису.

Етап 7. Перевірка підпису

  • реалізувати Verification Service;
  • реалізувати статуси перевірки;
  • реалізувати ручну перевірку;
  • реалізувати журнал перевірок.

Етап 8. Dashboard та аудит

  • реалізувати dashboard API;
  • реалізувати список проблемних документів;
  • реалізувати фільтри;
  • реалізувати експорт, якщо потрібно.

Етап 9. Production hardening

  • додати rate limiting;
  • додати alerting;
  • додати dead letter queue;
  • додати backup файлів;
  • додати моніторинг callback / polling;
  • додати безпечне зберігання секретів.

33. Ризики

Ризик Опис Як зменшити
Немає API-доступу SmartID Без доступу неможливо реалізувати повну автоматичну інтеграцію. Передбачити fallback: ручне завантаження підпису.
Документ змінено після заявки Можна підписати неактуальну версію. Версіонування і hash документа.
Callback втрачено Система не дізнається про результат. Callback retry, polling статусу, журнал raw events.
Дублювання callback Може повторно змінити статус. Ідемпотентність callback.
Невідомий формат підпису Неможливо зберегти/перевірити результат. Уточнити формат за документацією SmartID.
Невідповідність підписанта Документ підписала не та особа. Перевірка даних сертифіката.
Помилка перевірки Підпис отримано, але не підтверджено. MANUAL_REVIEW і аудит.
Прострочені сесії Користувач не завершив підписання. TTL, нагадування, повторна заявка.

34. Відкриті питання

  1. Чи є офіційний API-доступ до SmartID для цього проєкту?
  2. Який точний формат результату підписання: p7s, ASIC, PDF з підписом або інший?
  3. Чи потрібно підписувати PDF, XML, DOCX або будь-який файл?
  4. Який максимальний розмір документа?
  5. Чи потрібне пакетне підписання?
  6. Чи потрібен fallback зі ручним завантаженням p7s?
  7. Чи потрібно підписувати документи клієнтами, співробітниками або обома?
  8. Чи потрібно перевіряти РНОКПП / ЄДРПОУ підписанта?
  9. Чи потрібна інтеграція з K2 ERP?
  10. Чи потрібно зберігати підписані документи в архіві довгострокового зберігання?
  11. Чи потрібен UI для підписанта?
  12. Чи потрібні email/SMS-нагадування?
  13. Який строк дії сесії підписання?
  14. Який callback security mechanism надає SmartID?
  15. Чи потрібна інтеграція з ЕДО-системами після підписання?

35. Джерела

  • Офіційна сторінка SmartID ПриватБанку.
  • Офіційна сторінка SmartID для бізнесу.
  • Інструкція ПриватБанку щодо створення SmartID.
  • Технічна документація SmartID API, яка надається після підключення.
  • Документація K2 ERP щодо документів і бізнес-процесів.
  • Законодавчі вимоги до КЕП і електронного документообігу.

36. Див. також