Проблема: разные тарифы доставки в зависимости от региона клиента
В WooCommerce часто требуется настроить разные цены доставки в зависимости от региона покупателя. Например, доставка в Москву может стоить 300 рублей, а в регионы — 600 рублей. В стандартном WooCommerce это можно сделать через зоны доставки, но если нужно более гибкое динамическое изменение стоимости или объединение нескольких условий — понадобится кастомный код.
Диагностика задачи
Для начала проверьте, как у вас сейчас настроены зоны доставки в WooCommerce: WooCommerce > Настройки > Доставка > Зоны доставки. Если тарифы не совпадают с бизнес-логикой или нужно учитывать дополнительные условия (например, пользовательская роль, сумма заказа или наличие товара на складе), стандартных зон может быть недостаточно.
Дополнительно убедитесь, что у вас включена локализация региона в профиле пользователя или в форме оформления заказа — без корректного региона код не сможет корректно применить нужную стоимость.
Пошаговое решение с примером кода
1. Отключаем стандартные зоны доставки (если они конфликтуют)
Если зоны доставки заданы, но не подходят, лучше их удалить или отключить, чтобы не было конфликтов.
2. Добавляем фильтр на изменение стоимости доставки
Используем хук woocommerce_package_rates, чтобы изменить цены в зависимости от региона клиента. Ниже пример, как задать разную стоимость доставки для Москвы и регионов:
add_filter('woocommerce_package_rates', 'custom_change_shipping_cost_by_region', 10, 2);
function custom_change_shipping_cost_by_region($rates, $package) {
// Получаем страну и город из адреса доставки
$country = isset($package['destination']['country']) ? $package['destination']['country'] : '';
$city = isset($package['destination']['city']) ? strtolower(trim($package['destination']['city'])) : '';
// Массив городов Москвы для проверки
$moscow_cities = ['москва', 'moscow'];
foreach ($rates as $rate_key => $rate) {
// Пример: если метод доставки - flat_rate
if ('flat_rate' === $rate->method_id) {
if (in_array($city, $moscow_cities) && $country === 'RU') {
// Устанавливаем стоимость для Москвы
$rates[$rate_key]->cost = 300; // 300 рублей
} else {
// Для остальных регионов
$rates[$rate_key]->cost = 600; // 600 рублей
}
}
}
return $rates;
}3. Кэширование и производительность
Если у вас большой магазин и много запросов, рекомендуем кэшировать результаты определения региона или городов, чтобы не делать тяжелых операций внутри фильтра.
Проверка результата после внедрения
- Добавьте товар в корзину и перейдите к оформлению заказа.
- Введите адрес доставки с городом "Москва" и проверьте, что стоимость доставки равна 300 рублей.
- Измените город на любой другой российский регион и убедитесь, что стоимость изменилась на 600 рублей.
- Если у вас несколько методов доставки, проверьте, что изменения применились только к нужному методу (например, flat_rate).
Частые ошибки и как их исправить
- Неправильное имя города: В WooCommerce город может приходить с разными регистрами и пробелами. Используйте
strtolowerиtrim, чтобы нормализовать строку. - Несоответствие метода доставки: Проверьте, что в условии вы правильно сравниваете
$rate->method_id. Например, «flat_rate», а не «flatrate». - Конфликт с зонами доставки: Если активны зоны с разными тарифами, они могут переопределять стоимость. Отключите или корректно настройте зоны.
- Кэширование плагинов: Если используете кеширующие плагины, после изменений очистите кеш, иначе изменения не отобразятся.
Практические советы по безопасности и производительности
- Не храните в коде жестко заданные цены, лучше вынесите их в настройки плагина или темы.
- Избегайте тяжелых операций внутри фильтра
woocommerce_package_rates, так как он вызывается при каждом расчёте корзины. - Обязательно проверяйте валидность и формат входящих данных: страна, город — могут быть пустыми или некорректными.
- Для мультирегиональных магазинов используйте более продвинутые методы геолокации пользователя (например, по IP), чтобы повысить точность.
Сравнение вариантов реализации
| Метод | Плюсы | Минусы | Когда использовать |
|---|---|---|---|
| Зоны доставки WooCommerce | Простая настройка в админке, не требует кода | Ограниченная гибкость, не всегда удобна при сложных условиях | Для простых случаев с четко разделенными регионами |
Кастомный код (фильтр woocommerce_package_rates) | Максимальная гибкость, можно учитывать любые условия | Требует навыков программирования, возможны ошибки | При сложной логике изменения стоимости, комбинированных условиях |
| Плагины для расширенной доставки | Большие возможности без кода | Могут быть платными, влиять на производительность | Если нужна готовая комплексная система доставки |