В версии модуля sale 17.0.13 появилось автоматическое определение местоположения покупателя при оформлении заказа. Но это можно использовать и в своих целях, соответствующие классы и методы доступны для использования разработчиками.
В sale 17.0.17 замечен баг с геолокацией (Ошибка "Call to undefined method Bitrix\Main\Service\GeoIp\Manager::getData()"). Из-за этого не работает оформление заказа (sale.order.ajax). Для получения костыля нужно написать в техподдержку или обновиться до sale 17.0.18.
Определение местоположения реализовано в классах пространства имён \Bitrix\Main\Service\GeoIp
. Для работы примеров будет использоваться сокращение:
use \Bitrix\Main\Service\GeoIp;
Обработчики геолокации
Доступные обработчики можно найти и настроить в настройках Настройки > Настройки продукта > Геолокация. На момент написания статьи доступны обработчики:
- MaxMind;
- Sypex Geo;
- Расширение GeoIP.
Для первых двух нужны ключи для доступа к соответствующим сервисам. Для тестирования проще и дешевле зарегистрироваться на Sypex Geo, там дают 30000 бесплатных запросов в месяц. Ключ для сервиса будет указан в личном кабинете, его нужно будет указать в настройках обработчика.
Обработчики геолокации - классы-наследники GeoIp\Base
. Из коробки идут 3 обработчика, как говорилось выше:
$buildInHandlers = array(
'\Bitrix\Main\Service\GeoIp\MaxMind' => 'lib/service/geoip/maxmind.php',
'\Bitrix\Main\Service\GeoIp\Extension' => 'lib/service/geoip/extension.php',
'\Bitrix\Main\Service\GeoIp\SypexGeo' => 'lib/service/geoip/sypexgeo.php'
);
Добавить свои можно с помощью события onMainGeoIpHandlersBuildList
модуля main:
$eventManager = \Bitrix\Main\EventManager::getInstance();
$eventManager->addEventHandler(
'main',
'onMainGeoIpHandlersBuildList',
'myGeoIpHandlers'
);
function myGeoIpHandlers()
{
return new \Bitrix\Main\EventResult(
\Bitrix\Main\EventResult::SUCCESS,
array(
'\Acme\YourClass' => '/path/to/your/class.php',
)
);
}
Примеры обработчиков можно найти в ядре, обязательно требуется определить три метода: getTitle
, getDescription
и getData
.
Использование
Для определения местоположения требуется IP пользователя. Его можно получить с помощью метода GeoIp\Manager::getRealIp
:
$ipAddress = GeoIp\Manager::getRealIp();
Для получения геоинформации по этому IP нужно вызвать метод GeoIp\Manager::getDataResult
:
$result = GeoIp\Manager::getDataResult($ipAddress, "ru");
Метод возвращает объект класса GeoIp\Result
(до версии 17.0.18 – GeoIp\DataResult
). Поля объекта:
object(Bitrix\Main\Service\GeoIp\Result)#101 (4) {
["geoData":protected]=>
object(Bitrix\Main\Service\GeoIp\Data)#75 (16) {
["ip"]=>
string(12) "XXX.XXX.XXX.XXX"
["lang"]=>
string(2) "ru"
["countryName"]=>
string(12) "Россия"
["regionName"]=>
string(31) "Липецкая область"
["subRegionName"]=>
NULL
["cityName"]=>
string(12) "Липецк"
["countryCode"]=>
string(2) "RU"
["regionCode"]=>
string(6) "RU-LIP"
["zipCode"]=>
NULL
["latitude"]=>
float(52.60311)
["longitude"]=>
float(39.57076)
["timezone"]=>
string(13) "Europe/Moscow"
["asn"]=>
NULL
["ispName"]=>
NULL
["organizationName"]=>
NULL
["handlerClass"]=>
string(34) "Bitrix\Main\Service\GeoIp\SypexGeo"
}
["isSuccess":protected]=>
bool(true)
["errors":protected]=>
object(Bitrix\Main\ErrorCollection)#79 (1) {
["values":protected]=>
array(0) {
}
}
["data":protected]=>
array(0) {
}
}
Из поля 'handlerClass' видно, что для определения использовался обработчик Sypex Geo. Вообще менеджер перебирает все доступные настроенные обработчики, которые могут вернуть результат на нужном языке (второй аргумент в методе getDataResult
) и с нужными полями. Если найден подходящий обработчик и он вернул результат, то запросы к другим доступным обработчикам не делаются.
Нужные поля можно указать третьим аргументом в методе getDataResult
, например:
GeoIp\Manager::getDataResult($ip, $lang, array('cityName', 'zipCode'));
В таком случае Sypex Geo не будет использован, т.к. в списке возвращаемых полей нет zipCode.
Перед запросом можно включить сохранение геоинформации в cookies, для этого перед getDataResult
следует вызвать:
GeoIp\Manager::useCookieToStoreInfo(true);
В таком случае, в случае успешного получения геоинформации она будет сохранена в cookies BX_MAIN_GEO_IP_DATA_XXX_XXX_XXX_XXX
, привязанной к определенному IP. Пока cookie будет жива и IP будет оставаться прежним, запросов в сервис геолокации по данному пользователю не будет.
Стоит учесть, что максимальная длина cookie - 4096 байт, а в IE вроде как еще меньше. Поэтому неизвестно, насколько надежно держать в cookie сериализованный объект с геоинформацией. Уверен, что в Битриксе об этом не задумывались.
Геолокация в модуле sale
Как говорилось в начале, геолокация была анонсирована в обновлении модуля sale, поэтому геолокацию можно использовать для определения местоположения пользователя для оформления заказа. Для этого существует класс Bitrix\Sale\Location\GeoIp
, который использует вышеописанный функционал для поиска местоположения в базе Битрикса.
// Возвращает ID местоположения
\Bitrix\Sale\Location\GeoIp::getLocationId($ip, $lang);
// Возвращает код местоположения
\Bitrix\Sale\Location\GeoIp::getLocationCode($ip, $lang);
// Возвращает индекс
\Bitrix\Sale\Location\GeoIp::getZipCode($ip, $lang);
Во всех этих методах используется сохранение результата геолокации в cookies. Местоположение в базе находится по названию независимо от регистра.