Задать вопрос

Как в битрикс, sale.order.ajax установить цену доставки по своей логике, в зависимости от действия пользователя?

Создал свою службу доставки. нужно что бы бы при выборе доставки, появилось поле, куда пользователь введет адрес или выберет его из подсказки, я обработаю эти данные и верну стоимость доставки.

Код службы доставки

<?php
use Bitrix\Main\Localization\Loc;
use Bitrix\Sale\Delivery\Services\Base;

Loc::loadMessages(__FILE__);

class AddressByZones extends Base
{
    /**
     * Название службы
     */
    public static function getClassTitle()
    {
        return 'Доставка по зонам + поле ввода';
    }

    /**
     * Описание службы
     */
    public static function getClassDescription()
    {
        return 'Служба доставки, которая отображает дополнительное поле при выборе.';
    }

    /**
     * Обязательный конструктор
     */
    public function __construct(array $initParams)
    {
        parent::__construct($initParams);
    }

    public function getConfigStructure()
    {
        return [
            'MAIN' => [
                'TITLE' => 'Настройки API',
                'ITEMS' => [
                   
                    ]
                ]
            ],
            'GEO_ZONES' => [
                'TITLE' => 'Зоны доставки',
                'ITEMS' => [
                    'ZONES_DATA' => [
                        'TYPE' => 'STRING',
                        "MULTILINE" => 'Y',
                        'NAME' => 'Данные зон (JSON)',
                        'DEFAULT' => '',
                        'ROWS' => 15,
                        'COLS' => 110
                    ]
                ]
            ]
        ];
    }

    /**
     * Расчёт стоимости
     */
    public function calculateConcrete(\Bitrix\Sale\Shipment $shipment = null)
    {
        $result = new \Bitrix\Sale\Delivery\CalculationResult();
        $description = '
        <div class="form-floating mb-3" style="position:relative;">
            <input class="form-control" type="text" id="delivery-address-input" placeholder="Введите адрес" autocomplete="off">
            <ul id="delivery-address-suggest" style="border:1px solid #ccc; z-index: 11; max-width:300px; position:absolute; background:#fff; list-style:none; margin:0; padding:0;"></ul>
        </div>
    ';

       $result->setDescription($description);

        return $result;
    }


    /**
     * Сохраняем введённое значение
     */
    public function getShipmentExtraServices()
    {
        return [];
    }

}



в order_ajax.js в блок init добавил

кусок order_ajax.js
BX.addCustomEvent('onAjaxSuccess', function () {
                console.log('вспиасть все обработчик');

                var selectedDeliveryId = document.querySelector('input[name="DELIVERY_ID"]:checked').value;
                console.log('выбрана доставка' + selectedDeliveryId);

                if (selectedDeliveryId == 765) {
                    // Проверяем, не загружен ли скрипт уже
                    if (!document.querySelector('script[src*="suggest-maps.yandex.ru"]')) {
                        var script = document.createElement('script');
                        script.src = 'https://suggest-maps.yandex.ru/v1/suggest?lang=ru_RU&apikey=***';
                        script.type = 'text/javascript';

                        script.onload = function () {
                            console.log('Яндекс Suggest API загружен');
                            // Здесь можно инициализировать функционал подсказок
                            initYandexSuggest();
                        };

                        script.onerror = function () {
                            console.error('Ошибка загрузки Яндекс Suggest API');
                        };

                        document.head.appendChild(script);
                    } else {
                        console.log('Яндекс Suggest API уже загружен');
                        //initYandexSuggest();
                    }
                    /* подсказка */
                    const input = document.getElementById("delivery-address-input");
                    const suggestions = document.getElementById("delivery-address-suggest");

                    console.log('input');
                    console.log(input);

                    console.log('suggestions');
                    console.log(suggestions);

                    input.addEventListener("input", async function () {
                        const query = input.value.trim();
                        if (query.length < 3) {
                            suggestions.innerHTML = "";
                            return;
                        }

                        try {
                            const res = await fetch(`/_dev/yandex_suggest/proxy.php?q=${encodeURIComponent(query)}`);
                            const data = await res.json();

                            console.log("Yandex raw:", data); // отладка

                            suggestions.innerHTML = "";

                            if (Array.isArray(data.results)) {
                                data.results.forEach(item => {
                                    const title = item.title?.text || "";
                                    const subtitle = item.subtitle?.text || "";
                                    const distance = item.distance?.text || "";

                                    const li = document.createElement("li");
                                    li.style.padding = "10px";
                                    li.style.cursor = "pointer";
                                    li.innerHTML = `<strong>${title}</strong>
                    ${subtitle ? `<br><small>${subtitle}</small>` : ""}`;

                                    li.addEventListener("click", async () => {
                                        input.value = subtitle + ", " + title;

                                        console.log('выбранный адрес');
                                        console.log(input.value);

                                        /* полученный адрес нужно отправить на получение координат */
                                        // Отправка адреса на Bitrix обработчик
                                        try {
                                            // Формируем URL с параметрами
                                            const url = '/bitrix/tools/AddressByZonesGetCoordinate.php';

                                            // Отправляем POST запрос
                                            console.log('Проверяем что отправляем');
                                            console.log(encodeURIComponent(input.value));

                                            const response = await fetch(url, {
                                                method: 'POST',
                                                headers: {
                                                    'Content-Type': 'application/x-www-form-urlencoded',
                                                },
                                                body: encodeURIComponent(input.value)
                                            });

                                            if (!response.ok) {
                                                throw new Error('Ошибка HTTP: ' + response.status);
                                            }

                                            const result = await response.text(); // Добавлен await
                                            console.log('Ответ от Bitrix обработчика:', result);

                                            if (result == 'SPB_A') {
                                                console.log('ВСЕ ок SPB_A,  можно ставить цену 222');

                                          
                                            }

                                        } catch (error) {
                                            console.error('Ошибка при получении координат:', error);
                                        }

                                        suggestions.innerHTML = "";
                                    });

                                    suggestions.appendChild(li);
                                });
                            } else {
                                console.warn("Нет results в ответе", data);
                            }
                         //   this.sendRequest();
                        } catch (err) {
                            console.error("Ошибка:", err);
                        }
                    });

                }
            });


тут я получил нужный результат, как теперь устанвоить стоимость доставки в оформлении заказа?
или может кто делал по другой логике?
  • Вопрос задан
  • 147 просмотров
Подписаться 2 Сложный Комментировать
Помогут разобраться в теме Все курсы
  • Нетология
    Python-разработчик с нуля
    6 месяцев
    Далее
  • Академия Eduson
    Frontend-разработчик
    9 месяцев
    Далее
  • Логомашина
    Графический дизайн с нуля
    7 месяцев
    Далее
Решения вопроса 1
Ошибка в самом начале.
Расчёт стоимости должен происходить в calculateConcrete, а не на фронте.

Если просто «подставить цену» в верстку через JS:
• эта цена не сохранится в заказе (в админке будет другая или нулевая);
• её можно подменить в браузере;
• при любом пересчёте (пересчёт корзины, изменение доставки/оплаты) Битрикс заново вызовет calculateConcrete(), и фронтовая цена потеряется.

Логика такая:
Цена доставки в Битриксе должна считаться на backend в calculateConcrete(), а фронт только собирает данные (адрес, координаты, зона) и инициирует пересчёт. Чтобы backend увидел данные с фронта их можно сохранить в свойство заказа.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы