Проблема: ограничение способов оплаты по товарам в WooCommerce
В стандартном WooCommerce нет встроенной функции, которая позволяла бы показывать или скрывать определённые методы оплаты в зависимости от выбранных товаров в корзине. Это часто требуется, например, если вы продаёте цифровые и физические товары, и хотите разрешать оплату по безналу только для физических товаров, а для цифровых — только онлайн-платежи. Или если у товара есть особые условия оплаты.
Диагностика проблемы
Проверить, что WooCommerce не фильтрует способы оплаты по товарам, можно так:
- Добавьте в корзину разные товары с разными условиями оплаты.
- Перейдите на страницу оформления заказа.
- Посмотрите, доступны ли все методы оплаты, которые активированы в настройках WooCommerce.
Если все методы всегда отображаются, несмотря на разные товары в корзине, значит, фильтр не настроен.
Решение: фильтрация методов оплаты через хук woocommerce_available_payment_gateways
WooCommerce позволяет изменить доступные способы оплаты с помощью фильтра woocommerce_available_payment_gateways. Мы можем реализовать логику, которая проверит товары в корзине и отфильтрует методы оплаты.
Пример кода для ограничения способов оплаты по товарам с определённой категорией
add_filter('woocommerce_available_payment_gateways', 'filter_payment_gateways_by_product_category');
function filter_payment_gateways_by_product_category($available_gateways) {
if (is_admin()) return $available_gateways; // Не трогаем админку
$restrict_cod_category = 'physical'; // Категория товаров, для которой разрешён COD
$has_physical = false;
$has_other = false;
foreach (WC()->cart->get_cart() as $cart_item) {
$product_id = $cart_item['product_id'];
$terms = get_the_terms($product_id, 'product_cat');
$categories = wp_list_pluck($terms, 'slug');
if (in_array($restrict_cod_category, $categories)) {
$has_physical = true;
} else {
$has_other = true;
}
}
// Если в корзине есть товары из категории 'physical', разрешаем COD
if ($has_physical) {
// Оставляем все методы
}
// Если в корзине есть товары вне категории 'physical', отключаем COD
if ($has_other && isset($available_gateways['cod'])) {
unset($available_gateways['cod']);
}
return $available_gateways;
}
В этом примере метод оплаты «Оплата при получении» (COD) доступен только если в корзине есть товары из категории physical. Если в корзине есть другие товары, COD отключается.
Пример: разрешить оплату картой только для цифровых товаров
add_filter('woocommerce_available_payment_gateways', 'only_card_for_digital_products');
function only_card_for_digital_products($available_gateways) {
if (is_admin()) return $available_gateways;
$digital_category = 'digital';
$has_digital = false;
$has_non_digital = false;
foreach (WC()->cart->get_cart() as $cart_item) {
$product_id = $cart_item['product_id'];
$terms = get_the_terms($product_id, 'product_cat');
$categories = wp_list_pluck($terms, 'slug');
if (in_array($digital_category, $categories)) {
$has_digital = true;
} else {
$has_non_digital = true;
}
}
// Если есть цифровые товары, разрешаем только payment_method_1 (например, card)
if ($has_digital) {
foreach ($available_gateways as $gateway_id => $gateway) {
if ($gateway_id !== 'payment_method_1') {
unset($available_gateways[$gateway_id]);
}
}
}
// Если есть нецифровые товары, разрешаем все методы
if ($has_non_digital) {
// Ничего не меняем
}
return $available_gateways;
}
Пошаговая инструкция для внедрения решения
- Определите логику ограничения способов оплаты (по категориям, тегам, метаполям товаров).
- Добавьте приведённый код в файл
functions.phpвашей дочерней темы или в кастомный плагин. - Замените названия категорий и ID методов оплаты на актуальные для вашего магазина.
- Очистите кэш сайта и браузера.
- Проверьте работу на странице оформления заказа с разными товарами в корзине.
Как проверить, что решение сработало
- Добавьте в корзину товар из категории, где метод оплаты должен быть доступен, и убедитесь, что он отображается.
- Добавьте товар из категории, где метод оплаты должен быть запрещён, и проверьте, что метод не показывается.
- Проверьте комбинации товаров разных категорий — метод оплаты должен показываться/скрываться согласно логике.
Частые ошибки и как исправить
- Методы оплаты не меняются: убедитесь, что хук подключён правильно, и код не вызывает ошибок. Проверьте, что в корзине есть товары, и что категории заданы верно.
- Ошибка «Undefined index» для метода оплаты: проверьте, что ID метода оплаты совпадает с тем, что используется в WooCommerce (например, 'cod', 'bacs', 'paypal').
- Код не работает в админке: добавьте проверку
if (is_admin()) return $available_gateways;в начале функции. - Методы оплаты исчезают полностью: возможно, условие фильтрации слишком жёсткое, и все методы удаляются. Проверьте логику и отладьте с помощью
error_logили дебагера.
Практические советы по безопасности и производительности
- Не используйте тяжелые запросы в цикле корзины — кешируйте результаты, если нужно.
- Проверяйте, что фильтр работает только на фронтенде оформления заказа, чтобы не замедлять админку.
- Используйте корректные ID методов оплаты, чтобы избежать ошибок.
- Если у вас много продуктов и сложная логика, рассмотрите хранение условий в метаполях и используйте прямые SQL-запросы для оптимизации.
Сравнение способов реализации фильтрации оплаты
| Метод | Плюсы | Минусы |
|---|---|---|
| Код в functions.php | Быстро, гибко, бесплатно | Требует навыков, возможны ошибки при обновлениях темы |
| Кастомный плагин | Изолированное решение, легко переносить между сайтами | Нужно писать и поддерживать плагин |
| Плагины из репозитория | Готовые решения без кода | Могут быть ограничены в возможностях, нагрузка на сайт |