В фокусе статьи
Исходная задача: сохранить связку корзины, заказа и оплаты
Магазину нужен был checkout, в котором сумма, доставка и резервирование не теряются после перехода покупателя на банковскую страницу.
Технический риск WooCommerce-сценария возникает, когда заказ отмечается как paid сразу после return URL. Покупатель может закрыть вкладку, повторно открыть ссылку или вернуться на сайт до финального статуса от банка.
В кейсе заказ создается в состоянии ожидания оплаты до перехода на vPOS. Backend сохраняет order id, сумму, валюту и внешний payment id, поэтому результат можно проверить и сопоставить без ручного поиска.
- фиксировать состав заказа, скидку, доставку и валюту до создания payment session;
- использовать один внутренний order id во всех вызовах и журналах;
- не создавать новый заказ при повторном нажатии кнопки оплаты;
- отдельно хранить внутренний и внешний идентификаторы платежа.
Решение: webhook и server-side verification управляют статусом
Фронтенд показывает покупателю понятный результат, но источником истины остается проверка платежа на backend.
После оплаты пользователь возвращается на страницу результата, а backend независимо принимает callback или webhook и сверяет подпись, сумму, валюту, order id и допустимость перехода статуса.
Повторная доставка события не создает второй заказ, чек или уведомление: обработчик использует idempotency и сохраняет историю попыток. Pending, failed, paid и refunded остаются отдельными событиями, а не одной перезаписываемой отметкой.
- проверять подлинность события и все критичные поля на сервере;
- разделять статус оплаты, статус заказа и статус фискального чека;
- вести audit trail для повторных callbacks и ручных действий;
- не переводить товар в отгрузку для pending-платежа.
Контроль после запуска: возвраты и ежедневная сверка
После запуска команда должна видеть не только успешные оплаты, но и расхождения между WooCommerce, банком и учетом.
Возврат оформляется как отдельная операция, связанная с исходным платежом. Это важно для частичных возвратов, повторной доставки webhook и последующей фискализации.
Ежедневная сверка сопоставляет подтвержденные оплаты, отмены, возвраты и заказы в ожидании. Команда получает список исключений, а не пытается восстановить картину по скриншотам и переписке.
- не удалять исходную оплату при возврате;
- разбирать расхождения по order id и provider payment id;
- проверять повторные попытки оплаты и устаревшие payment links;
- заранее определить путь поддержки для спорных операций.
FAQ
Можно ли отмечать заказ WooCommerce как оплаченный по return URL?
Нет. Return URL нужен для интерфейса покупателя, но финальный статус должен быть подтвержден серверной проверкой или корректно обработанным webhook.
Как защититься от дубля оплаты или callback?
Сохранить стабильные order id и payment id, использовать idempotency key, проверять допустимый переход статуса и журналировать каждую попытку доставки события.
Что важно для возвратов?
Возврат должен быть отдельной операцией с привязкой к исходному платежу. Он не должен стирать историю заказа или исходный payment record.