Типичная проблема в магазине WooCommerce выглядит так: покупатель выбирает страну, а налог и способы доставки либо не меняются, либо меняются только после обновления корзины, либо вообще считаются по адресу магазина. В результате в корзине одна сумма, на чекауте другая, а в поддержке появляются вопросы про «неправильную цену».
Ниже разберём рабочий сценарий: как привязать расчёт к стране покупателя, где смотреть диагностику, что можно сделать настройками WooCommerce, а где уже нужен код. Примеры рассчитаны на стандартный WooCommerce без выдуманных API и без экзотических плагинов.
Когда проблема действительно в настройках WooCommerce
Прежде чем писать код, проверьте базовые вещи. Во многих магазинах логика уже есть, но она не включена или конфликтует с темой.
Что проверить в админке
- WooCommerce → Настройки → Общие: задан ли адрес магазина и страна.
- WooCommerce → Настройки → Налог: включены ли налоги и выбрана ли база расчёта.
- WooCommerce → Настройки → Доставка: созданы ли зоны доставки и привязаны ли к странам.
- WooCommerce → Настройки → Доставка → Зоны доставки: есть ли отдельная зона для нужной страны или группы стран.
- WooCommerce → Настройки → Общие → Местоположение по умолчанию: если стоит адрес магазина, а не геолокация, расчёт может стартовать не с той страны.
Если магазин работает только по одной стране, часто достаточно правильно настроить зону доставки и налоговые классы. Если же нужно менять поведение в зависимости от страны покупателя ещё до ввода адреса, без кода обычно не обойтись.
Диагностика: почему страна определяется неправильно
Сначала поймите, откуда WooCommerce берёт страну. Есть три частых источника: адрес магазина, адрес доставки из профиля пользователя и данные, введённые в чекауте. Если покупатель ещё ничего не указал, WooCommerce может использовать геолокацию или дефолтную страну магазина — в зависимости от настроек.
Проверка в реальном магазине обычно такая:
- Откройте корзину в режиме инкогнито.
- Очистите cookies сайта.
- Посмотрите, какая страна подставляется до ввода адреса.
- Введите адрес вручную и проверьте, обновились ли налог и доставка.
- Сравните поведение для гостя и для авторизованного пользователя.
Если суммы меняются только после ручного обновления страницы, проблема часто в том, что тема или кастомный JS не триггерит пересчёт checkout fragments. Если же страна вообще не влияет на расчёт, проверьте, включена ли доставка по зонам и не перекрывает ли её фиксированная ставка.
Решение без лишнего кода: зоны доставки и налоговые классы
Для простого магазина лучше сначала использовать штатные механизмы WooCommerce. Это надёжнее, чем городить собственную логику на хуках, если задача стандартная.
Как настроить зоны доставки
Создайте отдельные зоны для стран, где условия доставки отличаются. Например, одна зона для России, другая для стран СНГ, третья для остальных стран. Внутри каждой зоны добавьте свои методы: фиксированная ставка, бесплатная доставка, самовывоз.
Важно: WooCommerce применяет первую подходящую зону. Если у вас есть широкая зона «Весь мир» выше конкретной страны, она может перехватывать расчёт. Это одна из самых частых ошибок.
Как настроить налоги
Если налог зависит от страны, используйте отдельные налоговые классы и таблицу ставок. WooCommerce умеет хранить ставки по стране, региону и индексу. Для большинства магазинов этого достаточно, если налоговая логика не завязана на внешнюю систему.
| Подход | Когда подходит | Минус |
|---|---|---|
| Настройки WooCommerce | Обычные зоны доставки и стандартные ставки | Не покрывает нестандартные правила |
| Код через хуки | Нужна логика по стране до чекаута или особые исключения | Нужно тестировать на обновлениях |
| Сторонний плагин | Сложные налоги, интеграция с сервисом расчёта | Зависимость от плагина и его обновлений |
Пошагово: как подменить налог и доставку по стране через код
Если стандартных настроек мало, можно вмешаться в расчёт на уровне WooCommerce. Ниже пример, который меняет стоимость доставки для конкретной страны и добавляет условную надбавку к налогу. Это не универсальный шаблон для любого магазина, а основа, которую нужно адаптировать под вашу модель налогообложения.
add_filter( 'woocommerce_package_rates', function( $rates, $package ) {
if ( empty( $package['destination']['country'] ) ) {
return $rates;
}
$country = $package['destination']['country'];
foreach ( $rates as $rate_id => $rate ) {
if ( 'RU' === $country && 'flat_rate' === $rate->method_id ) {
$rates[ $rate_id ]->cost = 300;
}
if ( 'KZ' === $country && 'flat_rate' === $rate->method_id ) {
$rates[ $rate_id ]->cost = 500;
}
}
return $rates;
}, 10, 2 );
add_filter( 'woocommerce_product_get_tax_class', function( $tax_class, $product ) {
if ( is_admin() ) {
return $tax_class;
}
$country = WC()->customer ? WC()->customer->get_shipping_country() : '';
if ( 'KZ' === $country ) {
return 'reduced-rate';
}
return $tax_class;
}, 10, 2 );Первый хук меняет стоимость метода доставки flat_rate в зависимости от страны доставки. Второй пример показывает, как можно подставить другой налоговый класс для товара, если страна доставки уже известна. В реальном проекте лучше не менять налоговый класс товара «на лету», если у вас сложная бухгалтерия: безопаснее управлять ставками в таблицах WooCommerce или через отдельную бизнес-логику на чекауте.
Куда вставлять код
Если это одноразовая доработка для темы, используйте дочернюю тему. Если логика должна жить независимо от темы, вынесите её в небольшой плагин. Так вы не потеряете изменения после обновления темы.
Минимальный вариант для плагина выглядит так:
<?php
/**
* Plugin Name: Country-based shipping tweaks
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
add_filter( 'woocommerce_package_rates', 'wpdemo_country_shipping_tweaks', 10, 2 );
function wpdemo_country_shipping_tweaks( $rates, $package ) {
if ( empty( $package['destination']['country'] ) ) {
return $rates;
}
$country = $package['destination']['country'];
foreach ( $rates as $rate_id => $rate ) {
if ( 'UA' === $country && 'flat_rate' === $rate->method_id ) {
$rates[ $rate_id ]->cost = 250;
}
}
return $rates;
}Как проверить, что решение сработало
Проверка должна быть не визуальной «на глаз», а по сценарию. Иначе легко пропустить кеш, старую сессию клиента или конфликт с плагином доставки.
- Откройте магазин в инкогнито и очистите корзину.
- Выберите страну доставки, для которой вы прописали отдельное правило.
- Убедитесь, что стоимость доставки изменилась сразу после обновления чекаута.
- Проверьте итоговую сумму до и после смены страны.
- Сравните поведение для гостя и авторизованного пользователя.
- Если используете кеширование, убедитесь, что корзина и checkout исключены из кеша.
Дополнительно полезно включить логирование WooCommerce и посмотреть, не падают ли сторонние фильтры. Если у вас есть плагин для отладки, проверьте, не перезаписывает ли он данные клиента после AJAX-обновления.
Частые ошибки и как их исправить
Первая подходящая зона доставки перекрывает нужную
Если у вас есть зона «Все страны» выше конкретной страны, WooCommerce может выбрать её раньше. Решение простое: переставьте зоны так, чтобы более точные правила шли выше общих.
Страна берётся из адреса магазина, а не покупателя
Это происходит, когда в настройках стоит дефолтное местоположение магазина. Для магазинов с международной аудиторией лучше использовать геолокацию или явно просить покупателя выбрать страну на чекауте.
Кеш мешает обновлению корзины
Если страница корзины или чекаута закеширована, покупатель будет видеть старые суммы. Исключите эти страницы из кеша на уровне плагина или сервера. Для динамических блоков корзины это критично.
Код меняет цену, но не налоговую логику
Не путайте изменение стоимости товара и изменение налога. Если вам нужен именно налог, лучше работать с налоговыми ставками WooCommerce, а не подменять цену товара вручную. Иначе отчёты и бухгалтерия быстро начнут расходиться.
Безопасность и производительность
Любая логика, завязанная на страну, должна быть предсказуемой. Не тяните внешние API на каждом обновлении корзины без кеширования: чекаут станет медленным, а ошибки сети начнут ломать оформление заказа.
Если всё же нужна внешняя проверка, делайте её асинхронно и сохраняйте результат в сессию WooCommerce или в user meta, если это оправдано. Для простых правил по стране достаточно встроенных данных клиента.
Ещё один практический момент: не меняйте глобальные настройки налога в рантайме для каждого посетителя. Это почти всегда приводит к трудноуловимым багам, особенно если одновременно работают купоны, много валют и плагины доставки.
Когда лучше не писать код
Если задача сводится к стандартным ставкам по странам, используйте штатные зоны и налоговые таблицы. Код нужен только тогда, когда есть исключения: отдельные правила для конкретных стран, нестандартные методы доставки, особые условия для B2B или локальные ограничения.
Если вам нужен более широкий контроль над контентом и блоками внимания в магазине, иногда удобнее закрыть часть сценариев плагинами, а не дописывать всё вручную. Но для расчёта налогов и доставки лучше держаться ближе к механике WooCommerce, чем к визуальным надстройкам.