Как проверить успешность платежа?
Что проверяют
Понимаете ли вы, что фронтенд не может сам решить, что платёж прошёл: истина живёт у платёжного провайдера и на вашем бэкенде. Следом обычно спрашивают, что показать пользователю, если он закрыл вкладку сразу после оплаты или уведомление ещё не пришло.
Как отвечать
Опишите поток целиком и роль фронтенда в нём:
- создание платежа на сервере: бэкенд создаёт платёж у провайдера с суммой из своей базы и ключом идемпотентности, фронтенд получает только идентификатор или токен для платёжной формы. Секретный ключ провайдера в браузер не попадает никогда;
- оплата: виджет провайдера или редирект на его страницу, при необходимости 3-D Secure. Данные карты фронтенд не видит, это же снимает с вас большую часть требований PCI DSS;
- источник истины: провайдер присылает вебхук на бэкенд, тот проверяет подпись или запрашивает статус по API и только тогда помечает заказ оплаченным. Обработчик идемпотентен, потому что уведомление может прийти дважды;
- возврат пользователя: параметры в URL после редиректа вроде
?status=successничего не доказывают, их можно подставить руками. Страница возврата спрашивает статус заказа у своего бэкенда; - ожидание: пока статус
pending, показывайте «Проверяем оплату» и опрашивайте эндпоинт с растущим интервалом и общим лимитом или подпишитесь на SSE и WebSocket. После лимита честно напишите, что подтверждение придёт на почту; - отказы: различайте отказ банка, отмену пользователем и сетевую ошибку, блокируйте повторное нажатие кнопки, чтобы не создать второй платёж.
В React это обычно useQuery из TanStack Query с refetchInterval, который выключается, как только статус стал финальным.
Где спотыкаются
Проверяют статус запросом к API провайдера прямо из браузера с секретным ключом. Ключ виден любому в DevTools, а с ним можно делать возвраты и читать чужие платежи.
Считают платёж успешным по колбэку виджета или параметру в URL и сразу выдают товар. Колбэк говорит лишь о том, что форма отработала, а подтверждение списания приходит на бэкенд.
Не учитывают гонку между редиректом и вебхуком. Пользователь возвращается раньше уведомления, видит «Оплата не прошла» и платит второй раз.