Короткий ответ

Создание платежа, idempotency, webhook/callback, подпись, статусы, возвраты и связь с заказом. Разбираем практический порядок работ, риски, стоимость и то, как принять результат без новых проблем.

Ниже — конкретные проверки, команды, таблицы и контроль результата. Выполняйте изменения только после резервной копии, если действие затрагивает рабочую систему.

Жизненный цикл оплаты

Этап
ранить
Создание заказаmsOrder id
Создание платежаexternal payment id
Redirect
од
Webhook/callbackсерверное событие
Проверка статуса
одимости
Paid statusменять один раз, идемпотентно
Refundотдельный статус/история

return_url не подтверждает оплату

Пользователь может закрыть страницу или вручную открыть URL успеха. Статус заказа меняйте только после подтверждённого серверного события/API платёжного провайдера.

Идемпотентный callback — принцип

PHP
$paymentId = (string)$payload['payment_id'];

$order = findOrderByPaymentId($paymentId);
if (!$order) {
    http_response_code(404);
    exit;
}

if ($order->get('status') == PAID_STATUS_ID) {
    http_response_code(200);
    exit('already processed');
}

// verifyProviderStatus($paymentId)
// затем изменить статус ровно один раз

Как проверить результат

После изменений повторите исходный сценарий, зафиксируйте результат и убедитесь, что соседние функции работают так же, как до правки. Если проблема проявляется не всегда, проведите несколько повторов в одинаковых условиях и сохраните диагностические данные.

Связанные материалы

Платёжный callback и идемпотентность

Возврат покупателя со страницы оплаты и серверное уведомление провайдера — разные события. Изменять статус заказа на «Оплачен» следует только после достоверной серверной проверки платежа: подписи/авторизации уведомления и сверки идентификатора, суммы и валюты с заказом. Повторные callback должны обрабатываться идемпотентно, без повторной выдачи цифрового товара и повторного создания заказа.

В тестировании нужны успешная оплата, отказ, задержанный webhook, повторная доставка webhook и возврат. Секреты провайдера нельзя записывать в открытые логи.