Реализация функционала «купить в 1 клик» на Битрикс

  • 1035
   
Разделы

Я не претендую на право называться автором всей размещенной здесь информации, так как некоторые моменты были заимствованы в доступных источниках и немного переработаны для удобства пользования.


По возможности указываю ссылки на источники.


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

Частный вебмастер по разработке сайтов на 1С Битрикс и WordPress

Потребовалось на сайте реализовать упрощенный процесс покупки товара в 1 клик с указанием номера телефона и имени. Покупка осуществляется со страницы товара и в самой корзине. При покупке в корзине оформляется вся корзина, а на странице товара только этот товар.

Данные отправляются AJAX – ом и обрабатываются, чтобы не загружать страницу при загрузке, ну и чтобы при оформлении лишних перезагрузок не было.

Код максимально комментировал. Если возникнут проблемы, учите матчасть =)

В нашем случае этот обработчик кроме запросов покупки в 1 клик, обрабатывает все остальные формы сайта (если вдруг что-то лишнее нашли в коде=)).

Начнем со всплывающей формы, которая находится в подвале сайта.

<?
// ВЫВОД ИНФОРМАЦИИ О ТОВАРАХ, КОТОРЫЕ СОБИРАЕМСЯ КУПИТЬ


if($APPLICATION->GetCurPage() == '/personal/cart/') {
// Если покупка происходит в корзине

// получаем товары из корзины
$basket = \Bitrix\Sale\Basket::loadItemsForFUser(Bitrix\Sale\Fuser::getId(), Bitrix\Main\Context::getCurrent()->getSite());

// выводим циклом
$basketItems = $basket->getBasketItems();
foreach ($basket as $basketItem) {
$res = CIBlockElement::GetByID($basketItem->getField('PRODUCT_ID'));
$ar_res = $res->GetNext()
?>
<div class="basket__product m-click__product flex align-center">
<a href="<?= $basketItem->getField('DETAIL_PAGE_URL') ?>" class="basket__product-img">
<img src="<?=CFile::GetPath($ar_res["PREVIEW_PICTURE"])?>" alt="<?= $basketItem->getField('NAME') ?>">
</a>
<a href="<?= $basketItem->getField('DETAIL_PAGE_URL') ?>" class="basket__product-title">
<?= $basketItem->getField('NAME') ?>
</a>
</div>
<?
}
} else {
// Если покупка происходит на странице товара

// получаем ИД товара и выводим инфу
$productID = $APPLICATION->GetPageProperty('productId');
if ($productID) :
$res = CIBlockElement::GetByID($productID);
$ar_res = $res->GetNext()
?>
<div class="basket__product m-click__product flex align-center">
<a href="<?= $ar_res['DETAIL_PAGE_URL'] ?>" class="basket__product-img">
<img src="<?=CFile::GetPath($ar_res["PREVIEW_PICTURE"])?>" alt="<?= $ar_res['NAME'] ?>">
</a>
<a href="<?= $ar_res['DETAIL_PAGE_URL'] ?>" class="basket__product-title">
<?= $ar_res['NAME'] ?>
</a>
</div>

<?
endif;
}
?>

<!-- Форма -->
<form id='m-click' class="m-contact__form" method="post" enctype="multipart/form-data" onsubmit="sendForm(event)">
<input class='modal__input' type="text" required placeholder="Ваше имя" name='userName'>
<input class='modal__input' required type="tel" maxlength="28" placeholder="Телефон" name='userTel'>

<input hidden type="text" name='pageUrl' value="<?=$APPLICATION->GetCurPage()?>">
<input hidden type="text" name='productId' value="<?=$APPLICATION->GetPageProperty('productId')?>">

<div class="m-contact__caption">
Отправляя заявку, вы соглашаетесь с нашей <a class='link' href="#">политикой конфеденциальности</a>
</div>

<button type='submit' class="btn btn_red modal__btn">Купить в один клик</button>
</form>

JS

/***  ФОРМА ОТПРАВКИ  ***/
function sendForm(event) {
event.preventDefault();
let data = new FormData(event.target);
//console.log(data)
$.ajax({
url: '/local/ajax/send.php',
method: 'post',
contentType: false,
processData: false,
dataType: 'html',
data: data,
success: function(data){
// ошибок нет
console.log(data);
},
error: function(data) {
// ошибка
console.log(data);
}
});
}

Обработчик

<? require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/prolog_before.php");

// подключаем модуль отправки данных
use Bitrix\Main\Mail\Event;


/*** Получаем данные из формы отправленные скриптом ***/
// перед присвоением в переменную, проверяем есть ли данные
if (!empty($_POST["userName"])) $name = $_POST['userName'];
if (!empty($_POST["userTel"])) $phone = $_POST['userTel'];
if (!empty($_POST["pageUrl"])) $pageUrl = $_POST['pageUrl'];

if (!empty($_POST["productId"])) $productId = $_POST['productId'];


// перекодировка для работы с кирилицей. На случай если сайт работает в кодировке windows-1251
// если сайт на UTF-8, закоментируй строку ниже
$_POST['userName'] = iconv('UTF-8', 'windows-1251', $_POST['userName']);


/*** Проверка данных ***/
if ($name && $phone) {


/** Оформление заказа **/
// подключаем библиотеки
CModule::IncludeModule("sale");
CModule::IncludeModule("catalog");


// функция заказа
function makeOrder($products)
{

// проверяем авторизацию пользователя
global $USER;
if ($USER->GetID() != 0) {
// если пользователь авторизован
$userId = $USER->GetID();
} else {
// если пользователь не авторизован, то выдаем ИД анонимного пользователя
// у меня в системе он был, если нет, создайте
// так же, можно авторизовать пользователя и выдать ему его ИД
$userId = \CSaleUser::GetAnonymousUserID();
}


// создадим объект корзины
$basket = Bitrix\Sale\Basket::create('s2');
foreach ($products as $product) {
$item = $basket->createItem("catalog", $product["PRODUCT_ID"]);
unset($product["PRODUCT_ID"]);
$item->setFields($product);

}

// создать сам заказ
$order = Bitrix\Sale\Order::create('s2', $userId);
$order->setPersonTypeId(1);
$order->setBasket($basket);


// создать отгрузки
$shipmentCollection = $order->getShipmentCollection();
$shipment = $shipmentCollection->createItem(
Bitrix\Sale\Delivery\Services\Manager::getObjectById(1)
);


// Наполним отгрузку товарами
$shipmentItemCollection = $shipment->getShipmentItemCollection();
foreach ($basket as $basketItem) {
$item = $shipmentItemCollection->createItem($basketItem);
$item->setQuantity($basketItem->getQuantity());
}

// создадим оплату
$paymentCollection = $order->getPaymentCollection();
$payment = $paymentCollection->createItem(
Bitrix\Sale\PaySystem\Manager::getObjectById(1)
);

// сохранить наш заказ
$result = $order->save();
if (!$result->isSuccess()) {
$result->getErrors();
}
// для проверки
//print_r($result);
}


// тут разбираемся, нажал пользователь купить в 1 клик на странице товара или в корзине
if ($productId) {
// если покупаем со страницы товара

// получаем инфы о товаре по ИД
$ar_res = CIBlockElement::GetByID($productId);
$arProd = $ar_res->GetNext(); // инфа
$arPrice = CPrice::GetBasePrice($productId); // цена товара по ИД

// формируем массив для отправки в функцию заказа
$products = array(
array(
'PRODUCT_ID' => $productId,
'NAME' => $arProd['NAME'],
'PRICE' => $arPrice['PRICE'],
'CURRENCY' => 'RUB',
'QUANTITY' => 1,
'PRODUCT_PROVIDER_CLASS' => '\Bitrix\Catalog\Product\CatalogProvider',
)
);
// отправляем в функцию
makeOrder($products);

} else {
// оформление всей корзины

// получение списка товаров корзины
$basket = \Bitrix\Sale\Basket::loadItemsForFUser(Bitrix\Sale\Fuser::getId(), Bitrix\Main\Context::getCurrent()->getSite());

// формируем массив для отправки в функцию заказа
$basketItems = $basket->getBasketItems();
foreach ($basket as $basketItem) {

$products[] =
[
'PRODUCT_ID' => $basketItem->getField('PRODUCT_ID'),
'NAME' => $basketItem->getField('NAME'),
'PRODUCT_PROVIDER_CLASS' => '\Bitrix\Catalog\Product\CatalogProvider',
'PRICE' => $basketItem->getField('PRICE'),
'CURRENCY' => 'RUB',
'QUANTITY' => $basketItem->getField('QUANTITY')
];
}

// отправляем в функцию
makeOrder($products);
// очистка корзины
CSaleBasket::DeleteAll(CSaleBasket::GetBasketUserID());
}

// для проверки
// print_r($products);


/** сохранение данных в инфоблок **/
// подключаем модуль инфоблоков
CModule::IncludeModule('iblock');
// инициализируем
$elem = new CIBlockElement;

// берем все входящее данные и пихаем в строку
if (empty($_POST['userTel']))
$_POST['userTel'] = $_POST[0];
$text = '';
foreach ($_POST as $name => $val) {
$text .= $name . ' : ' . $val . '
';
}
// добавляем товары к этой строке
$productList = '';
foreach ($products as $product) {
$productList .= $product['NAME'] . ' - ' . round($product['QUANTITY']) . ';
';
}
$text .= $productList;


// все ид файлов присваиваем свойству, если есть, у меня нет)
$PROP['FILES'] = [];

// настройки
$arLoadProductArray = array(
"MODIFIED_BY" => 1,
"IBLOCK_SECTION_ID" => false, // элемент лежит в корне раздела
"IBLOCK_ID" => 29, // Ид инфоблока
"PREVIEW_TEXT" => $text, // массив со свойствами
"NAME" => $phone, // имя записи
"ACTIVE" => "Y",
);
// сохраняем
$PRODUCT_ID = $elem->Add($arLoadProductArray);


/*** Отправка данных ***/
Event::send(array(
"EVENT_NAME" => "SENDMESSAGE",
"LID" => "s2",
"C_FIELDS" => array(
"AUTHOR" => $_POST['userName'],
"PHONE" => $_POST['userTel'],
"URL" => $pageUrl,
"PRODUCTS" => $productList,
),
"FILE" => [],
));
}
?>

<? // опять проверки ?>
<? // print_r($_POST) ?>
<? // print_r($text) ?>

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

Комментарии

Комментарий отправлены на валидацию!

Теги: