Не отправляется изображение на Laravel

Я пытаюсь отправить файл, закрепляемый пользователем, на сервер. Если я пробую проверить, выбран ли вообще файл, то мне вполне выводит информацию о файле:

File {name: '424.jpg', lastModified: 1730399692321, lastModifiedDate: Thu Oct 31 2024 21:34:52 GMT+0300 (Москва, стандартное время), webkitRelativePath: '', size: 173585, …}

Однако на сервере я не получаю файла. Вывод из контроллера:

[2024-11-30 15:03:40] production.DEBUG: Confirm payment request: {"_token":"токен","telegram_user_id":"6665878283","receipt":{"Illuminate\\Http\\UploadedFile":""}} 

Моя форма и её обработка на клиенте:

    // Обработчик кнопки подтверждения оплаты
    $('#paymentForm').on('submit', function (event) {
        event.preventDefault();
        const fileInput = document.getElementById('receipt');
        if (!fileInput.files || fileInput.files.length === 0) {
            popupAlert('Пожалуйста, выберите файл', 'error', 3000);
            return;
        }

        const formData = new FormData();
        const file = fileInput.files[0];
        console.log(file);
        formData.append('receipt', file);

        // Добавьте другие данные формы, если они есть
        $(this).serializeArray().forEach(function(item) {
            formData.append(item.name, item.value);
        });

        for (var pair of formData.entries()) {
            console.log(pair[0]+ ', ' + pair[1]);
        }

        $.ajax({
            url: '/api/investment/confirm-payment',
            method: 'POST',
            data: formData,
            processData: false,
            contentType: false,
            success: function (response) {
                console.log('Success:', response);
                popupAlert('Платеж успешно подтвержден', 'success', 3000);
                $('.investment_payment_details, .payment_instructions').fadeOut(300);
            },
            error: function (xhr) {
                console.error('Error:', xhr.responseJSON);
                popupAlert(xhr.responseJSON?.message || 'Ошибка при загрузке чека', 'error', 3000);
            }
        });
    });
    </script>
        <form id="paymentForm" enctype="multipart/form-data" class="upload-container">
            @csrf
            <input type="file"
                id="receipt"
                name="receipt"
                accept="image/*"
                style="display: none;"
                onchange="handleFileSelect(this)">

            <input type="hidden" name="telegram_user_id" value="{{ $user->telegram_user_id }}">

            <button type="button"
                class="btn-secondary upload-receipt-btn"
                onclick="document.getElementById('receipt').click()">
                <img src="{{ asset('images/app/attach.png') }}" alt="Прикрепить">
                Прикрепить чек
            </button>

            <div class="selected-file" style="display: none;">
                <span class="file-name"></span>
                <button type="button" class="remove-file" onclick="removeFile()">
                    <img src="{{ asset('images/app/close.png') }}" alt="Удалить">
                </button>
            </div>
        </form>

И мой контроллер:

public function confirmPayment(Request $request)
{
    // Валидация входящих данных
    Log::debug('Confirm payment request:', $request->all());
    $validated = $request->validate([
        'telegram_user_id' => 'required|exists:telegram_users,telegram_user_id',
        'receipt' => 'required|file|image',
    ], [
        'receipt.required' => 'Файл с чеком обязателен.',
        'receipt.file' => 'Файл с чеком обязателен.',
        'receipt.image' => 'Файл с чеком обязателен.',
    ]);

    try {
        // Ищем активный код пользователя
        $code = OneTimeCode::where('used_by_telegram_id', $request->post('telegram_user_id'))
            ->where('is_used', false)
            ->where(function($query) {
                $query->whereNull('expires_at')
                      ->orWhere('expires_at', '>', now());
            })
            ->firstOrFail();

        $code->receipt_path = $request->file('receipt')->store('receipts', 'public');
        $code->is_used = true;
        $code->save();

        return response()->json([
            'status' => 'success',
            'message' => 'Платёж успешно подтверждён'
        ]);

    } catch (\Exception $e) {
        Log::error('Payment confirmation error: ' . $e->getMessage());
        return response()->json([
            'status' => 'error',
            'message' => 'Не удалось подтвердить платёж: ' . $e->getMessage()
        ], 422);
    }
}

Ответы (0 шт):