Проблема: необходимость ограничения платёжных систем по стране покупателя
В WooCommerce иногда требуется отключать определённые способы оплаты в зависимости от географического положения клиента. Например, отключить оплату через PayPal для пользователей из определённых стран или регионов. Это особенно актуально для магазинов с ограничениями по доставке, юридическим требованиям или валютным ограничениям.
Диагностика проблемы
Стандартный WooCommerce не предоставляет встроенной опции для динамического отключения способов оплаты по геолокации. В настройках платежей можно ограничить по стране, но это работает только в том случае, если адрес доставки или оплаты заполнен и выбран клиентом. При первом заходе или если адрес не заполнен, ограничение не работает.
Также часто сталкиваются с ситуацией, когда IP-адрес клиента не совпадает с адресом доставки, или требуется более точный контроль на уровне IP-геолокации.
Пошаговое решение: отключение платёжных систем по IP-геолокации
1. Получение геолокации клиента по IP
Для определения страны по IP можно использовать бесплатный сервис GeoIP от ipapi.co или ipinfo.io. Ниже пример с ipapi.co:
function get_client_country_code() {
$ip = $_SERVER['REMOTE_ADDR'];
$response = wp_remote_get('https://ipapi.co/' . $ip . '/country/');
if (is_wp_error($response)) {
return false;
}
$country_code = wp_remote_retrieve_body($response);
if (strlen($country_code) !== 2) {
return false;
}
return strtoupper($country_code);
}2. Фильтрация доступных платёжных систем в WooCommerce
Используем хук woocommerce_available_payment_gateways для отключения выбранных способов оплаты, если страна клиента совпадает с запрещённым списком.
add_filter('woocommerce_available_payment_gateways', 'disable_payment_gateways_by_geoip');
function disable_payment_gateways_by_geoip($available_gateways) {
$blocked_countries = array('RU', 'BY', 'UA'); // пример стран блокировки
$blocked_gateways = array('paypal', 'stripe'); // ID платёжных систем для отключения
$country = get_client_country_code();
if ($country && in_array($country, $blocked_countries)) {
foreach ($blocked_gateways as $gateway_id) {
if (isset($available_gateways[$gateway_id])) {
unset($available_gateways[$gateway_id]);
}
}
}
return $available_gateways;
}Как проверить, что решение сработало
- Откройте страницу оформления заказа с IP-адресом из заблокированной страны (можно проверить через VPN).
- Убедитесь, что в списке способов оплаты отсутствуют отключённые платежные системы (например, PayPal или Stripe).
- Для IP из разрешённых стран все способы оплаты доступны.
- Проверьте, что при смене адреса доставки или оплаты поведение не меняется (т.к. мы ориентируемся строго на IP, а не адрес клиента).
Частые ошибки и их исправление
- Ошибка: Все способы оплаты отключены.
Причина: IP не определяется, функция get_client_country_code возвращает false, но логика не учитывает этот случай.
Решение: Добавьте проверку результата функции и отключение способов оплаты выполняйте только при успешном определении страны. - Ошибка: Задержка при загрузке страницы оформления заказа.
Причина: Синхронный HTTP-запрос к сервису геолокации.
Решение: Кэшировать результат геолокации в сессии или transient, чтобы не делать запрос при каждом заходе. - Ошибка: IP-адрес клиента определён неверно (например, сервер находится за прокси).
Решение: Используйте более корректный способ определения IP, например, учитывайте заголовокX-Forwarded-For.
Практические советы по оптимизации и безопасности
- Кэширование геолокации: Используйте transient API для кеширования результата геолокации на 12 часов, чтобы снизить количество запросов к внешнему API и ускорить загрузку страницы.
- Обработка ошибок: Всегда проверяйте ответ сервиса геолокации и обрабатывайте ситуации, когда сервис недоступен.
- Защита данных: Не храните IP-адреса и геоданные дольше необходимого срока, чтобы соответствовать требованиям GDPR.
- Тестирование: Используйте VPN или онлайн-сервисы для проверки работы фильтрации платёжных систем из разных стран.
Пример кэширования результата геолокации через transient
function get_client_country_code() {
$ip = $_SERVER['REMOTE_ADDR'];
$cache_key = 'geoip_country_' . md5($ip);
$country_code = get_transient($cache_key);
if ($country_code !== false) {
return $country_code;
}
$response = wp_remote_get('https://ipapi.co/' . $ip . '/country/');
if (is_wp_error($response)) {
return false;
}
$country_code = wp_remote_retrieve_body($response);
if (strlen($country_code) !== 2) {
return false;
}
$country_code = strtoupper($country_code);
set_transient($cache_key, $country_code, 12 * HOUR_IN_SECONDS);
return $country_code;
}Таблица сравнения вариантов реализации ограничения платёжных систем
| Метод | Плюсы | Минусы | Пример |
|---|---|---|---|
| Встроенные настройки WooCommerce (по стране доставки) | Простота настройки, нет кода | Зависит от адреса, не от IP; не всегда точный контроль | WooCommerce settings → Payments → Restrict by country |
| Плагин GeoIP для WooCommerce | Автоматизация, удобный интерфейс | Плагины могут влиять на производительность; могут быть платными | GeoIP Based Payment Gateways plugin |
| Код на PHP с внешним API (описанный способ) | Полный контроль, бесплатно, гибкость | Нужно писать код, возможна задержка из-за запросов | Решение с wp_remote_get и transient |