Реалізація продажу електронних книг (PDF/EPUB) на сайті

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

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

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

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

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Реалізація продажу електронних книг (PDF/EPUB) на сайті
Середня
~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

Реалізація продажу електронних книг (PDF/EPUB) на сайті

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

Схема доставки файлів

Головне правило: файли не повинні лежати в публічно доступній директорії. Ніяких /public/books/my-book.pdf. Сховище — S3-сумісне об'єктне сховище (AWS S3, Cloudflare R2, MinIO) без публічного ACL.

Після підтвердження оплати користувач отримує тимчасове підписане посилання:

// 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 завантажень на покупку.

Платіжна інтеграція

Для цифрових товарів Stripe рекомендує payment_intent або checkout.session. Ключевий момент — флаг оподаткування: цифрові книги в деяких юрисдикціях облагаються НДС інакше, ніж фізичні товари. 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, але психологічно стримує розповсюдження.

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
ProcessPurchase::dispatch($purchase)->onQueue('purchases');

// У Job
class ProcessPurchase implements ShouldQueue {
    public function handle() {
        // 1. Генеруємо watermark (опціонально)
        // 2. Створюємо підписане посилання
        // 3. Надсилаємо листа
        Mail::to($this->purchase->user)->send(
            new BookPurchasedMail($this->purchase, $downloadUrl)
        );
    }
}

Особиста бібліотека

Користувач повинен мати можливість завантажити книгу повторно через /library. Там список всіх покупок з кнопкою «Завантажити», що викликає ендпоінт генерації нового temporary URL. Це важливо — зберігати постійне посилання в БД нема сенсу, воно протухне.

Строки

Завдання Час
Завантаження файлів, S3, захист 1 день
Платіжна інтеграція + webhook 1–2 дні
Особиста бібліотека, повторне завантаження 1 день
Email-доставка 0,5 дня
Watermark (PDF) 1–2 дні

Базова реалізація без watermark — 3–4 дні.