В WooCommerce заказ может появляться даже тогда, когда платёж не прошёл: пользователь закрыл страницу, банк отклонил транзакцию, платёжный шлюз вернул ошибку или не дождался callback. Для магазина это обычно выглядит как мусорные заказы в статусе pending или failed, которые потом мешают аналитике, ручной обработке и интеграциям с CRM.
Полностью «не создавать заказ до успешной оплаты» в стандартном checkout WooCommerce нельзя без изменения логики оформления. Но можно добиться практического результата: не сохранять черновик заказа, если платёж не дошёл до подтверждения, либо автоматически удалять такие заказы после неуспешной попытки. Ниже — рабочие варианты, их ограничения и проверка результата.
Когда это действительно проблема
Сценарий обычно один из трёх:
- платёжный шлюз создаёт заказ, но возвращает ошибку до подтверждения;
- покупатель уходит со страницы оплаты, а заказ уже записан в базу;
- интеграция с внешней кассой или CRM получает «пустые» заказы, которые потом приходится фильтровать вручную.
Если у вас много отказов по оплате, такие заказы быстро засоряют список заказов и отчёты. Особенно это заметно, когда подключены вебхуки, автоматические уведомления или синхронизация остатков.
Диагностика: что именно создаёт заказ
Сначала проверьте, где именно возникает запись заказа. В WooCommerce заказ может создаваться:
- до редиректа на платёжную страницу;
- после нажатия кнопки Оформить заказ;
- после ответа платёжного шлюза через callback или webhook;
- плагином оплаты, который сам меняет статус и сохраняет метаданные.
Если заказ появляется в админке сразу после отправки формы, а потом получает статус failed, значит проблема не в сохранении как таковом, а в том, что WooCommerce уже успел создать сущность заказа до подтверждения оплаты. Это штатное поведение для большинства сценариев checkout.
Если же заказ создаётся только после callback от шлюза, а потом остаётся в базе даже при ошибке, тогда нужно смотреть логи конкретного платёжного плагина и его обработчики статусов.
Что проверить перед изменениями
- какой платёжный метод используется: встроенный, сторонний плагин, офлайн-метод;
- есть ли у плагина оплаты собственная настройка поведения при ошибке;
- не создаёт ли заказ кастомный код в
woocommerce_checkout_order_processedили похожем хуке; - включены ли логи WooCommerce и логирование шлюза.
Подходы к решению: плагин, код или очистка после ошибки
| Подход | Когда подходит | Минус |
|---|---|---|
| Настройка платёжного плагина | Если шлюз уже умеет не сохранять неуспешные попытки | Зависит от конкретного плагина |
| Код в теме или мини-плагине | Если нужно точечно менять поведение checkout | Нужно аккуратно тестировать |
| Автоудаление неуспешных заказов | Если заказ всё равно создаётся, но его нужно быстро чистить | Заказ успевает попасть в базу и логи |
На практике чаще всего используют второй или третий вариант. Первый хорош, если у платёжного провайдера есть готовая настройка, но это встречается не всегда.
Решение через код: удалять заказ, если оплата не подтверждена
Ниже пример для кастомного мини-плагина или functions.php дочерней темы. Логика простая: если заказ создан, но платёжный метод вернул отказ или ошибка произошла до подтверждения, заказ переводится в failed и затем удаляется только в тех сценариях, где это безопасно для вашего процесса.
Важно: не удаляйте заказы без проверки. Если у вас есть бухгалтерия, интеграция с 1С или CRM, лучше оставлять заказ в статусе failed, а не стирать его физически. Удаление подходит только для магазинов, где такие записи действительно являются мусором.
add_action('woocommerce_checkout_order_processed', function( $order_id, $posted_data, $order ) {
if ( ! $order instanceof WC_Order ) {
$order = wc_get_order( $order_id );
}
if ( ! $order ) {
return;
}
// Пример: если заказ уже помечен как failed на этапе обработки шлюзом,
// можно оставить его в истории, но не удалять автоматически.
if ( $order->has_status( 'failed' ) ) {
$order->add_order_note( 'Заказ не прошёл оплату и был помечен как failed.' );
}
}, 10, 3 );Если вам нужно именно удаление, делайте это только после явной проверки статуса и только для определённых способов оплаты. Например, для тестового шлюза или для сценариев, где заказ не должен попадать в список вообще.
add_action('woocommerce_order_status_failed', function( $order_id ) {
$order = wc_get_order( $order_id );
if ( ! $order ) {
return;
}
$allowed_gateways = array( 'cod', 'bacs' ); // пример: не удалять офлайн-методы
$payment_method = $order->get_payment_method();
// Удаляем только если это ваш тестовый или временный метод оплаты.
if ( in_array( $payment_method, $allowed_gateways, true ) ) {
return;
}
// Не удаляйте, если заказ уже содержит полезные данные для учёта.
if ( $order->get_total() > 0 ) {
return;
}
wp_delete_post( $order_id, true );
}, 20 );Этот пример намеренно консервативный. В реальном магазине лучше не удалять заказы автоматически, а только переводить их в failed и скрывать из рабочих списков через фильтры админки или отчётов.
Более безопасный вариант: скрыть неуспешные заказы из рабочих списков
Если проблема не в базе, а в том, что менеджеры видят слишком много мусора, лучше не удалять данные, а ограничить отображение. Это безопаснее для аудита и отладки.
Например, можно оставить заказы в базе, но исключить статус failed из некоторых внутренних списков или фильтров в CRM-выгрузке. Такой подход особенно полезен, если платёжный шлюз иногда ошибается, а потом повторно подтверждает оплату.
Проверка результата после внедрения
После изменения логики проверьте не только админку, но и технические следы:
- сделайте тестовый заказ с заведомо неуспешной оплатой;
- убедитесь, что заказ не переходит в рабочий статус вроде
processingилиcompleted; - проверьте, остаётся ли запись в
failedили удаляется по вашему правилу; - посмотрите, не ломаются ли письма WooCommerce и webhook-и;
- проверьте логи платёжного шлюза и WooCommerce > Статус > Логи.
Если заказ всё равно создаётся, но вы его не видите, значит проблема решена на уровне отображения. Если заказ исчезает полностью, убедитесь, что это не мешает возврату средств, спорным операциям и ручной проверке.
Что считать успешным результатом
- неуспешные оплаты не попадают в рабочий список заказов;
- в базе не копятся лишние записи, если вы выбрали удаление;
- успешные оплаты продолжают обрабатываться без задержек;
- вебхуки и уведомления не теряют события.
Частые ошибки и как их исправить
Удаляют все заказы со статусом failed
Это самая опасная ошибка. Статус failed может появляться не только из-за ошибки оплаты, но и после ручной отмены, проблем с банком или временного сбоя шлюза. Если стереть такие заказы, потом будет сложно разбирать спорные ситуации.
Путают ошибку оплаты с отменой заказа
В WooCommerce cancelled и failed — не одно и то же. Если код написан без проверки статуса, можно случайно удалить заказ, который менеджер уже обработал вручную.
Ставят удаление в слишком ранний хук
Если удалять заказ до того, как шлюз успел записать метаданные, можно сломать callback или получить повторную попытку оплаты. Для таких сценариев безопаснее сначала пометить заказ как неуспешный, а удаление вынести в отдельную задачу по расписанию.
Не проверяют конкретный способ оплаты
Один и тот же сайт может использовать несколько методов: карта, СБП, наложенный платёж, банковский перевод. Автоматическое удаление должно быть привязано к конкретному шлюзу, иначе вы потеряете полезные заказы.
Практические советы по безопасности и производительности
Если заказов много, не запускайте массовое удаление прямо в запросе checkout. Это создаёт лишнюю нагрузку и может замедлить оформление. Лучше:
- помечать заказ как неуспешный сразу;
- удалять старые тестовые записи отдельной задачей через WP-Cron или вручную;
- хранить в логах причину отказа, если это помогает поддержке;
- не трогать заказы, которые уже ушли во внешние системы.
Если вам нужно регулярно чистить мусорные заказы, удобнее вынести это в отдельный мини-плагин, а не держать код в теме. Тогда логика не пропадёт при смене шаблона и её проще отключить в случае конфликта.
Для магазинов, где важна чистота базы и SEO-обслуживание сайта, иногда полезно сочетать такую очистку с инструментами вроде Clearfy Pro, но только если вы понимаете, какие именно записи и статусы он затрагивает. Автоматическую чистку заказов лучше всё равно держать под своим контролем.
Если нужен более жёсткий сценарий
Иногда задача звучит иначе: не просто убрать неуспешные заказы, а вообще не создавать их до подтверждения оплаты. Это уже не точечная правка, а изменение checkout-потока. В таком случае придётся смотреть в сторону конкретного платёжного шлюза, кастомной страницы оплаты или отдельной логики оформления, потому что стандартный WooCommerce рассчитан на сохранение заказа до завершения транзакции.
Поэтому в большинстве проектов разумнее не ломать ядро процесса, а ограничить последствия: оставить только полезные статусы, скрыть мусорные записи из рабочих списков и чистить тестовые заказы по понятному правилу.