wpcoding.ru wordpress WP Coding

WooCommerce: как отключить создание заказа без оплаты

В WooCommerce заказ может появляться еще до фактической оплаты — например, при переходе на страницу благодарности, при выборе некоторых офлайн-способов оплаты или из-за особенностей платежного шлюза. Для части магазинов это нормально, но если вам нужен строгий сценарий «сначала деньги, потом заказ», поведение приходится менять вручную.

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

Когда это действительно проблема

Сценарий обычно всплывает в трех случаях:

  • заказ создается в статусе pending или on-hold, хотя оплата еще не прошла;
  • менеджеры видят в админке «пустые» или неоплаченные заказы и начинают обрабатывать их вручную;
  • внешние интеграции — CRM, склад, ERP — получают событие о новом заказе раньше оплаты и создают лишние записи.

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

Диагностика: что именно создает заказ

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

  1. Откройте тестовый заказ в админке WooCommerce.
  2. Посмотрите статус сразу после оформления.
  3. Проверьте, меняется ли статус после возврата с платежной страницы или после webhook/callback от шлюза.
  4. Сравните поведение для разных методов оплаты: карта, наличные при получении, банковский перевод, Stripe/CloudPayments/ЮKassa и т.д.

Если заказ создается сразу, но оплата подтверждается позже, это штатное поведение WooCommerce. Если же заказ остается неоплаченным и дальше обрабатывается как обычный, значит нужно ограничить дальнейшие действия по статусу или по способу оплаты.

Что смотреть в логах

Для платежных шлюзов полезно включить логирование в их настройках. В WooCommerce также можно посмотреть журнал ошибок, если шлюз пишет в стандартный лог. Ищите:

  • callback/webhook пришел, но заказ не найден;
  • заказ создан, но статус не меняется на processing или completed после оплаты;
  • платежный метод возвращает pending и не отправляет подтверждение.

Рабочее решение: не запускать обработку до оплаты

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

add_action('woocommerce_payment_complete', function( $order_id ) {
    $order = wc_get_order( $order_id );

    if ( ! $order ) {
        return;
    }

    // Если заказ уже обработан, ничего не делаем.
    if ( in_array( $order->get_status(), array( 'processing', 'completed' ), true ) ) {
        return;
    }

    // Здесь можно добавить свою логику: уведомления, синхронизацию, склад.
    // Для обычного магазина достаточно перевести заказ в processing.
    if ( $order->needs_processing() ) {
        $order->update_status( 'processing', 'Оплата подтверждена, заказ переведен в обработку.' );
    } else {
        $order->update_status( 'completed', 'Оплата подтверждена, заказ завершен.' );
    }
});

Этот вариант не ломает checkout и не мешает шлюзам, которые подтверждают оплату асинхронно. Но если вам нужно именно не создавать заказ для некоторых способов оплаты, фильтровать нужно уже на уровне доступности метода оплаты или поведения checkout.

Если нужно скрыть способ оплаты до выполнения условий

Частая задача — не запрещать заказ целиком, а убрать методы, которые не должны создавать неоплаченные заявки. Например, оставить только онлайн-оплату и скрыть bacs или cod для определенных корзин. Для этого подходит фильтр woocommerce_available_payment_gateways.

add_filter('woocommerce_available_payment_gateways', function( $gateways ) {
    if ( is_admin() ) {
        return $gateways;
    }

    if ( ! WC()->cart ) {
        return $gateways;
    }

    $total = (float) WC()->cart->get_total( 'edit' );

    // Пример: если сумма нулевая или корзина пустая, убираем офлайн-методы.
    if ( $total <= 0 ) {
        unset( $gateways['bacs'] );
        unset( $gateways['cod'] );
    }

    return $gateways;
});

Если у вас задача жестче — например, не создавать заказ до оплаты в конкретном сценарии — обычно это решается не отключением WooCommerce, а настройкой шлюза или изменением бизнес-логики: сначала редирект на оплату, потом создание заказа через подтвержденный callback.

Сравнение подходов

ПодходЧто делаетПлюсыМинусы
Оставить заказ, но обрабатывать только после оплатыЗаказ создается, рабочие действия запускаются после payment_completeСовместимо с большинством шлюзовНе убирает сам факт создания заказа
Скрывать офлайн-методы оплатыУбирает способы, которые создают неоплаченные заказыПросто внедритьНе подходит, если офлайн-оплата нужна
Менять логику шлюза/checkoutСоздание заказа переносится после подтверждения оплатыМаксимально строгий сценарийСложнее поддерживать, зависит от платежки

Пошагово: как внедрить без риска

  1. Сделайте резервную копию файлов и базы.
  2. Добавьте код в дочернюю тему или в небольшой mu-plugin, а не в файл темы, который может затереться при обновлении.
  3. Проверьте, какие статусы выставляет ваш платежный шлюз.
  4. Протестируйте оформление с тестовой оплатой и с офлайн-методом.
  5. Убедитесь, что письма, CRM и склад запускаются только после подтверждения оплаты.

Пример mu-plugin

Если не хотите зависеть от темы, создайте файл wp-content/mu-plugins/wc-payment-control.php и поместите туда код. Это удобнее для точечных бизнес-правил: логика не исчезнет после смены темы.

<?php
/**
 * Plugin Name: WC Payment Control
 */

add_action('woocommerce_payment_complete', function( $order_id ) {
    $order = wc_get_order( $order_id );

    if ( ! $order ) {
        return;
    }

    // Пример: не отправлять заказ в CRM, пока не подтверждена оплата.
    do_action( 'myshop_order_paid', $order_id );
});

Проверка результата после внедрения

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

  • заказ не попадает в рабочую обработку до оплаты;
  • после успешной оплаты статус меняется ожидаемо;
  • повторный callback не создает дубликат действий;
  • письма клиенту не уходят раньше времени;
  • интеграция с CRM/складом не получает ложный «новый заказ».

Если используете webhooks, отдельно проверьте, что платежный шлюз может достучаться до сайта. Иногда проблема не в WooCommerce, а в блокировке запросов на стороне хостинга, WAF или плагина безопасности.

Частые ошибки и как их исправить

Заказ остается в pending, но его уже обрабатывает склад

Значит, складская интеграция завязана не на статус оплаты, а на событие создания заказа. Перенесите запуск синхронизации на woocommerce_payment_complete или проверяйте $order->is_paid() перед отправкой данных.

Платежный шлюз не меняет статус автоматически

У некоторых методов оплаты подтверждение приходит асинхронно. Если webhook не работает, заказ будет висеть неоплаченным. Проверьте URL callback, SSL-сертификат, доступность сайта извне и логи шлюза.

Код добавили в тему, а после обновления он пропал

Для таких правок используйте дочернюю тему или mu-plugin. Это не косметика, а нормальная практика для бизнес-логики магазина.

Отключили не тот способ оплаты

Фильтр woocommerce_available_payment_gateways работает на доступные шлюзы, но не решает проблему для уже выбранного метода. Если у вас несколько сценариев оплаты, проверяйте ID шлюза и условия отдельно.

Безопасность и производительность

Не стоит проверять оплату «по факту прихода на thank you page». Это ненадежно: пользователь может закрыть вкладку, вернуться назад или открыть страницу повторно. Источником истины должен быть сам заказ и подтверждение от платежного шлюза.

Также не делайте тяжелые запросы в хук woocommerce_payment_complete без необходимости. Если нужно отправить данные во внешнюю систему, лучше вынести это в очередь через WP-Cron или отдельный фоновой обработчик, иначе checkout начнет тормозить на пиковых нагрузках.

Если вам нужно быстро убрать лишние статусы, дубли и шум в админке, полезно сочетать точечный код с чисткой лишней логики в WooCommerce. Для этого иногда хватает аккуратной настройки, а не большого набора плагинов.

Когда задача выходит за рамки одного хука, лучше сначала определить, что именно вам нужно: запретить создание заказа, скрыть офлайн-методы или просто не запускать обработку до оплаты. В WooCommerce это три разных сценария, и у каждого свой безопасный способ решения.

×

Время действовать!

Суперцены на
WordPress!

-20%
на премиум темы

Не упусти шанс ⋙