Шляхом Альбірео

НовиниЗаписиГеокодінгIP-локація

2021.04.16
РНР-скрипти і зовнішні сервіси для ip-локації. Робота на боці сервера.
Note

До епохи глобального интернет-сервісу існували локальні бази на серверах, та по IP-адресі визначали місце користувача, який до того сервера звертався. Підтримка актуальності світових даних була не простим завданням і коштувала чималих грошей.

Зараз настав час, коли з'явилися вільні сервіси, що допомогають в питанні визначення місця юзера на глобусі. Один з них ip-api.com, який видає розгорнуту інформацію по запиту (країна, місто, валюта, провайдер, координати та інше):

/* Отримання інформації по IP-адресі */

[PHP]

<?php $ip = $_SERVER['REMOTE_ADDR']; $query = @unserialize(file_get_contents('http://ip-api.com/php/' . $ip . '?lang=en')); echo '<p>'. $query['country'] .' - '. $query['city'] .' - '. $query['zip'] .' - '. $query['timezone'] .' - '. $query['query'] .' - '. $query['isp'] . '</p>'; ?>

В скрипті ми визначаємо IP свого серверу через $ip = $_SERVER['REMOTE_ADDR'] і робимо запит в IP-api.com, потім чекаємо відповідь і виводимо її в HTML. Всього три строки, а у відповідь отримаємо про користувача, який завітав на сервер, щось схоже на:

Sweden - Linköping - 58222 - Europe/Stockholm - 77.111.244.25 - Opera Browser VPN

Note

Але, скрипт не спрацює, якщо сервер підключений за роутером. В цьому разі, на REMOTE_ADDR ми отримаємо лише локальну адресу, а нас таке не влаштовує.
Випадок має рішення за допомоги іншого сервісу ipify.org, до якого можна звернутися і отримати необхідну адресу уже ззовні:

$ip = file_get_contents('https://api.ipify.org');

За умови всих дій і використання стилів Berry 4.0, перепишемо попередній скрипт в Albireo таким чином:

/* Отримання інформації по IP-адресі */

[PHP]

$ip = file_get_contents('https://api.ipify.org'); $query = @unserialize(file_get_contents('http://ip-api.com/php/' . $ip . '?lang=en')); if ($query && $query['status'] == 'success') { echo '<p class="t-upper t80"> <img class="pad5-b pad10-r opacity80" src="' . getConfig('assetsUrl') . 'images/flags-iso/shiny/32/' . $query['countryCode'] . '.png">' . $query['country'] . '<span class="t-green400 mar5-rl">&#9733;</span>' . $query['city'] . '<span class="t-green400 mar5-rl">&#9733;</span>' . $query['zip'] . '<span class="t-green400 mar5-rl">&#9733;</span>' . $query['timezone'] . '<span class="t-green400 mar5-rl">&#9733;</span><span class="t-nowrap">' . $query['query'] . '</span><span class="t-green400 mar5-rl">&#9733;</span>' . $query['isp'] . '</p>'; } else { echo 'Не вдалося виявити локацію.'; }

Вивід ми прикрасили додатково прапором країни, який вже приєднали локально, бо він у відповідь сервісу не входить. Якщо прапорець не потрібен, то можна просто видалити фрагмент коду:

<img class="pad5-b pad10-r opacity80" src="' . getConfig('assetsUrl') . 'images/flags-iso/shiny/32/' . $query['countryCode'] . '.png">'
Note

Кращим варіантом буде написати snippet, з перевіркою можливостей відгуку сервера, поєднавши обидва підходи. В цьому випадку, ми уникаємо проблем роботи з сервером.

/* Отримання інформації по IP-адресі */

[PHP]

$ip = $_SERVER['REMOTE_ADDR']; $query = @unserialize(file_get_contents('http://ip-api.com/php/' . $ip . '?lang=en')); if ($query && $query['status'] != 'success') { $ip = file_get_contents('https://api.ipify.org'); } $query = @unserialize(file_get_contents('http://ip-api.com/php/' . $ip . '?lang=en')); if ($query && $query['status'] == 'success') { echo '<p class="t-upper t80"><img class="pad5-b pad10-r opacity80" src="' . getConfig('assetsUrl') . 'images/flags-iso/shiny/32/' . $query['countryCode'] . '.png">' . $query['country'] . '<span class="t-green400 mar5-rl">&#9733;</span>' . $query['city'] . '<span class="t-green400 mar5-rl">&#9733;</span>lat ' . $query['lat'] . ' - lon ' . $query['lon'] . '<span class="t-green400 mar5-rl">&#9733;</span>' . $query['timezone'] . '<span class="t-green400 mar5-rl">&#9733;</span><span class="t-nowrap">ip ' . $query['query'] . '</span><span class="t-green400 mar5-rl">&#9733;</span>' . $query['isp'] . '</p>'; } else { echo 'Не вдалося виявити локацію.'; }

Кінцевий результат роботи snippet, з додатковими координатами, може бути таким:

United StatesDublinlat 40.0992 - lon -83.1141America/New_Yorkip 18.217.193.85Amazon.com, Inc.