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

В более старших версиях добавили новое поле в корзину PRODUCT_PROVIDER_CLASS, которое теперь берет на себя взаимодействие торгового каталога и интернет-магазина. По умолчанию это CCatalogProductProvider.

Если теперь мы добавим товар в корзину таким образом:

$arFields = array(
    'PRODUCT_ID' => 1,
    'NAME' => 'Новое имя товара',
    'PRICE' => 100,
    'DETAIL_PAGE_URL' => '/custom_url/',
 
);
CSaleBasket::Add($arFields);

Зайдем в корзину, и с удивлением обнаружим, что у добавленного товара «Название» и «Страница детального просмотра» поменялись на те, которые настоящие у товара, а не то что мы передали функции CSaleBasket::Add.

Всему виной провайдер CCatalogProductProvider, который и поддерживает взаимодействие с интернет магазином. Этот класс использует интерфейс IBXSaleProductProvider. Если заглянуть в код класса, то можно увидеть следующее:

$arResult = array(
    "NAME" => $arProduct["~NAME"],
    "CAN_BUY" => "Y",
    "DETAIL_PAGE_URL" => $arProduct['~DETAIL_PAGE_URL'],
    "BARCODE_MULTI" => $arCatalogProduct["BARCODE_MULTI"],
    "WEIGHT" => intval($arCatalogProduct['WEIGHT']),
    "DIMENSIONS" => serialize(array(
                                "WIDTH" => $arCatalogProduct["WIDTH"],
                                "HEIGHT" => $arCatalogProduct["HEIGHT"],
                                "LENGTH" => $arCatalogProduct["LENGTH"]
                                )
    ),
    "TYPE" => ($arCatalogProduct["TYPE"] == CCatalogProduct::TYPE_SET) 
        ? CCatalogProductSet::TYPE_SET : NULL
);
 
return $arResult;

Тут то и происходит подмена наших полей на стандартные.

Чтобы решить эту проблему, мы создадим свой провайдер, назовем его CCatalogProductProviderCustom, и подключим его в init.php

Код его будет такой:

if (!CModule::IncludeModule("sale") || !CModule::IncludeModule("catalog"))
    return false;
 
IncludeModuleLangFile(__FILE__);
 
class CCatalogProductProviderCustom extends CCatalogProductProvider
{
    public static function GetProductData($arParams)
    {
        // code
    }
 
    public static function OrderProduct($arParams)
    {
        // code
    }
 
}

Код функций GetProductData и OrderProduct надо взять из исходного класса CCatalogProductProvider. Только убрав в них две злосчастные строчки, чтобы получилось примерно так:

$arResult = array(
    //"NAME" => $arProduct["~NAME"],
    "CAN_BUY" => "Y",
    //"DETAIL_PAGE_URL" => $arProduct['~DETAIL_PAGE_URL'],
    "BARCODE_MULTI" => $arCatalogProduct["BARCODE_MULTI"],
    "WEIGHT" => intval($arCatalogProduct['WEIGHT']),
    "DIMENSIONS" => serialize(array(
                                "WIDTH" => $arCatalogProduct["WIDTH"],
                                "HEIGHT" => $arCatalogProduct["HEIGHT"],
                                "LENGTH" => $arCatalogProduct["LENGTH"]
                                )
    ),
    "TYPE" => ($arCatalogProduct["TYPE"] == CCatalogProduct::TYPE_SET) 
        ? CCatalogProductSet::TYPE_SET : NULL
);

И теперь при добавлении товара в корзину при помощи CSaleBasket::Add надо передавать передавать PRODUCT_PROVIDER_CLASS равным CCatalogProductProviderCustom.

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