Задать вопрос
@html_student
Молодой и глупый.

Ошибка при попытке редиректа CORS?

Есть форма для приема платежей

<form id="paymentForm"  method="post">
    <input type="hidden" name="uid" value="<? echo $_SESSION['SESS_AUTH']['USER_ID'];?>"> 
    <button type="button button-color-2 button-payment-online" id="paymentButton">Оплатить</button>
</form>


document.addEventListener("DOMContentLoaded", function() {
    document.getElementById("paymentButton").addEventListener("click", function() {
        console.log('Кнопка нажата');
        pay();
    });
});

function pay() {
    // AJAX-запрос на сервер для инициации платежа
    fetch('/yookassa/pay.php', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            uid: document.querySelector('input[name="uid"]').value
        })
    })
    .then(response => response.json())
    .then(data => {
        if (data.success) {
            // Перенаправляем пользователя на страницу оплаты ЮKassa
            alert('Успех: ' + data);
        } else {
            alert('Ошибка: ' + data.message);
        }
    });
}

Отправляю на PHP файл

<?php
require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php');

// Данные для аутентификации
$shopId = '444444';
$secretKey = 'test_8h3Hee3cU90BqgW4cXN0aBWA017IA6pmEot8Z9fefadfdfO3s';

// Данные для создания платежа
$paymentAmount = '100.00';  // Сумма платежа
$currency = 'RUB';  // Валюта
$returnUrl = 'https://site.ru/yookassa/payment_success.php';  // URL, на который вернется пользователь после оплаты
$description = 'Заказ №1';  // Описание платежа

// Генерация уникального ключа идемпотентности
$idempotenceKey = uniqid('', true);

// Создание массива данных для отправки
$data = [
    'amount' => [
        'value' => $paymentAmount,
        'currency' => $currency
    ],
    'capture' => true,  // Захват средств после оплаты
    'confirmation' => [
        'type' => 'redirect',
        'return_url' => $returnUrl
    ],
    'description' => $description
];

// Инициализация cURL
$ch = curl_init('https://api.yookassa.ru/v3/payments');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Idempotence-Key: ' . $idempotenceKey,
    'Authorization: Basic ' . base64_encode($shopId . ':' . $secretKey),
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));

// Выполнение запроса и получение результата
$result = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

// Декодируем ответ от API
$response = json_decode($result, true);

// Логирование ответа для отладки
$logData = "HTTP Code: $httpCode\nResponse: $result\n";
file_put_contents($_SERVER['DOCUMENT_ROOT'] . '/yookassa/payment_creation.log', $logData . PHP_EOL, FILE_APPEND);

if ($httpCode === 200 && !empty($response['id'])) {
    // Перенаправление пользователя на страницу оплаты
    header('Location: ' . $response['confirmation']['confirmation_url']);
    exit();
} else {
    // Логируем ошибку и выводим сообщение
    $errorMessage = isset($response['description']) ? $response['description'] : 'Неизвестная ошибка';
    echo '<script>alert("Ошибка создания платежа: ' . $errorMessage . '");</script>';
}


В целом всё отлично отправляет и даже возвращает нормальный ответ в payment_creation.log
HTTP Code: 200
Response: {
  "id" : "2e651283-000f-5000-9000-1ace9a103003",
  "status" : "pending",
  "amount" : {
    "value" : "100.00",
    "currency" : "RUB"
  },
  "description" : "Заказ №1",
  "recipient" : {
    "account_id" : "444444",
    "gateway_id" : "2310415"
  },
  "created_at" : "2024-08-31T11:30:11.287Z",
  "confirmation" : {
    "type" : "redirect",
    "confirmation_url" : "https://yoomoney.ru/checkout/payments/v2/contract?orderId=2e6512434383-000f-5000-9000-1ace9a103003"
  },
  "test" : true,
  "paid" : false,
  "refundable" : false,
  "metadata" : { }
}


Но сайт не редиректит
66d305514ad0c155934161.png
По факту то у меня идет же серверный редирект а не клиентский, почему такая проблема?
  • Вопрос задан
  • 126 просмотров
Подписаться 1 Простой 3 комментария
Решения вопроса 2
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Перенаправление через Location - это фактически команда браузеру сделать новый запрос. А, поскольку изначальный запрос был через fetch, то и новый запрос пойдёт через него. Ну а fetch не может сделать новый запрос из-за нарушения CORS.
Выход - делать оплату в отдельном окне не используя AJAX или отправлять команду на переадресацию в ответе скрипта и выполнять её средствами JS.
Ответ написан
Комментировать
nokimaro
@nokimaro
Меня невозможно остановить, если я смогу начать.
Внутри pay.php вместо header location возвращайте json-ответ

echo json_encode(['url' => $response['confirmation']['confirmation_url']]);
exit;


Соотв-но через fetch получаете в ответе json-объект от php, декодируете его, находите нужный url и делаете редирект средствами браузера например через window.location
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы