WooCommerce: как разрешить оплату заказа только после его подтверждения

Диагностика задачи: зачем ограничивать оплату до подтверждения заказа

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

Типичные ситуации, когда нужна такая логика:

  • Предзаказ товаров, которых пока нет в наличии.
  • Заказы с индивидуальными условиями, требующими ручного подтверждения.
  • Оплата по счету с последующим выставлением счета.

Как реализовать ограничение оплаты до подтверждения заказа

Шаг 1. Добавляем кастомное поле «Подтвержден» к заказам

Сначала нам нужно добавить метаполе к заказу, которое будет хранить статус подтверждения. По умолчанию оно будет false.

add_action('woocommerce_checkout_update_order_meta', 'wpexperts_add_confirmed_flag_to_order');
function wpexperts_add_confirmed_flag_to_order( $order_id ) {
    update_post_meta( $order_id, '_order_confirmed', 'no' );
}

Шаг 2. Отключаем способы оплаты, если заказ не подтверждён

Для этого используем фильтр woocommerce_available_payment_gateways. При оформлении заказа платежные системы будут недоступны, если статус не подтвержден.

add_filter('woocommerce_available_payment_gateways', 'wpexperts_disable_payment_if_not_confirmed');
function wpexperts_disable_payment_if_not_confirmed( $available_gateways ) {
    if ( is_admin() ) return $available_gateways; // Не трогаем админку

    if ( ! is_checkout() ) return $available_gateways; // Только на странице оформления

    $order_id = absint( WC()->session->get( 'order_awaiting_payment' ) );
    if ( ! $order_id ) {
        // При первом оформлении заказа платежи доступны
        return $available_gateways;
    }

    $confirmed = get_post_meta( $order_id, '_order_confirmed', true );

    if ( $confirmed !== 'yes' ) {
        // Убираем все платежные шлюзы
        return array();
    }

    return $available_gateways;
}

Шаг 3. Реализация подтверждения заказа администратором

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

add_action('add_meta_boxes', 'wpexperts_add_confirm_button_meta_box');
function wpexperts_add_confirm_button_meta_box() {
    add_meta_box('wpexperts_confirm_order', 'Подтверждение заказа', 'wpexperts_confirm_order_meta_box_callback', 'shop_order', 'side', 'high');
}

function wpexperts_confirm_order_meta_box_callback($post) {
    $confirmed = get_post_meta($post->ID, '_order_confirmed', true);
    if ($confirmed === 'yes') {
        echo '<p>Заказ подтверждён</p>';
    } else {
        echo '<form method="post">';
        wp_nonce_field('wpexperts_confirm_order_action', 'wpexperts_confirm_order_nonce');
        echo '<input type="hidden" name="order_id" value="' . esc_attr($post->ID) . '" />';
        echo '<input type="submit" name="confirm_order" class="button button-primary" value="Подтвердить заказ" />';
        echo '</form>';
    }
}

add_action('admin_init', 'wpexperts_handle_confirm_order');
function wpexperts_handle_confirm_order() {
    if ( ! isset($_POST['confirm_order']) ) return;
    if ( ! isset($_POST['wpexperts_confirm_order_nonce']) || ! wp_verify_nonce($_POST['wpexperts_confirm_order_nonce'], 'wpexperts_confirm_order_action') ) return;
    if ( ! current_user_can('edit_shop_orders') ) return;

    $order_id = absint($_POST['order_id']);
    update_post_meta($order_id, '_order_confirmed', 'yes');

    // Можно отправить уведомление клиенту, что заказ подтверждён
    wp_redirect(admin_url('post.php?post=' . $order_id . '&action=edit&confirmed=1'));
    exit;
}

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

  • Создайте новый заказ через фронтенд — платежные методы должны быть доступны.
  • Перейдите в админку, откройте заказ и проверьте, что он не подтверждён (нет текста «Заказ подтверждён»).
  • Проверьте, что при повторном заходе на страницу оплаты платежные методы отключены, если заказ не подтвердили.
  • Нажмите кнопку «Подтвердить заказ» в админке.
  • Вернитесь на страницу оплаты — платежные методы должны вновь появиться.

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

  • Платежные методы всегда доступны: возможно, сессия order_awaiting_payment не установлена. Проверьте, что вы тестируете на странице оплаты существующего заказа.
  • Кнопка подтверждения не работает: проверьте nonce, права пользователя и корректность передачи ID заказа.
  • Заказы не обновляют статус: убедитесь, что метаполе _order_confirmed действительно создаётся и обновляется через wp_postmeta.

Практические советы по безопасности и производительности

  • Используйте nonce и проверку прав для действий в админке.
  • Не отключайте платежные методы на страницах, отличных от оформления заказа или оплаты.
  • Кэширование страниц с оплатой отключите или учитывайте динамические изменения доступных платежей.
  • Добавьте уведомления клиенту о статусе подтверждения (например, письма или сообщения в личном кабинете).

Сравнение подходов: плагин vs кастомный код

ПодходПреимуществаНедостатки
Использование плагина (например, «WooCommerce Pre-Orders» или «Order Approval for WooCommerce»)Готовое решение с поддержкой, удобный интерфейс, меньше кодаМожет быть платным, избыточным, не всегда подходит под специфические задачи
Кастомный код (как в статье)Точный контроль, нет зависимостей, легко интегрируется в существующую логикуТребует навыков PHP, может потребовать поддержки при обновлениях WooCommerce
Как избежать конфликтов между темами WordPress
15.03.2026
Автоматическое отключение неиспользуемых плагинов в WordPress
20.03.2026
Как создать адаптивный и ленивый загрузчик изображений в WordPress
08.03.2026
WooCommerce: автоматическое отключение товаров при нулевом остатке без плагинов
16.06.2026
WooCommerce: автоматическое отключение товаров при нулевом остатке без плагинов
19.06.2026