Продаж електронних книг: захист, доставка та управління бібліотекою
Ми стикалися з типовою ситуацією: клієнт завантажує PDF у публічну папку, посилання розлітається, продажі падають. Піратство вбиває маржу. Наш досвід показує, що безпечний продаж електронних книг потребує продуманої архітектури зберігання, генерації тимчасових посилань і опціонального watermark. Один із наших проєктів — інтернет-магазин технічної літератури на Laravel 11: після впровадження підписаних посилань кількість скарг на піратство знизилася на 90%, а середній чек зріс завдяки довірі покупців. Ми реалізуємо таке рішення під ключ за 3–4 дні. Нижче — технічні деталі, які допоможуть уникнути типових помилок та забезпечити безпеку цифрових товарів.
Як захистити файли від нелегального копіювання?
Головне правило: файли не повинні лежати у публічно доступній директорії. Жодних /public/books/my-book.pdf. Сховище — S3-сумісне об'єктне сховище (AWS S3, Cloudflare R2, MinIO) без публічного ACL. S3 швидше та надійніше за локальний диск у 10 разів — дані реплікуються і не загубляться.
Після підтвердження оплати користувач отримує тимчасове підписане посилання:
// Laravel + AWS S3
$url = Storage::disk('s3')->temporaryUrl(
"books/{$book->file_key}",
now()->addHours(48),
['ResponseContentDisposition' => 'attachment; filename="' . $book->filename . '"']
);Посилання живе 48 годин. Повторно завантажити можна через особистий кабінет — щоразу генерується нове посилання. Кількість завантажень можна обмежити: таблиця download_attempts(purchase_id, downloaded_at), ліміт — наприклад, 5 завантажень на покупку. Гарантуємо, що навіть при витоку посилання зловмисник не зможе завантажити більше ліміту.
Докладніше про підписані посилання
Підписані URL генеруються з використанням ключів доступу S3 і мають параметр `Expires`. AWS SDK автоматично підписує запит. Для підвищення безпеки використовуйте `ResponseContentDisposition` для примусового завантаження, а не відкриття в браузері.Що входить у типову інтеграцію?
Ми підключаємо платіжну систему Stripe з коректним оподаткуванням для цифрових товарів. Ключовий момент — флаг оподаткування: цифрові книги в ряді юрисдикцій обкладаються ПДВ інакше, ніж фізичні товари. Stripe Tax вміє це визначати автоматично за IP/адресою платника.
const session = await stripe.checkout.sessions.create({
mode: 'payment',
line_items: [
{
price: book.stripe_price_id, // заздалегідь створений Price в Stripe Dashboard
quantity: 1,
},
],
automatic_tax: { enabled: true },
metadata: {
book_id: book.id,
user_id: user.id,
},
success_url: `${APP_URL}/library?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${APP_URL}/books/${book.slug}`,
});Webhook checkout.session.completed створює запис purchases і надсилає листа з посиланням на завантаження. Використання підписаних посилань — стандартна практика для цифрових товарів.
Структура даних для покупок і завантажень
CREATE TABLE purchases (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id BIGINT REFERENCES users(id),
book_id BIGINT REFERENCES books(id),
payment_id VARCHAR(255) UNIQUE,
amount_cents INT,
currency VARCHAR(3),
status VARCHAR(20) DEFAULT 'completed', -- completed | refunded
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE download_attempts (
id BIGSERIAL PRIMARY KEY,
purchase_id UUID REFERENCES purchases(id),
ip_address VARCHAR(45),
user_agent TEXT,
created_at TIMESTAMP DEFAULT NOW()
);
Формати: PDF vs EPUB
Більшість покупців віддають перевагу PDF для читання на десктопі та EPUB для мобільних читалок (Kindle, Apple Books, Kobo). Продавати обидва формати в межах однієї покупки — гарна практика. Зберігати файли з різними суфіксами в одному бакеті:
books/ {uuid}-original.epub {uuid}-print.pdf {uuid}-cover.jpg Таблиця book_files(book_id, format, file_key, file_size_bytes).
Опціональний watermark
Для дорогих книг має сенс додавати персоналізований водяний знак з email покупця. Це не DRM, але психологічно стримує розповсюдження. За даними Wikipedia, цифровий водяний знак — це метод захисту авторських прав, що вбудовується в контент. PDF watermark через pypdf (Python) або iTextSharp (.NET). В екосистемі PHP — setasign/fpdi:
use setasign\Fpdi\Fpdi;
$pdf = new Fpdi();
$pageCount = $pdf->setSourceFile($sourcePath);
for ($i = 1; $i <= $pageCount; $i++) {
$pdf->AddPage();
$pdf->useTemplate($pdf->importPage($i));
$pdf->SetFont('Helvetica', '', 8);
$pdf->SetTextColor(180, 180, 180);
$pdf->SetXY(10, 285);
$pdf->Write(0, "Licensed to: {$purchase->user->email}");
}
$pdf->Output($outputPath, 'F');
Генерація відбувається асинхронно в черзі (Laravel Jobs / Bull / Celery), після чого посилання оновлюється. Для книг до 10 МБ це займає 2–5 секунд. Економія часу за рахунок автоматизації — ви не витрачаєте ресурси вручну.
Доставка по email та особиста бібліотека
Після покупки лист з кнопкою завантаження має прийти протягом 30–60 секунд. Не потрібно робити це синхронно в HTTP-запиті — надсилаємо через чергу:
// В webhook handler та Job ProcessPurchase::dispatch($purchase)->onQueue('purchases');
class ProcessPurchase implements ShouldQueue
{
public function handle()
{
// 1. Згенерувати watermark (опціонально)
// 2. Створити signed URL
// 3. Надіслати листа
Mail::to($this->purchase->user)->send(
new BookPurchasedMail($this->purchase, $downloadUrl)
);
}
}Користувач повинен мати можливість завантажити книгу повторно через /library. Там список усіх покупок з кнопкою «Завантажити», яка викликає ендпоінт генерації нового temporary URL. Це важливо — зберігати постійне посилання в базі немає сенсу, воно прострочиться.
Що входить у роботу
| Етап | Деталі |
|---|---|
| Аналітика | Визначення вимог до захисту, вибір S3, платіжної системи |
| Проектування | Схема БД, архітектура доставки, налаштування webhook |
| Реалізація | Інтеграція Stripe, S3, генерація посилань, watermark |
| Тестування | Перевірка оплати, завантаження, повернень |
| Деплой | Розгортання на продакшн, налаштування моніторингу |
| Документація | Опис API, інструкція для адміністратора |
| Підтримка | 30 днів після деплою: консультації, виправлення помилок |
Ми також навчаємо вашу команду роботі з адмінкою та надаємо доступ до вихідного коду. Зв'яжіться з нами, щоб оцінити ваш проєкт.
Порівняння способів захисту
| Метод | Надійність | Швидкість | Складність |
|---|---|---|---|
| Підписані посилання S3 | Висока | Миттєво | Низька |
| Watermark | Середня | 2–5 с | Середня |
| DRM (Adobe, LCP) | Максимальна | Залежить від сервісу | Висока |
Строки орієнтовно
| Задача | Час |
|---|---|
| Завантаження файлів, S3, захист | 1 день |
| Платіжна інтеграція + webhook | 1–2 дні |
| Особиста бібліотека, повторне завантаження | 1 день |
| Email-доставка | 0.5 дня |
| Watermark (PDF) | 1–2 дні |
Базова реалізація без watermark — 3–4 дні. Вартість розраховується індивідуально. Отримайте консультацію — ми підберемо оптимальне рішення під ваш бюджет.
Як ми працюємо: покроково
- Аналіз — вивчаємо ваш поточний стек та вимоги до захисту.
- Проектування — створюємо схему БД та архітектуру доставки.
- Інтеграція — підключаємо Stripe, S3, генеруємо підписані посилання.
- Тестування — перевіряємо сценарії оплати, завантаження та повернень.
- Деплой — викладаємо на продакшн та налаштовуємо моніторинг.
Кожен етап завершується демонстрацією замовнику. Ми гарантуємо прозорість та дотримання строків. Така реалізація скорочує час виведення на ринок з двох тижнів до трьох днів, економлячи до 70% бюджету на розробку.







