Войти Регистрация
Корзина 0 позиций
на сумму 0 ₽
8 (831) 274-00-00

У встроенного в Битрикс модуля Почта России есть возможность передавать на страницу  в личном кабинете покупателя ссылки для отслеживания трек номера на сайт перевозчика "проверить отправление".


Ссылка выглядит так: https://pochta.ru/tracking#80091763556299


Есть проблема, что они сейчас не работают у некоторых перевозчиков, например СДЭК не работает ссылка,
наверно это сделано для защиты от ботов.
В СДЭК трек нужно вводить в окно на странице отслеживания  и работает на скриптах страницы.

Но все равно это нужно сделать потому, что есть механизм ссылка по которой можно перейти на страницу отслеживания
У других перевозчиков такой ссылки нет в личном кабинете покупателя, вместо неё пусто.

Задача:
Ссылку нужно добавить каждому перевозчику, чтоб покупатель не только Почта России мог перейти по ссылке отслеживать перемещения заказа.

Как это сделать?

Попробуем отследить где в коде есть pochta.ru
Ищем по коду...

Скорее всего это здесь:
/bitrix/modules/sale/lib/delivery/tracking/rus_post.php

/**
 * @param string $trackingNumber
 * @return string Url were we can see tracking information (строка возврата URL, где мы можем видеть информацию для отслеживания)
 */
public function getTrackingUrl($trackingNumber = '')
{
return 'https://pochta.ru/tracking'.($trackingNumber <> '' ? '#'.$trackingNumber : '');


Ищем по "проверить отправление"
Ищем по коду...

Подробная информация о заказе
(bitrix:sale.personal.order.detail)

/var/www/intercom-nn.ru/bitrix/templates/eshop_bootstrap_v4/components/bitrix/sale.personal.order.detail/.default/lang/ru
28:template.php

$MESS["SPOD_ORDER_CHECK_TRACKING"] = "проверить отправление";



пробуем найти по SPOD_ORDER_CHECK_TRACKING

/bitrix/components/bitrix/sale.personal.order.detail/templates/bootstrap_v4/template.php

<? if($shipment['TRACKING_URL'] <> '')
{
<------>?>
<------><div
<------><------>class="mb-2 sale-order-detail-payment-options-shipment-button-container">
<------><------><a href="" onclick="return false"
<------><------>   class="sale-order-detail-payment-options-shipment-button-element"
<------><------>   href="<?= $shipment['TRACKING_URL'] ?>"><?= Loc::getMessage('SPOD_ORDER_CHECK_TRACKING') ?></a>
<------></div>
<------><?
}
?>


пробуем найти: TRACKING_URL

/bitrix/components/bitrix/sale.personal.order.detail/class.php

if ($shipment["DELIVERY_ID"] > 0 && mb_strlen($shipment["TRACKING_NUMBER"]))
{
<------>$shipment["TRACKING_URL"] = $trackingManager->getTrackingUrl($shipment["DELIVERY_ID"], $shipment["TRACKING_NUMBER"]);
}

пробуем найти: trackingManager

/bitrix/components/bitrix/sale.personal.order.detail/class.php

$trackingManager = Sale\Delivery\Tracking\Manager::getInstance();


/bitrix/modules/sale/lib/delivery/tracking/manager.php

/**
 * @return static
 */
public static function getInstance()
{
<------>if (self::$instance === null)
<------><------>self::$instance = new static();

<------>return self::$instance;
}

Найдем: getTrackingUrl

/bitrix/modules/sale/lib/delivery/tracking/manager.php

/**
<------> * @param int $deliveryId Delivery service id. (Идентификатор службы доставки.)
<------> * @param string (строка параметров) $trackingNumber Trcking number. (Номер отслеживания.)
<------> * @return string  Url were we can see tracking information. (по которому мы можем видеть информацию для отслеживания.)
<------> * @throws ArgumentNullException (вызывает исключение)
<------> */
<------>public function getTrackingUrl($deliveryId, $trackingNumber = '')
<------>{
<------><------>if(!$deliveryId)
<------><------><------>return '';

<------><------>$trackingObject = $this->getTrackingObjectByDeliveryId($deliveryId);

<------><------>if(!$trackingObject)
<------><------><------>return '';

<------><------>return $trackingObject->getTrackingUrl($trackingNumber);
<------>}


/bitrix/modules/sale/lib/delivery/tracking/rus_post.php

/**
 * @param string $trackingNumber
 * @return string Url were we can see tracking information
 */
public function getTrackingUrl($trackingNumber = '')
{
<------>return 'https://pochta.ru/tracking'.($trackingNumber <> '' ? '#'.$trackingNumber : '');
}

еще тут:

/bitrix/modules/sale/handlers/delivery/spsr/tracking.php

/**
 * @param string (строка параметров) $trackingNumber
 * @return string Url were we can see tracking information (URL-адрес возвращаемой строки, если бы мы могли видеть информацию об отслеживании)
 */
public function getTrackingUrl($trackingNumber = '')
{
<------>return 'http://www.spsr.ru/ru/service/monitoring';
}

и еще один

/bitrix/modules/sale/handlers/delivery/additional/tracking.php

/**
 * @param string $trackingNumber
 * @return string Url were we can see tracking information
 */
public function getTrackingUrl($trackingNumber = '')
{
<------>$result = '';

<------>/** @var \Sale\Handlers\Delivery\AdditionalHandler  $parentService */
<------>$parentService = $this->deliveryService->getParentService();
<------>$trackingUrlTempl = $parentService->getTrackingUrlTempl();

<------>if(!empty($trackingUrlTempl))
<------><------>$result = str_replace('##TRACKING_NUMBER##', urlencode($trackingNumber), $trackingUrlTempl);...........................................................

<------>return $result;
}

и еще тут

/bitrix/modules/sale/lib/delivery/tracking/base.php

/**
 * @param string $trackingNumber
 * @return string Url were we can see tracking information (URL-адрес возвращаемой строки, если бы мы могли видеть информацию об отслеживании)
 */
public function getTrackingUrl($trackingNumber = '')
{
<------>return '';
}

Попробовал подставить в
/bitrix/modules/sale/lib/delivery/tracking/rus_post.php
вместо
//<----><------>return 'https://pochta.ru/tracking'.($trackingNumber <> '' ? '#'.$trackingNumber : '');
строку
<------><------>return 'https://tracking.ozon-dostavka.ru/?SearchId'.($trackingNumber <> '' ? '='.$trackingNumber : '');

Сслка у заказов Почта России отображается на сайт доставки озон
У заказов с доставкой озон трек на клиентской странице отображаться не стал.


В Административной части сайта:

для остальных служб доставки ссылка на строку отслеживания также недоступна, как и в пользовательском разлеле.

Скрыты строки сами название и данные то что должно отображаться:
Статусотправления
Описание статуса
Подробнее о статусе отправления

В базе данных есть таблица Таблица: b_sale_order_delivery  есть столбец TRACKING_DESCRIPTION

Подробнее о статусе отправления: https://pochta.ru/tracking#80091763556299


sale-order-shipment-tracking-description-1           adm-detail-content-cell-r tal     


Попробуем найти поиском: "Подробности можно посмотреть по ссылке"
найден
в /bitrix/modules/sale/lang/ru/lib/delivery/tracking/rus_post.php
строка
$MESS["SALE_DELIVERY_TRACKING_RUS_POST_STATUS_DESCR"] = "Подробности можно посмотреть по ссылке";

ищем "SALE_DELIVERY_TRACKING_RUS_POST_STATUS_DESCR"

находим

в /bitrix/modules/sale/lib/delivery/tracking/rus_post.php


258: $result->description = $this->createDescription($trackingNumber);

/**
 * @param string $trackingNumber
 * @return string
 */
protected function createDescription($trackingNumber)
{
$link = 'https://pochta.ru/tracking#'.$trackingNumber;
return Loc::getMessage('SALE_DELIVERY_TRACKING_RUS_POST_STATUS_DESCR').': '.'<a href="'.$link.'">'.$link.'</a>';
}


У другмх перевозчиков такой информации нет, а трек номер есть
Значит есть условие при котором эта строка не появляется, если это не Почта России
или может быти если нет ?


$MESS["SALE_ORDER_SHIPMENT_TRACKING_URL"] = "Подробнее о статусе отправления";

Смотрим


Смотрим... "Идентификатор отправления" отображается у всех доставок

а
"Описание статуса" и "Подробнее о статусе отправления" отображается только у Почта России





$MESS["SALE_ORDER_SHIPMENT_TRACKING_NUMBER"] = "Идентификатор отправления";

Если убираем условие: $data['HAS_TRACKING']


Тогда появляются строки которые отображаются у Почта России



$fields['HAS_TRACKING'] = $delivery->getTrackingClass() <> '' ? true : false;

Нужно искать TrackingClass похоже что отображение скрытых строк зависит от того что там true или false

Если TRACKING_DISCRIPTION  Прописать текст, тогда он появится в "Описание статуса"


Но, если после этого нажать на кнопку "Статус отправления" "Обновить " то информация в таблице затирается.
И соответственно описание статуса опять становится пустым.

А по "Подробнее о статусе отправления" здесь также как и в личном кабинете покупателя

/bitrix/modules/sale/lib/helpers/admin/blocks/ordershipment.php

if($fields['HAS_TRACKING'] && intval($fields['DELIVERY_ID']) > 0)
{
<------>$trackingManager = \Bitrix\Sale\Delivery\Tracking\Manager::getInstance();
<------>$fields['TRACKING_URL'] = $trackingManager->getTrackingUrl($fields['DELIVERY_ID'], $fields['TRACKING_NUMBER']);
}

/bitrix/modules/sale/lib/delivery/tracking/manager.php

/**
 * @return static
 */
public static function getInstance()
{
<------>if (self::$instance === null)
<------><------>self::$instance = new static();

<------>return self::$instance;
}



/**
<------> * @param int $deliveryId Delivery service id. (Идентификатор службы доставки.)
<------> * @param string $trackingNumber Trcking number. (Номер отслеживания.)
<------> * @return string  Url were we can see tracking information. (по которому мы можем видеть информацию для отслеживания.)
<------> * @throws ArgumentNullException (вызывает исключение)
<------> */
<------>public function getTrackingUrl($deliveryId, $trackingNumber = '')
<------>{
<------><------>if(!$deliveryId)
<------><------><------>return '';

<------><------>$trackingObject = $this->getTrackingObjectByDeliveryId($deliveryId);

<------><------>if(!$trackingObject)
<------><------><------>return '';

<------><------>return $trackingObject->getTrackingUrl($trackingNumber);
<------>}

Найдем:getTrackingObjectByDeliveryId
/bitrix/modules/sale/admin/delivery_service_edit.php

<?if($isTrackingTabShow):?>
<------><?$tabControl->BeginNextTab();
<------><------>$tManager = Delivery\Tracking\Manager::getInstance();
<------><------>$tracking = $tManager->getTrackingObjectByDeliveryId($ID);
<------><------>$trackingParamsStructure = $tracking->getParamsStructure()
<------><------>?><tr>
<------><------><td width="40%" class="adm-detail-valign-top"><?=Loc::getMessage("SALE_DSE_FORM_DESCRIPTION")?>:</td>
<------><------><td width="60%">
<------><------><------><?=$tracking->getClassDescription()?>
<------><------><------><?=(empty($trackingParamsStructure) ? '<br>'.Loc::getMessage('SALE_DSE_TAB_TRACKING_PARAMS_EMPTY') : '')?>.....................................
<------><------></td></tr>
<------><------><?if(!empty($trackingParamsStructure)):?>
<------><------><------><tr class="heading"><td colspan="2"><?=Loc::getMessage("SALE_DSE_TAB_TRACKING_PARAMS")?></td></tr>
<------><------><------><?foreach($trackingParamsStructure as $id => $params):?>
<------><------><------><------><tr>
<------><------><------><------><------><td width="40%"><?=$params["LABEL"]?>:</td>
<------><------><------><------><------><td width="60%">
<------><------><------><------><------><------><?=$tracking->getEditHtml($id,"TRACKING_PARAMS[".$id."]")?>
<------><------><------><------><------></td>
<------><------><------><------></tr>
<------><------><------><?endforeach;?>
<------><------><?endif;?>
<?endif;?>


10_WAITING_SHIPMENT_status_DB (В пункте приёма)
20_ON_THE_WAY_status_DC (В пути)
30_ARRIVED_status_DD (Готов к выдаче)
40_HANDED_status_DF (Выдача произведена)
50_PROBLEM_status_DZ
60_UNKNOWN_status_DX
70_RETURNED_status_DR

​​​​​​​​​​

04.10.2021, 9:38  Добрый день.

Спасибо за пояснения. Технически, в штатных компонентах Битрикса ссылка для отслеживания, видимо, завязана на получение информации от службы доставки через метод getTrackingUrl класса обработчика СД, ответственного за трекинг отправлений. У современных обработчиков служб доставок, как у Почты или Озона, можно "прикрутить" tracking class и в теории все должно заработать само собой.

Т.е. это не просто готовая ссылка, которая где-то хранится. 

У Озона по ТЗ такой функционал не требовали, поэтому не было реализовано. Плюс у Битрикса традиционно очень "подробная" документация: все, что известно про создание своего tracking class:

"У служб доставок существует механизм автоматического отслеживания идентификаторов отправления (трэкинг-номеров)". Какая начинка должна быть по минимуму, что для чего - разбирайтесь сами, анализируя исходники Битрикса и обработчиков, где это работает. 

Соответственно:

- Чтобы решить эту задачу для Озона, нужно прикрутить свой tracking class к нему (что потребует доработки модуля, т.к. в его обработчике оный класс со своими методами сейчас отсутствует)

- В общем случае каждой доставке нужно делать свой класс отслеживания. При этом нет уверенности, что для СД, использующих ныне устаревший вариант обработчика "автоматизированная служба доставки" (СДЭК, DPD, Boxberry и т.п.) это вообще реализуемо, по другим решениям таких примеров не видели, нужно смотреть исходники Битрикса. 

- Можно пойти другим путем и кастомизировать сам компонент на странице

https://intercom-nn.ru/personal/orders/95888?access=a49aa812bd3cb48f488988d9b6ad2d79 .

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

05.10.2021, 15:21

Спасибо, более-менее посмотрели что в движке и обработчике Почты России

, который Битрикс предлагает брать как пример вместо написания адекватной документации. 

В общем, помимо формирования ссылки на отслеживание класс трекинга отвечает еще и за статусы трекинга, на примере заказа 95190 и его отгрузки в Почту - вот этот блок параметров

. Как видите, тут есть кнопка обновления статусов трекинга, которая делает запрос к серверу Почты, получает информацию об этом отправлении и , обработав, отдает движку CMS в формализованном виде, а тот "двигает" статус трекинга этой отгрузки, причем это НЕ то же самое, что статус отгрузки 

Из плюсов - вроде не слишком времязатратно реализовать желаемое. 

Из минусов - похоже, что колдунство с запросами статусов трекинга от ТК обязательно, т.е. даже если оно вам совсем не требуется, его придется реализовать в классе трекинга. Причем в движке Битрикса жестко прошиты статусы трекинга, которые вообще могут быть, их всего 8

, без влезания в ядро CMS добавить свои нельзя, поменять тексты нельзя и связать это чудо со статусами Отгрузок (например, по трекингу заказ перешел в определенный статус - и отгрузка тоже перешла в него, как сейчас обновление статусов заказов работает по статусам, получаемым от Озон) тоже нельзя. 

По времени порядка 4 ч оценка, с учетом, что часть времени пошла на расковыривание движка CMS

Сделано 11.10.2021

/bitrix/modules/ipol.ozon/classes/lib/Bitrix/Handler/DeliveryHandlerProfile.php

и создан файл: /bitrix/modules/ipol.ozon/classes/lib/Bitrix/Handler/Tracking.php

<?
namespace Ipol\Ozon\Bitrix\Handler;

use \Bitrix\Main\Localization\Loc;
use \Bitrix\Main\Error;
use \Bitrix\Sale\Result;
use \Bitrix\Sale\Delivery\Tracking\StatusResult;
use \Bitrix\Sale\Delivery\Tracking\Statuses;

use \Ipol\Ozon\StatusHandler;
use \Ipol\Ozon\OrdersTable;
use \Ipol\Ozon\Bitrix\Tools;
use \Ipol\Ozon\Bitrix\Controller\Status;

Loc::loadMessages(__FILE__);

/**
 * Class Tracking
 * @package namespace Ipol\Ozon\Bitrix\Handler
 */
class Tracking extends \Bitrix\Sale\Delivery\Tracking\Base
{
    /**
     * @return string
     */
    public function getClassTitle()
    {
        return Tools::getMessage('TRACKING_TITLE');
    }

    /**
     * @return string
     */
    public function getClassDescription()
    {
        return Tools::getMessage('TRACKING_DESCRIPTION');
    }

    /**
     * Get Bitrix Tracking status by tracking number
     * @param $trackingNumber
     * @return \Bitrix\Sale\Delivery\Tracking\StatusResult
     */
    public function getStatus($trackingNumber)
    {
        $statusResult = new StatusResult();

        $trackingNumber = trim($trackingNumber);
        /*if (preg_match('/^[A-Z]{2}?\d{9}?[A-Z]{2}$/i', $trackingNumber) !== 1)
            $statusResult->addError(new Error(Tools::getMessage('TRACKING_ERROR_WRONG_FORMAT')));*/

        if (!\Ipol\Ozon\AuthHandler::isAuthorized())
            $statusResult->addError(new Error(Tools::getMessage('TRACKING_ERROR_NO_AUTH')));

        $orders = OrdersTable::getList([
            'select' => ['ID', 'BITRIX_ID', 'LOGISTIC_ORDER_NUMBER', 'POSTING_ID'],
            'filter' => ['=LOGISTIC_ORDER_NUMBER' => $trackingNumber],
            'order'  => ['ID' => 'ASC'],
        ])->fetchAll();

        if (count($orders) > 1) {
            // What if some goat edited orders table manually and LOGISTIC_ORDER_NUMBER not unique?
            $statusResult->addError(new Error(Tools::getMessage('TRACKING_ERROR_DUPLICATE_ORDERS').$trackingNumber));
        } else if (empty($orders)) {
            $statusResult->addError(new Error(Tools::getMessage('TRACKING_ERROR_NO_ORDERS').$trackingNumber));
        } else {
            $primaryId = $orders[0]['ID'];
            $postingId = $orders[0]['POSTING_ID'];
            if (empty($postingId))
                $statusResult->addError(new Error(Tools::getMessage('TRACKING_ERROR_NO_POSTING_ID').$trackingNumber));
        }

        if ($statusResult->isSuccess())
        {
            $handler = new Status();
            $answer = $handler->checkStatus($postingId);

            if ($answer && $answer->isSuccess()) {
                StatusHandler::settleStatuses($answer, $postingId);

                // Get last inner module status from local table
                $order = OrdersTable::getByOrderId($primaryId, ['STATUS']);

                $statusResult->trackingNumber = $trackingNumber;
                $statusResult->status = self::getMappedStatus($order['STATUS']);

                $link = $this->getTrackingUrl($trackingNumber);
                $statusResult->description = Tools::getMessage('TRACKING_STATUS_DESCR').'<a href="'.$link.'">'.$link.'</a>';

                $events = $answer->getResponse()->getItems();
                if ($events && $events->getLast()) {
                    $statusResult->lastChangeTimestamp = strtotime($events->getLast()->getMoment());
                }
            }
            else
                $statusResult->addError(new Error(Tools::getMessage('TRACKING_ERROR_REQUEST_FAIL').$trackingNumber));
        }

        return $statusResult;
    }

    /**
     * Get Bitrix Tracking statuses by tracking numbers array
     * @param array $trackingNumbers
     * @return \Bitrix\Sale\Delivery\Tracking\StatusResult[]
     */
    public function getStatuses(array $trackingNumbers)
    {
        $data = array();

        foreach($trackingNumbers as $number)
            $data[$number] = $this->getStatus($number);

        return $data;
    }

    /**
     * Map corresponded Bitrix Tracking status with module inner status
     * @param string $moduleStatus
     * @return string
     */
    protected static function getMappedStatus($moduleStatus)
    {
        switch ($moduleStatus)
        {
            case 'NEW':
            case 'OK':
                $bitrixStatus = Statuses::NO_INFORMATION;
                break;
            case 'REGISTRED':
            case 'SENDED':
            case 'DATEWAITS':
            case 'SENDEDTOCITY':
            case 'ARRIVEDTOCITY':
                $bitrixStatus = Statuses::ON_THE_WAY;
                break;
            case 'READYFORGIVE':
            case 'COURIER':
                $bitrixStatus = Statuses::ARRIVED;
                break;
            case 'GIVEN':
            case 'GIVENPART':
                $bitrixStatus = Statuses::HANDED;
                break;
            case 'PARTRETURN':
            case 'RETURNPRECEED':
            case 'RETURNREADY':
            case 'RETURNDONE':
                $bitrixStatus = Statuses::RETURNED;
                break;
            case 'REFUSE':
            case 'REJECTED':
            case 'ANNULED':
                $bitrixStatus = Statuses::PROBLEM;
                break;
            default:
                $bitrixStatus = Statuses::UNKNOWN;
                break;
        }

        return $bitrixStatus;
    }

    /**
     * @param string $trackingNumber
     * @return string Url were we can see tracking information
     */
    public function getTrackingUrl($trackingNumber = '')
    {
        return 'https://tracking.ozon-dostavka.ru/?SearchId=&#39;.$trackingNumber;
    }

    /**
     * Returns params structure
     * @return array
     */
    public function getParamsStructure()
    {
        return [];
    }
}


Войти Регистрация
Корзина 0 позиций
на сумму 0 ₽