Добрый день. На ровном месте, на двух проектах перестала работать ЮКасса, вернее перестали обновляться данные в базе данных MySQL. Поддержка ЮКассы говорит, что ответ от обработчика приходит с ответом 200 ОК. Но данные в базе данных у меня не добавляются и не изменяются (не устанавливается подписка у пользователя).
Я создал тестовый файл с полной эмуляцией запроса от ЮКассы - и он срабатывает корректно. Хостинг Джино говорит, что на их стороне проблем нет.
Вот файл, который принимает callback от ЮКассы:
<?php
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/connect.php';
session_start();
// Устанавливаем часовой пояс Москвы (UTC+3)
date_default_timezone_set('Europe/Moscow');
$input = file_get_contents('php://input');
$data = json_decode($input, true);
// Проверка необходимых полей
if (!isset($data['event'], $data['object']['id'], $data['object']['status'], $data['object']['metadata']['nickname'])) {
http_response_code(400);
exit('Некорректный запрос');
}
$payment_id = $data['object']['id'];
$status = $data['object']['status'];
$nickname = $data['object']['metadata']['nickname'];
// Обработка только успешных платежей
if ($data['event'] !== 'payment.succeeded' || $status !== 'succeeded') {
http_response_code(200);
exit('Не требуется обработка');
}
// Защита от повторной обработки
$stmt = $db->prepare("SELECT id FROM payments WHERE payment_id = ?");
$stmt->bind_param("s", $payment_id);
$stmt->execute();
$stmt->store_result();
if ($stmt->num_rows > 0) {
http_response_code(200);
exit('Уже обработано');
}
$stmt->close();
// Получение суммы
$amount = $data['object']['amount']['value'];
// Привязка тарифа по сумме
$tariffs = [
'39.00' => ['subscribe_days' => 7, 'subscribe_rates' => 2],
'97.00' => ['subscribe_days' => 7, 'subscribe_rates' => 3],
'69.00' => ['subscribe_days' => 14, 'subscribe_rates' => 2],
'176.00' => ['subscribe_days' => 14, 'subscribe_rates' => 3],
'118.00' => ['subscribe_days' => 30, 'subscribe_rates' => 2],
'249.00' => ['subscribe_days' => 30, 'subscribe_rates' => 3],
'290.00' => ['subscribe_days' => 90, 'subscribe_rates' => 2],
'689.00' => ['subscribe_days' => 90, 'subscribe_rates' => 3],
];
if (!isset($tariffs[$amount])) {
http_response_code(400);
exit('Неизвестная сумма');
}
$subscribe_days = $tariffs[$amount]['subscribe_days'];
$subscribe_rates = $tariffs[$amount]['subscribe_rates'];
// Получение текущей подписки пользователя
$stmt = $db->prepare("SELECT subscribe_date FROM users WHERE nickname = ?");
$stmt->bind_param("s", $nickname);
$stmt->execute();
$stmt->bind_result($current_subscribe_date);
$stmt->fetch();
$stmt->close();
// Вычисление новой даты подписки с временем
$now = new DateTime();
$subscribe_end = new DateTime($current_subscribe_date);
if ($now > $subscribe_end) {
$new_subscribe_date = $now->modify("+$subscribe_days days")->format('Y-m-d H:i:s');
} else {
$new_subscribe_date = $subscribe_end->modify("+$subscribe_days days")->format('Y-m-d H:i:s');
}
// Обновление данных пользователя
$stmt = $db->prepare("UPDATE users SET subscribe_date = ?, subscribe_rate = ? WHERE nickname = ?");
$stmt->bind_param("sis", $new_subscribe_date, $subscribe_rates, $nickname);
$stmt->execute();
$stmt->close();
// Сохранение информации о платеже
$stmt = $db->prepare("INSERT INTO payments (payment_id, nickname, amount, status) VALUES (?, ?, ?, ?)");
$stmt->bind_param("ssds", $payment_id, $nickname, $amount, $status);
$stmt->execute();
$stmt->close();
http_response_code(200);
echo 'OK';
?>
Вот код тестового файла:
<?php
/**
* ТЕСТОВЫЙ ЭМУЛЯТОР CALLBACK YOOKASSA
*/
header('Content-Type: text/plain; charset=utf-8');
// URL куда отправляем "вебхук" — ваш обработчик Юкассы
$callbackUrl = 'https://site.ru/pay.php';
// тестовый JSON полностью повторяет структуру YooKassa
$fakeCallbackData = [
"event" => "payment.succeeded",
"object" => [
"id" => "2e4f82c2-000f-5010-9000-29fca13db031", // любой ID (уникальный для теста)
"status" => "succeeded",
"paid" => true,
"amount" => [
"value" => "39.00",
"currency" => "RUB"
],
"metadata" => [
"nickname" => "legolas"
],
"description" => "Test payment",
]
];
// JSON в нужном виде как у Юкассы
$jsonData = json_encode($fakeCallbackData, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
// Инициируем CURL
$ch = curl_init($callbackUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Content-Type: application/json",
"Idempotence-Key: " . time(), // как у YooKassa
"User-Agent: AHC/2.1",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
curl_setopt($ch, CURLOPT_HEADER, true); // чтобы получить заголовки ответа
// Выполняем запрос
$response = curl_exec($ch);
$errno = curl_errno($ch);
$error = curl_error($ch);
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$responseHeaders = substr($response, 0, $headerSize);
$responseBody = substr($response, $headerSize);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$totalTime = curl_getinfo($ch, CURLINFO_TOTAL_TIME);
curl_close($ch);
// ---- Вывод результатов ----
echo "===== ОТПРАВЛЕННЫЙ JSON =====\n$jsonData\n\n";
echo "===== URL КУДА ОТПРАВЛЕНО =====\n$callbackUrl\n\n";
echo "===== HTTP CODE =====\n$httpCode\n\n";
echo "===== ВРЕМЯ ЗАПРОСА =====\n{$totalTime} сек.\n\n";
echo "===== ОТВЕТНЫЕ ЗАГОЛОВКИ =====\n$responseHeaders\n\n";
echo "===== ТЕЛО ОТВЕТА PAY-NOTICE =====\n$responseBody\n\n";
if ($errno) {
echo "===== CURL ERROR =====\n$errno: $error\n\n";
}
echo "===== ТЕСТ ЗАВЕРШЁН =====\n";
?>
Если я сам лично перехожу по тестовому файлу - Всё работает корректно. Когда проходит реальный платеж от ЮКассы, то данные в базе данных не обновляются (и не вставляется запись о платеже).
Вот ответ поддержки Юкассы:
На примере платежа 30869025-000f-5001-8000-12d1032446bc обработчик магазина успешно принял уведомление. Соответственно, статус заказа должен был обновиться. Указанный в настройках URL для уведомлений можно посмотреть тут: https://yookassa.ru/my/merchant/integration/http-n....
- Если у вас какое-то готовое решение (CMS/CRM), обратитесь в поддержку решения с логами ниже.
- Если у вас самописная интеграция, причину нужно искать на вашей стороне. Документация тут: https://yookassa.ru/developers/using-api/webhooks.
Наш запрос:
Oct 19, 2025 @ 08:51:54.408406945
sendNotificationAsync(): url=https://site.ru/pay.php, request.object={
"id" : "30869025-000f-5001-8000-12d1032446bc",
"status" : "succeeded",
"amount" : {
"value" : "39.00",
"currency" : "RUB"
},
"income_amount" : {
"value" : "38.37",
"currency" : "RUB"
},
"description" : "Оплата подписки на сервисе тарифу",
"recipient" : {
"account_id" : "1333333",
"gateway_id" : "2445561"
},
"payment_method" : {
"type" : "sbp",
"id" : "30869025-000f-5001-8000-12d1032446bc",
"saved" : false,
"status" : "inactive",
"sbp_operation_id" : "B52920551524010J0020120011611166",
"payer_bank_details" : {
"bank_id" : "100000020111",
"bic" : "044525223"
}
},
"captured_at" : "2025-10-19T05:51:54.205Z",
"created_at" : "2025-10-19T05:51:33.962Z",
"test" : false,
"refunded_amount" : {
"value" : "0.00",
"currency" : "RUB"
},
"paid" : true,
"refundable" : true,
"receipt_registration" : "pending",
"metadata" : {
"nickname" : "legolas"
}
}, headers=[Signature: v1 3086903a 1 MGQCMEnBnHeqpkd17dI9XD1csl91tbyCyVWlXgTxT4G+DDRgtSQZ15654bZOTtFC1t5MgIwVMVLDPVhOQM5tnViKRbLq4rfHM2tCKYrUR12YjUVylw61UOB67H0fK/BGB2po7xD, Content-Type: application/json, User-Agent: AHC/2.1, Accept: */*]
Ответ обработчика:
Oct 19, 2025 @ 08:51:54.478363339
END http request: method=POST, url=https://site.ru/pay.php, status=200, time.ms=20
В чём проблема вообще понять не могу, всё уже перепробовал, не пойму что сломалось, хотя сам ничего не делал. Сломалось сразу одновременно на двух проектах (стоят на одном и том же хостинге Джино). Есть какие-то мысли? Подскажите пожалуйста.