Правильный жизненный цикл платежа

  1. сайт создаёт локальный заказ;
  2. сервер создаёт платёж у провайдера;
  3. сохраняет payment_id;
  4. отправляет пользователя на подтверждение;
  5. принимает webhook;
  6. проверяет статус платежа;
  7. только после подтверждённого статуса помечает заказ оплаченным.

Что нельзя считать подтверждением оплаты

СобытиеДостаточно?
Пользователь открыл return_urlнет
JS показал successнет
Webhook пришёл один разнужно проверить подлинность/статус
API вернул succeeded/финальный статусда, согласно модели провайдера
Локальный order status изменился вручнуюнет

Пример создания платежа с ключом идемпотентности

PHP
$idempotencyKey = bin2hex(random_bytes(16));

$payload = [
    'amount' => ['value' => '100.00', 'currency' => 'RUB'],
    'capture' => true,
    'confirmation' => [
        'type' => 'redirect',
        'return_url' => 'https://example.com/order/123/return',
    ],
    'description' => 'Заказ #123',
];

// Отправляйте запрос С СЕРВЕРА.
// Ключ идемпотентности сохраняйте вместе с попыткой операции.

Повторный POST должен быть безопасным

При сетевой ошибке клиент может не знать, создался платёж или нет. Поэтому платёжные API используют идемпотентность: повтор той же операции с тем же ключом не должен создавать вторую транзакцию.

Webhook должен переживать повторы

Платёжный провайдер может доставлять уведомление несколько раз. Сохраняйте event/payment id и обновляйте заказ идемпотентно.

Что тестировать до запуска

СценарийПроверка
Успешная оплатазаказ paid один раз
Пользователь закрыл оплатузаказ не становится paid
Webhook пришёл дваждынет дубля операции
Timeout APIбезопасный повтор
Возврат
ронизирован
Неверная сумма/statusзаказ не подтверждён автоматически

Return URL и webhook решают разные задачи

Return URL нужен для интерфейса пользователя. Webhook/API — для серверной фиксации результата. Не связывайте бухгалтерский статус заказа только с браузерным переходом.

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

Сценарии проверки подключения онлайн-оплаты

Тестируйте полный цикл: создание платежа, успешное подтверждение, отказ, обрыв связи, позднее уведомление, повторный webhook и возврат. Изменять статус заказа следует только по проверенному серверному событию, а не по одному открытию страницы «Спасибо». Платёжный идентификатор, сумма и валюта должны сверяться с данными заказа.

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