Замена стандартных обработчиков геолокации на локальный сервис DaData.ru в Битрикс
23 апреля 2024
BXmeta
Столкнулись с проблемой работы стандартных обработчиков геолокации в России? Или нет возможности оплатить их услуги? В нашей новой статье мы расскажем, как легко и быстро переключиться на локальный сервис DaData.ru.
Мы покажем, как настроить и интегрировать DaData.ru с вашим проектом на Битрикс, чтобы обеспечить точное определение геолокации ваших пользователей. Следуйте нашим пошаговым инструкциям и получите рабочее решение без лишних затрат.
Решение
Создаем личный кабинет на сайте dadata.ruСоздать файл /local/php_interface/lib/dadata_geo.php (скопировать в него код из примера ниже)
<?php
namespace BXmeta\GeoIp;
use Bitrix\Main;
use Bitrix\Main\Error;
use Bitrix\Main\Text\Encoding;
use Bitrix\Main\Web\HttpClient;
use Bitrix\Main\Service\GeoIp\Result;
use Bitrix\Main\Service\GeoIp\Data;
use Bitrix\Main\Service\GeoIp\ProvidingData;
class DadataGeo extends \Bitrix\Main\Service\GeoIp\Base
{
/**
* @return string Title of handler.
*/
public function getTitle()
{
return 'dadata.ru';
}
/**
* @return string Handler description.
*/
public function getDescription()
{
return "https://dadata.ru/";
}
/**
* @param string $ipAddress Ip address
* @return Main\Result
*/
protected function sendRequest($ipAddress)
{
$result = new Main\Result();
$httpClient = $this->getHttpClient();
$httpClient->setHeader('Content-Type', 'application/json');
$httpClient->setHeader('Accept', 'application/json');
$httpClient->setHeader('Authorization', 'Token ' . $this->config['API_KEY']);
$httpClient->setHeader('X-Secret', $this->config['SECRET_KEY']);
$url = "https://suggestions.dadata.ru/suggestions/api/4_1/rs/iplocate/address";
$posData = [
"ip" => $ipAddress
];
$httpRes = $httpClient->post($url, json_encode($posData));
$errors = $httpClient->getError();
if (!$httpRes && !empty($errors)) {
$strError = "";
foreach ($errors as $errorCode => $errMes)
$strError .= $errorCode . ": " . $errMes;
$result->addError(new Error($strError));
} else {
$status = $httpClient->getStatus();
if ($status != 200) {
$result->addError(new Error('dadata.ru http status: ' . $status));
} else {
$arRes = json_decode($httpRes, true);
if (is_array($arRes)) {
if (mb_strtolower(SITE_CHARSET) != 'utf-8')
$arRes = Encoding::convertEncoding($arRes, 'UTF-8', SITE_CHARSET);
$result->setData($arRes);
} else {
$result->addError(new Error('Can\'t decode json result'));
}
}
}
return $result;
}
/**
* @return HttpClient
*/
protected static function getHttpClient()
{
return new HttpClient([
"version" => "1.1",
"socketTimeout" => 5,
"streamTimeout" => 5,
"redirect" => true,
"redirectMax" => 5,
]);
}
/**
* Languages supported by handler ISO 639-1
* @return array
*/
public function getSupportedLanguages()
{
return ['ru'];
}
/**
* @param string $ipAddress Ip address
* @param string $lang Language identifier
* @return Result | null
*/
public function getDataResult($ipAddress, $lang = '')
{
$dataResult = new Result();
$geoData = new Data();
$geoData->ip = $ipAddress;
$geoData->lang = $lang = strlen($lang) > 0 ? $lang : 'en';
$res = $this->sendRequest($ipAddress);
if ($res->isSuccess()) {
$rowData = $res->getData();
$data = $rowData['location']['data'];
if (!empty($data['country']))
$geoData->countryName = $data['country'];
if (!empty($data['country_iso_code']))
$geoData->countryCode = $data['country_iso_code'];
if (!empty($data["region_with_type"]))
$geoData->regionName = $data['region_with_type'];
if (!empty($data["region_iso_code"]))
$geoData->regionCode = $data['region_iso_code'];
if (!empty($data["city"]))
$geoData->cityName = $data['city'];
if (!empty($data['timezone']))
$geoData->timezone = $data['timezone'];
if (!empty($data['geo_lat']))
$geoData->latitude = $data['geo_lat'];
if (!empty($data['geo_lon']))
$geoData->longitude = $data['geo_lon'];
if (!empty($data['postal_code']))
$geoData->zipCode = $data['postal_code'];
} else {
$dataResult->addErrors($res->getErrors());
}
$dataResult->setGeoData($geoData);
return $dataResult;
}
/**
* Is this handler installed and ready for using.
* @return bool
*/
public function isInstalled()
{
return true;
}
/**
* @param array $postFields Admin form posted fields during saving process.
* @return array Field CONFIG for saving to DB in admin edit form.
*/
public function createConfigField(array $postFields)
{
return [
'API_KEY' => isset($postFields['API_KEY']) ? $postFields['API_KEY'] : '',
'SECRET_KEY' => isset($postFields['SECRET_KEY']) ? $postFields['SECRET_KEY'] : '',
];
}
/**
* @return array Set of fields description for administration purposes.
*/
public function getConfigForAdmin()
{
return [
[
'NAME' => 'API_KEY',
'TITLE' => 'Api key',
'TYPE' => 'TEXT',
'VALUE' => htmlspecialcharsbx($this->config['API_KEY'])
],
[
'NAME' => 'SECRET_KEY',
'TITLE' => 'Secret key',
'TYPE' => 'TEXT',
'VALUE' => htmlspecialcharsbx($this->config['SECRET_KEY'])
],
];
}
/**
* @return ProvidingData Geolocation information witch handler can return.
*/
public function getProvidingData()
{
$result = new ProvidingData();
$result->countryName = true;
$result->countryCode = true;
$result->regionName = true;
$result->regionCode = true;
$result->cityName = true;
$result->latitude = true;
$result->longitude = true;
$result->timezone = false;
$result->zipCode = true;
$result->ispName = false;
$result->organizationName = false;
return $result;
}
}
В файл init.php добавить обработчик события onMainGeoIpHandlersBuildList (скопировать в него код из примера ниже)
<?php
use \Bitrix\Main\EventManager;
function customGeoIpHandler()
{
return new \Bitrix\Main\EventResult(
\Bitrix\Main\EventResult::SUCCESS,
array(
'\BXmeta\GeoIp\DadataGeo' => '/local/php_interface/lib/dadata_geo.php'
),
'main'
);
}
$eventManager = EventManager::getInstance();
$eventManager->addEventHandler('main', 'onMainGeoIpHandlersBuildList', 'customGeoIpHandler');
Переходим в список обработчиков ваш_сайт/bitrix/admin/geoip_handlers_list.php?lang=ru
- Добавляем обработчик
- Указываем ключи полученные в личном кабинете dadata.ru