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

Как создать корзину пользователя средствами API без авторизации, без $USER для любого пользователя?

Код вызова API функции, который приводит к проблеме:
Loader::includeModule('catalog');
Loader::includeModule('sale');
            
arFUser = CSaleUser::GetList(['USER_ID' => $userId]);
 $basket = Sale\Basket::loadItemsForFUser($arFUser['ID'], SITE_ID);
        
 if ($item = $basket->getExistsItem('catalog', $productId)) {
       $item->setField('QUANTITY', $item->getQuantity() + $quantity);
 } else {
                
        $item = $basket->createItem('catalog', $productId);
       //функция которая вызывает ошибку "setFields"                
       $item->setFields([
            'QUANTITY' => $quantity,
            'CURRENCY' => \Bitrix\Currency\CurrencyManager::getBaseCurrency(),
            'LID' => SITE_ID,
            'PRODUCT_PROVIDER_CLASS' => \Bitrix\Catalog\Product\Basket::getDefaultProviderName(),
      ]);
     $basketPropertyCollection = $item->getPropertyCollection(); 
     $basketPropertyCollection->setProperty($arProps);              
}
            
  $saveResult = $basket->save(); 
   if(!$saveResult->isSuccess())
        $arError[] = implode(', ', $saveResult->getErrors());


Здравствуйте.
Создаю мобильное API для магазина на Битрикс. Вызываю функцию которая создает корзину с товарами у пользователя указанного в запросе ($userId).
Указанные выше код работает только при условии что ранее уже была создана корзина с товарами у указанного пользователя.
Если же корзина пуста ($basket->isEmpty()) на этапе указанном в коде возникает ошибка:

2018-11-19 10:00:24 - Host: www.....ru:443 - UNCAUGHT_EXCEPTION - [Error] Call to a member function GetID() on null (0)
/home/bitrix/ext_www/.../bitrix/modules/sale/lib/basketitemcollection.php:258
#0: Bitrix\Sale\BasketItemCollection->getContext()
/home/bitrix/ext_www/.../bitrix/modules/sale/lib/basketbase.php:1075
#1: Bitrix\Sale\BasketBase->getContext()
/home/bitrix/ext_www/.../bitrix/modules/sale/lib/basketitembase.php:591
#2: Bitrix\Sale\BasketItemBase->onFieldModify(string, double, double)
/home/bitrix/ext_www/.../bitrix/modules/sale/lib/basketitem.php:962
#3: Bitrix\Sale\BasketItem->onFieldModify(string, NULL, integer)
/home/bitrix/ext_www/.../bitrix/modules/sale/lib/internals/entity.php:217
#4: Bitrix\Sale\Internals\Entity->setField(string, integer)
/home/bitrix/ext_www/.../bitrix/modules/sale/lib/basketitembase.php:381
#5: Bitrix\Sale\BasketItemBase->setField(string, integer)
/home/bitrix/ext_www/.../bitrix/modules/sale/lib/internals/entity.php:399
#6: Bitrix\Sale\Internals\Entity->setFields(array)
/home/bitrix/ext_www/.../bitrix/modules/sale/lib/basketitembase.php:479
#7: Bitrix\Sale\BasketItemBase->setFields(array)
/home/bitrix/ext_www/.../api/controllers/v1/basket.php:172 - здесь код моей функции
#8: Api\Controllers\v1\Basket->add()
/home/bitrix/ext_www/.../bitrix/modules/artamonov.api/lib/controller.php:99
#9: Artamonov\Api\Controller->startObjectOriented()
/home/bitrix/ext_www/.../bitrix/modules/artamonov.api/lib/controller.php:30
#10: Artamonov\Api\Controller->run()
/home/bitrix/ext_www/.../bitrix/modules/artamonov.api/lib/router.php:71
#11: Artamonov\Api\Router->start()
/home/bitrix/ext_www/.../bitrix/modules/artamonov.api/lib/init.php:29
#12: Artamonov\Api\Init->start()
/home/bitrix/ext_www/.../bitrix/php_interface/init.php:2
#13: include_once(string)
/home/bitrix/ext_www/.../bitrix/modules/main/include.php:234
#14: require_once(string)
/home/bitrix/ext_www/.../bitrix/modules/main/include/prolog_before.php:14
#15: require_once(string)
/home/bitrix/ext_www/.../bitrix/modules/main/include/prolog.php:10
#16: require_once(string)
/home/bitrix/ext_www/.../bitrix/header.php:1
#17: require(string)
/home/bitrix/ext_www/.../404.php:7
#18: include_once(string)
/home/bitrix/ext_www/.../bitrix/urlrewrite.php:4

В файле basketitemcollection.php идет вызов метода:
public function getContext()   {      
global $USER;
      $context = array();

      /** @var BasketItem $basketItem */
      $basketItem = $this->rewind();
      if ($basketItem)
      {

         $siteId = $basketItem->getField('LID');
         $fuserId = $basketItem->getFUserId();
         $currency = $basketItem->getCurrency();

         $userId = Fuser::getUserIdById($fuserId);

         if (empty($context['SITE_ID']))
         {
            $context['SITE_ID'] = $siteId;
         }

         if (empty($context['USER_ID']) && $userId > 0)
         {
            $context['USER_ID'] = $userId;
         }

         if (empty($context['CURRENCY']) && !empty($siteId))
         {
            if (empty($currency))
            {
               $currency = Internals\SiteCurrencyTable::getSiteCurrency($siteId);
            }

            if (!empty($currency) && Currency\CurrencyManager::checkCurrencyID($currency))
            {
               $context['CURRENCY'] = $currency;
            }
         }
      }

      if (empty($context['SITE_ID']))
      {
         $context['SITE_ID'] = SITE_ID;
      }

      if (empty($context['USER_ID']))
      {
         $context['USER_ID'] = $USER->GetID() > 0 ? $USER->GetID() : 0;
      }

      if (empty($context['CURRENCY']))
      {
         Loader::includeModule('currency');
         $context['CURRENCY'] = Currency\CurrencyManager::getBaseCurrency();
      }

      return $context;
   }

В getContext() идет вызов "$USER->GetID()" которырый и приводит к ошибке, т.к. не происходит авторизация пользователя средствами битрикс и не создается глобальный массив $USER.
Как можно решить проблему? Может можно как то передать в метод $item->setFields() значение FUserId, что бы не происходил вызов "$USER->GetID()"?
  • Вопрос задан
  • 1326 просмотров
Подписаться 1 Средний Комментировать
Решения вопроса 1
udjin123
@udjin123
PHP, Golang, React
У вас вызов идет из init.php, на этой стадии еще не существует глобального объекта класса CUser, он создается позже, лучше использовать событие OnPageStart

Но вы можете использовать известный "костыль", но это не совсем правильно,

global $USER;
$USER = new CUser();

И у вас будет рабочий экземпляр $USER, да метод GetID будет возвращать NULL, но ошибки больше не будет, да и дальше по коду класс будет заново инициализирован уже битриксом как обычно.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
alexey_bille
@alexey_bille
Web developer
$userId = ...;
$fuserId = \Bitrix\Sale\Fuser::getIdByUserId($userID);
$basket = \Bitrix\Sale\Basket::loadItemsForFUser($fuserId , Bitrix\Main\Context::getCurrent()->getSite());
Ответ написан
gromdron
@gromdron
Работаю с Bitrix24
Вы не можете создать заказ не имея пользователя в системе сохранив нормальную работу системы.

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

Как вы можете видеть, авторизация проверяется на более низком уровне и вы никак не сможете это сделать.
Ответ написан
Ваш ответ на вопрос

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

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