Получение местоположения (геопозиции) пользователя по IP-адресу на PHP+API
Если вы задались вопросом о том, как (каким образом) можно определить город, регион или страну посетителя сайта зная его IP-адрес, то этот пост будет ответом на него.
На самом деле, и я об этом говорил неоднократно, эту (как и другие) задачу можно решить несколькими способами. Я же рассмотрю один конкретный, который лично использую на некоторых своих проектах.
В его основе (не считая PHP) будет лежать API. С помощью него, мы будем посылать определенные команды выбранному сервису, и в ответ на них получать нужные нам данные.
Такой подход я выбрал не случайно: он (особенно для новичков в программировании), на мой взгляд, проще в реализации + мы получаем актуальную (регулярно обновляемую) информацию (частота обновления зависит от выбранного сервиса). Здесь, конечно, как и в других вариантах решения поставленной задачи, есть свои минусы, в числе которых зависимость от внешних ресурсов, разная точность определения геопозиции, а также разного рода лимиты (ограничения). Говоря о последнем, поясню. Лимиты, как правило, представляют собой ограниченное количество (в час, день, месяц и так далее в зависимости от сервиса) запросов и распространяются они чаще всего на бесплатное использование сервисов, в платных же тарифах возможностей больше, и это логично, поскольку подобным (и не только) сервисам необходимо каким-то образом существовать и, на мой взгляд, бороться с недобросовестным использованием предоставленных инструментов.
Что-то опять много букв.
В общем, о нюансах я написал, техническую составляющую мы рассмотрим на примере бесплатной версии сервиса ip-api.com (предоставляет 45 запросов в минуту, подходит только для личного использования), но для более или менее серьезных проектов (даже для своих) рекомендую всё же посмотреть в сторону платных тарифов. Ниже я также приложу список других подобных сервисов, но сразу оговорюсь, что, возможно, потребуются корректировки в предложенный код из-за формата возвращаемых данных.
Поехали!
1. Первое, что нам нужно для того, чтобы определить местоположение пользователя – это получить его IP-адрес. Каким образом это делается, мы уже разбирали ранее. Все подробности можете почитать там, здесь же я просто возьму часть:
if(!empty($_SERVER['HTTP_CLIENT_IP'])) {
$userIP = $_SERVER['HTTP_CLIENT_IP'];
} elseif(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$userIP = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$userIP = $_SERVER['REMOTE_ADDR'];
}
2. Далее, собственно, составим свою небольшую функцию для получения данных от ip-api.com:
function getUserGeo() {
if(!empty($_SERVER['HTTP_CLIENT_IP'])) {
$userIP = $_SERVER['HTTP_CLIENT_IP'];
} elseif(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$userIP = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$userIP = $_SERVER['REMOTE_ADDR'];
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_URL, 'http://ip-api.com/json/'.$userIP);
$data = curl_exec($ch);
curl_close($ch);
return json_decode($data, true);
}
Пример её использования:
$getUserGeo = getUserGeo();
if($getUserGeo['status'] == 'success') {
echo 'Ваш город: '.$getUserGeo['city'];
} else {
echo 'Ошибка получения данных: '.$getUserGeo['message'];
}
Основной список возвращаемых полей (не требуют явного указания):
status - статус получения данных (success или fail)
message - сообщение об ошибке (возвращается, если status = fail)
country - страна
countryCode - двухбуквенный код страны по ISO 3166-1 alpha-2
region - код региона/штата (FIPS или ISO)
regionName - регион/штат
city - город
zip - индекс
lat - широта
lon - долгота
timezone - часовой пояс
isp - имя провайдера
org - название организации
as - номер AS и организация через пробел (RIR). Пусто для IP-блоков, не объявленных в таблицах BGP
query - IP-адрес, используемый для запроса
Также можно получить (уже с явным указанием):
continent - континент
continentCode - двухбуквенный код континента
district - район города
offset - cмещение часового пояса UTC DST в секундах
currency - национальная валюта
asname - имя AS (RIR)
reverse - обратный DNS IP-адреса (может задержать ответ)
mobile - мобильное подключение
proxy - используется прокси, VPN или Tor
hosting - хостинг, колокация или центр обработки данных
Для перечисления возвращаемых полей в функции строку:
curl_setopt($ch, CURLOPT_URL, 'http://ip-api.com/json/'.$userIP);
заменяете на:
curl_setopt($ch, CURLOPT_URL, 'http://ip-api.com/json/'.$userIP.'?fields=continentCode,currency');
Где «continentCode,currency» - нужные вам поля.
Данные от сервиса приходят на английском языке, по необходимости язык можно поменять, например, на русский. Для этого в функции строку:
curl_setopt($ch, CURLOPT_URL, 'http://ip-api.com/json/'.$userIP);
замените на:
curl_setopt($ch, CURLOPT_URL, 'http://ip-api.com/json/'.$userIP.'?lang=ru');
Список поддерживаемых языков (на момент написания поста):
en - английский (язык по умолчанию)
de - немецкий
es - испанский
pt-BR - португальский
fr - французский
ja - японский
zh-CN - китайский
ru - русский
Что касается лимита в 45 запросов: он (лимит) действует только на бесплатное использование сервиса, и в случае преодоления его происходит временная блокировка доступа до обновления лимитов (как вы поняли, это происходит каждую минуту). Если же вы регулярно превышаете лимит, время блокировки возрастает до одного часа.
Не нарушайте и удачных вам разработок!
Обещанный список сервисов:
https://www.ipinfodb.com
http://geoiplookup.net
https://geo.ipify.org
https://ipbase.com
https://www.myip.com/api-docs/
https://www.abstractapi.com/ip-geolocation-api
https://ipwhois.io/ru/
https://ipstack.com
https://www.geoplugin.com
https://ipinfo.io
Практическое применение этого кода вы можете найти в следующем посте, посвященном блокировке доступа к сайту или отдельному его элементу на основе геопозиции.