Реалізація системи завантаження файлів після оплати

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

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

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

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

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

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

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

Потік даних

Платіж підтвердив (webhook від еквайєра)
  ↓
PaymentController::webhook()
  ↓
PaymentConfirmedEvent → CreateDownloadLinksListener
  ↓
foreach (order.items as item where item.is_digital):
  CreateDigitalDownloadAction::execute(item)
    → DigitalOrderDownload (token, limits, expiry)
  ↓
DigitalDownloadReadyMail → покупець отримує email
  ↓
Покупець кліває посилання → /download/{token}
  ↓
DigitalDownloadController::download(token)
  → валідація токену
  → стріминг файлу

Обробка webhook платіжної системи

class PaymentWebhookController
{
    public function handle(Request $request, string $provider): JsonResponse
    {
        $handler = PaymentHandlerFactory::make($provider);

        // Верифікуємо підпис вебхука
        if (!$handler->verifySignature($request)) {
            Log::warning('Invalid payment webhook signature', ['provider' => $provider]);
            abort(400);
        }

        $paymentResult = $handler->parse($request);

        if ($paymentResult->isSuccessful()) {
            $order = Order::where('payment_id', $paymentResult->transactionId)->firstOrFail();

            DB::transaction(function () use ($order, $paymentResult) {
                $order->update([
                    'status'     => 'paid',
                    'paid_at'    => now(),
                    'payment_id' => $paymentResult->transactionId,
                ]);

                event(new PaymentConfirmedEvent($order));
            });
        }

        return response()->json(['ok' => true]);
    }
}

Синхронне vs. асинхронне створення посилань

Синхронно (inline у Listener) — покупець отримує email протягом 1–2 секунд після оплати. Підходить для малої кількості позицій.

Асинхронно (через Queue) — надійніше при високому навантаженні. Email може затриматися на кілька секунд, але не затримає HTTP-відповідь вебхука.

class CreateDownloadLinksListener implements ShouldQueue
{
    public $queue = 'digital-downloads';
    public $tries = 5;
    public $backoff = [5, 15, 30, 60, 120];

    public function handle(PaymentConfirmedEvent $event): void
    {
        $order = $event->order;

        $digitalItems = $order->items->filter(
            fn($item) => $item->product->digitalProduct !== null
        );

        foreach ($digitalItems as $item) {
            app(CreateDigitalDownloadAction::class)->execute($item);
        }
    }
}

Стріминг великих файлів

При виданні файлів з PHP важливо не завантажити весь файл у пам'ять. Laravel Storage::download() використовує стріминг автоматично, але для дуже великих файлів (>500 МБ) краще використовувати X-Accel-Redirect (nginx) або presigned URL (S3):

// Варіант 1: X-Accel-Redirect (nginx видає файл напряму, PHP тільки авторизує)
public function downloadViaAccel(DigitalOrderDownload $download): Response
{
    $this->validateDownload($download);
    $this->recordDownload($download);

    $internalPath = '/private-files/' . $download->digitalProduct->storage_path;

    return response('', 200, [
        'X-Accel-Redirect'       => $internalPath,
        'Content-Type'           => $download->digitalProduct->mime_type,
        'Content-Disposition'    => 'attachment; filename="' . $download->digitalProduct->original_filename . '"',
        'X-Content-Type-Options' => 'nosniff',
    ]);
}
# nginx конфіг
location /private-files/ {
    internal;
    alias /var/www/storage/app/private/;
}
// Варіант 2: S3 Presigned URL (для великих файлів, CDN-видача)
public function downloadViaS3(DigitalOrderDownload $download): RedirectResponse
{
    $this->validateDownload($download);
    $this->recordDownload($download);

    $url = Storage::disk('s3')->temporaryUrl(
        path: $download->digitalProduct->storage_path,
        expiration: now()->addMinutes(10),
        options: [
            'ResponseContentDisposition' => sprintf(
                'attachment; filename="%s"',
                $download->digitalProduct->original_filename
            ),
        ]
    );

    return redirect($url);
}

Email з посиланням на скачування

class DigitalDownloadReadyMail extends Mailable
{
    use Queueable, SerializesModels;

    public function __construct(
        private DigitalOrderDownload $download,
    ) {}

    public function envelope(): Envelope
    {
        return new Envelope(
            subject: 'Ваш цифровий продукт готовий до скачування',
        );
    }

    public function content(): Content
    {
        return new Content(
            view: 'mails.digital-download-ready',
            with: [
                'downloadUrl' => route('downloads.show', $this->download->token),
                'expiresAt'   => $this->download->expires_at,
                'remainingDownloads' => $this->download->remaining_downloads,
            ],
        );
    }
}

Графік реалізації

Базова реалізація: обробка webhook + одноразові посилання + email — 2–3 дні. Повна система: кілька типів файлів, стріминг, presigned URLs, обмеження скачувань, керування терміном дії — 4–6 днів.