Диагностика задачи: зачем ограничивать сроки доставки и способы оплаты для отдельных товаров
В WooCommerce стандартно можно настраивать сроки доставки и способы оплаты для всего магазина в целом, но в реальной практике часто требуется более тонкая настройка — например, для товаров с особенными условиями хранения, доставкой с задержкой или специфическими способами оплаты (наложенный платеж, предоплата). Встроенных инструментов для таких ограничений нет, поэтому приходится прибегать к кастомному коду или специализированным плагинам.
Типичные запросы:
- Запретить оплату конкретным способом для определенной категории товаров.
- Установить минимальное или максимальное время доставки для отдельных товаров.
- Скрыть способ доставки, если в корзине есть товар с особыми требованиями.
Как проверить текущие ограничения и поведение WooCommerce
Для диагностики:
- Добавьте в корзину товар, для которого хотите сделать ограничение.
- Перейдите на страницу оформления заказа и проверьте, отображаются ли все способы оплаты и доставки.
- Проверьте в админке WooCommerce — Настройки → Способы доставки и Способы оплаты, нет ли глобальных ограничений, которые мешают.
- Включите режим отладки WooCommerce в
wp-config.php(define('WP_DEBUG', true); define('WP_DEBUG_LOG', true);) и проверьтеwp-content/debug.logна наличие ошибок при загрузке способов оплаты/доставки.
Пошаговое решение: ограничение способов оплаты и сроков доставки для конкретных товаров
1. Ограничение способов оплаты на уровне корзины
Добавим фильтр, который будет убирать из списка способов оплаты те, которые не подходят, если в корзине есть определённые товары (по ID или категории).
add_filter('woocommerce_available_payment_gateways', 'restrict_payment_gateways_for_products');
function restrict_payment_gateways_for_products($available_gateways) {
if (is_admin()) return $available_gateways; // не трогаем админку
$restricted_product_ids = array(123, 456); // ID товаров с ограничениями
$cart_items = WC()->cart->get_cart();
foreach ($cart_items as $item) {
if (in_array($item['product_id'], $restricted_product_ids)) {
// например, запретим 'cod' и 'cheque'
unset($available_gateways['cod']);
unset($available_gateways['cheque']);
break;
}
}
return $available_gateways;
}2. Ограничение способов доставки по товарам
Чтобы скрыть способ доставки при наличии определённых товаров, используем аналогичный фильтр:
add_filter('woocommerce_package_rates', 'restrict_shipping_methods_for_products', 10, 2);
function restrict_shipping_methods_for_products($rates, $package) {
$restricted_product_ids = array(123, 456);
$found = false;
foreach ($package['contents'] as $item) {
if (in_array($item['product_id'], $restricted_product_ids)) {
$found = true;
break;
}
}
if ($found) {
// Оставим только определённый способ доставки, например 'local_pickup'
foreach ($rates as $rate_id => $rate) {
if ('local_pickup' !== $rate->method_id) {
unset($rates[$rate_id]);
}
}
}
return $rates;
}3. Установка минимального срока доставки для конкретных товаров
WooCommerce не имеет встроенного таймера для сроков доставки, поэтому можно добавить кастомное поле для товара и показывать предупреждение на странице оформления заказа, если выбранный срок доставки меньше минимального.
Пример добавления метаполя с минимальным сроком доставки (в днях) в админке товара (через functions.php или плагин):
add_action('woocommerce_product_options_shipping', 'add_min_delivery_time_field');
function add_min_delivery_time_field() {
woocommerce_wp_text_input(
array(
'id' => '_min_delivery_time',
'label' => __('Минимальный срок доставки (дни)', 'woocommerce'),
'type' => 'number',
'custom_attributes' => array('step' => '1', 'min' => '0'),
)
);
}
add_action('woocommerce_process_product_meta', 'save_min_delivery_time_field');
function save_min_delivery_time_field($post_id) {
$min_delivery_time = isset($_POST['_min_delivery_time']) ? intval($_POST['_min_delivery_time']) : '';
update_post_meta($post_id, '_min_delivery_time', $min_delivery_time);
}Далее на странице оформления заказа проверим выбранный способ доставки и сравним с минимальным сроком доставки товаров в корзине:
add_action('woocommerce_checkout_process', 'check_min_delivery_time');
function check_min_delivery_time() {
$chosen_shipping_methods = WC()->session->get('chosen_shipping_methods');
if (empty($chosen_shipping_methods)) return;
$min_days = 0;
foreach (WC()->cart->get_cart() as $cart_item) {
$product_id = $cart_item['product_id'];
$product_min = get_post_meta($product_id, '_min_delivery_time', true);
if ($product_min && $product_min > $min_days) {
$min_days = $product_min;
}
}
// Здесь поставьте логику проверки срока доставки, например, сравните с выбранным способом
// Для примера просто выведем ошибку, если срок меньше 3 дней
$allowed_min_days = 3; // пример
if ($min_days > $allowed_min_days) {
wc_add_notice(sprintf('Минимальный срок доставки для некоторых товаров: %d дней. Пожалуйста, выберите другой способ доставки.', $min_days), 'error');
}
}Проверка результата после внедрения
- Добавьте в корзину товар с ID из массива
$restricted_product_ids. - Перейдите на страницу оформления заказа и убедитесь, что отсутствуют запрещённые способы оплаты и доставки.
- Для проверки срока доставки добавьте товар с метаполем
_min_delivery_timeи выберите способ доставки с меньшим сроком; должна появиться ошибка. - Проверьте логи ошибок и консоль браузера на наличие исключений или JavaScript-конфликтов.
Частые ошибки и как их исправить
- Не срабатывают фильтры способов оплаты или доставки — проверьте, что фильтры добавлены в
functions.phpактивной темы или в плагине, и что кэш сайта и плагинов очищен. - Ошибки в логах из-за некорректных ID товаров — убедитесь, что ID товаров указаны правильно, и товары существуют.
- Пользователь видит способы оплаты/доставки, которые должны быть скрыты — возможно, способы оплаты заданы на уровне платежного шлюза, стоит проверить конфигурацию плагинов платежей и доставки.
- Ошибка при сохранении метаполя товара — убедитесь, что поле добавлено в правильный хук и используется корректный префикс (
_min_delivery_timeс подчеркиванием для приватного метаполя).
Практические советы по безопасности и производительности
- Не используйте тяжелые циклы и запросы в фильтрах, которые применяются на каждой загрузке страницы оформления заказа.
- Кэшируйте результаты проверки товаров в корзине, если это возможно.
- Избегайте глобальных изменений способов оплаты и доставки — ограничивайте логику только на страницах оформления заказа.
- Проверяйте совместимость кастомного кода с обновлениями WooCommerce и PHP.
Сравнение подходов: плагин vs кастомный код
| Критерий | Плагин (например, Conditional Shipping and Payments) | Кастомный код | Компромисс |
|---|---|---|---|
| Гибкость | Высокая, с интерфейсом | Максимальная, требует знаний | Код сложнее поддерживать |
| Производительность | Может замедлять сайт | Легковесный, при правильном коде | Требует тестирования |
| Простота использования | Для админа без знаний кода | Требует разработчика | Оптимально для больших проектов |
| Стоимость | Платный | Бесплатно | Зависит от времени разработки |