Диагностика задачи: зачем ограничивать оплату до подтверждения заказа
В стандартной логике 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 |