Как создать реальный заказ в 1 клик на d7

Когда-то пришлось столкнуться с необходимости создания реального заказа в Битриксе при покупки в 1 клик. Для формы я использовал веб-форму и компонент from.result.new, соответственно отлваливал событие создания результата формы и на нём генерировал заказ. Но, по большому счёту, где будет точка входа это дело техники и конкретной задачи. В статье я опущу детали, как получал данные по заполненной форме и напишу только о создании заказа.

Для начала определим use`ы

use Bitrix\Currency\CurrencyManager;
use Bitrix\Main\Context;
use Bitrix\Sale\Basket;
use Bitrix\Sale\Order;
use Bitrix\Main\Loader;
use Bitrix\Sale\Delivery\Services\Manager as DeliveryManager;
use Bitrix\Sale\PaySystem\Manager as PaySystemManager;

Дёрнем необходимые модули

Loader::includeModule('catalog');
Loader::includeModule('sale');
Loader::includeModule('iblock');

Данные которые я получил из заполненной веб-формы:

$name; // Имя пользователя
$email; // E-mail пользователя
$phone; // Телефон пользователя
$userComment; // Комментарий к заказу
$productId; // Id элемента

$userId = $fields['USER_ID'] ?: ONE_CLICK_BUY_USER_ID; // либо получаем из данных формы, либо берём по умолчанию

Первым делом, нужно достать цену со скидкой данного товар. Вот для этой процедуры на D7 я ничего не придумал, по этому зашёл в лоб:

$price = CCatalogProduct::GetOptimalPrice($productId, CUser::GetUserGroupArray());
if (empty($price['DISCOUNT_PRICE'])) {
    return;
}

Что бы выдернуть путь к карточке товара (а за одно и имя), пришлось снова обратиться к API старого ядра, не очень хотелось запариваться с самостоятельной обработкой URL по шаблону.

$orderFields['PRICE'] = $price['DISCOUNT_PRICE'];

$productInfo = [];
$elementsIterator = CIBlockElement::GetList(
    [],
    [
        'ID' => $productId,
        'IBLOCK_ID' => CATALOG_IBLOCK_ID,
    ],
    false,
    false,
    [
        'ID',
        'NAME',
        'DETAIL_PAGE_URL',
    ]
);
if (($element = $elementsIterator->GetNext(false, false))) {
    $productInfo = [
        'NAME' => $element['NAME'],
        'DETAIL_PAGE_URL' => $element['DETAIL_PAGE_URL'],
    ];
}

На этом подготовка данных закончилась. Теперь нужно создать заказ.

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

$siteId = Context::getCurrent()->getSite();
$basket = Basket::create($siteId);

$item = $basket->createItem('catalog', $productId);
$item->setFields([
    'QUANTITY' => 1,
    'CURRENCY' => CurrencyManager::getBaseCurrency(),
    'LID' => $siteId,
    'PRICE' => $orderFields['PRICE'],
    'NAME' => $productInfo['NAME'] ?? '',
    'DETAIL_PAGE_URL' => $productInfo['DETAIL_PAGE_URL'] ?? '',
]);

Далее создаём заказ и привязываем корзину к заказу

$order = Order::create($siteId, $userId);
$order->setPersonTypeId(PERSONAL_PERSON_TYPE); // в константе у меня храниться Id типа плательщика. По умолчанию все заказы будут создаваться из-под этого типа.
$order->setBasket($basket);

Теперь добавим в заказ доставку

$shipmentCollection = $order->getShipmentCollection();
$shipment = $shipmentCollection->createItem(
    DeliveryManager::getObjectById(ONE_CLICK_BUY_DELIVERY_ID) // В данной константе содержится Id службы доставки по умолчанию
 );

$shipmentItemCollection = $shipment->getShipmentItemCollection();

foreach ($basket as $basketItem) {
    /** @var \Bitrix\Sale\BasketItem $basketItem */
    /** @var \Bitrix\Sale\ShipmentItem $item */
    $item = $shipmentItemCollection->createItem($basketItem);
    $item->setQuantity($basketItem->getQuantity());
}

На следующем этапе добавим в заказ оплату

$paymentCollection = $order->getPaymentCollection();
/** @var \Bitrix\Sale\Payment $payment */
$payment = $paymentCollection->createItem(
    PaySystemManager::getObjectById(ONE_CLICK_BUY_PAYSYSTEM_ID) // В данной константе содержится Id службы оплтаы по умолчанию
);

В заказ нужно проставить общую сумму, валюту и комментарий:

$payment->setField('SUM', $order->getPrice());
$payment->setField('CURRENCY', $order->getCurrency());
$order->setField('COMMENTS', $userComment);

$order->doFinalAction(true);

Последним этапом будет заполнение свойств заказа данными.

/** В константах содержатся коды соответствующих свойств заказа */
foreach ($propertyCollection as $property) {
    switch (true) {
        case ($property->getField('CODE') == PERSONAL_EMAIL_FIELD_CODE && !empty($email)):
            $property->setValue($email);
            break;
            
        case $property->getField('CODE') == PERSONAL_PHONE_FIELD_CODE:
            $property->setValue($phone);
            break;
            
        case $property->getField('CODE') == PERSONAL_NAME_FIELD_CODE:
            $property->setValue($name);
            break;
            
        default:
            continue 2;
    }
}

$result = $order->save();

Что бы получить Id созданного заказа нужно дёрнуть getter:

$result->getId()

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

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *