Настройка геолокационного определения ближайшего магазина 1С-Битрикс

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Настройка геолокационного определения ближайшего магазина 1С-Битрикс
Простая
~1 рабочий день
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1181
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    813
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    747
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    976

Настройка геолокационного определения ближайшего магазина 1С-Битрикс

Пользователь открывает страницу «Наши магазины» и видит список из 30 адресов без какого-либо порядка. Он живёт в Минске, а первые пять магазинов в списке — Москва. Казалось бы, банальная задача — показать ближайшие — на практике упирается в точность геолокации, расчёт расстояний и хранение координат магазинов в Битрикс.

Хранение данных магазинов

В Битрикс магазины хранятся в двух местах в зависимости от используемого функционала:

Модуль sale, торговые точки: таблица b_sale_store с полями ID, TITLE, ADDRESS, GPS_N (широта), GPS_S (долгота). Это стандартная структура для точек самовывоза.

Инфоблок магазинов: если магазины оформлены как элементы инфоблока, координаты обычно хранятся в пользовательских свойствах типа String или в специализированных полях типа Map (при наличии сторонних модулей).

Для расчёта расстояний нужны числовые координаты. Если они хранятся в строковом свойстве инфоблока в формате «53.9045, 27.5615» — при выборке их придётся парсить, что неудобно. Правильное решение: хранить широту и долготу в двух отдельных числовых свойствах или использовать b_sale_store.GPS_N / b_sale_store.GPS_S.

Определение координат пользователя

Два подхода:

Браузерная геолокация (Geolocation API): точная, до 50 метров, но требует разрешения пользователя. Асинхронная — нельзя использовать при серверном рендеринге.

IP-геолокация: работает без запроса разрешения, точность — до города/района. В Битрикс встроен модуль location с базой GeoIP (b_geocode_city, b_geocode_country). Метод \Bitrix\Location\Service\FormatService::getInstance() работает с адресами, для IP-геолокации используется \Bitrix\Main\Service\GeoIp\Manager::getLocationByIp().

$location = \Bitrix\Main\Service\GeoIp\Manager::getLocationByIp(
    \Bitrix\Main\Context::getCurrent()->getRequest()->getRemoteAddress()
);

$userLat = $location['LATITUDE'] ?? null;
$userLon = $location['LONGITUDE'] ?? null;

Расчёт расстояний: формула Хаверсина в SQL

Самый эффективный подход — считать расстояния прямо в SQL-запросе. Формула Хаверсина для PostgreSQL:

SELECT
    id,
    title,
    gps_n AS lat,
    gps_s AS lon,
    (
        6371 * acos(
            cos(radians(:user_lat)) * cos(radians(gps_n)) *
            cos(radians(gps_s) - radians(:user_lon)) +
            sin(radians(:user_lat)) * sin(radians(gps_n))
        )
    ) AS distance_km
FROM b_sale_store
WHERE active = 'Y'
  AND gps_n IS NOT NULL
  AND gps_s IS NOT NULL
ORDER BY distance_km
LIMIT 5;

Для MySQL синтаксис аналогичен. На PostgreSQL дополнительно можно использовать расширение earthdistance с cube, что быстрее для больших наборов точек.

Через ORM Битрикс прямой SQL вызывается через \Bitrix\Main\Application::getConnection()->query(). Готового выражения Хаверсина в D7 ORM нет — придётся использовать ExpressionField с raw SQL или нативный запрос.

Фронтенд: два шага

  1. При загрузке страницы — показываем магазины, отсортированные по IP-геолокации (серверная сортировка, мгновенно).
  2. После получения точных координат через navigator.geolocation.getCurrentPosition() — пересортировываем через AJAX-запрос к компоненту с параметрами lat и lon.
navigator.geolocation.getCurrentPosition(function(pos) {
    fetch('/ajax/nearest-stores/?lat=' + pos.coords.latitude + '&lon=' + pos.coords.longitude)
        .then(r => r.json())
        .then(stores => renderStoreList(stores));
});

Компонент-обработчик AJAX читает lat/lon из GET, выполняет SQL с Хаверсином, возвращает JSON. В Битрикс это реализуется через компонент с параметром ajax_mode = Y или через собственный endpoint в /local/ajax/.

Что настраиваем

  • Проверку наличия координат в b_sale_store или инфоблоке магазинов, их заполнение
  • SQL-запрос с формулой Хаверсина через Application::getConnection()
  • IP-геолокацию через GeoIp\Manager для первичной сортировки без разрешения пользователя
  • AJAX-endpoint для пересортировки после получения точных координат браузера
  • Кеширование результата для каждой пары координат (округлённой до 0.01 градуса)