Из-за часто меняющегося компонента оформления заказа приведенное здесь решение не является полным и окончательным, а следить за актуальностью я не могу. Поэтому прошу пост рассматривать лишь для подспорья в написании собственного кода, а не использовать "как есть".
ЗЫ: Вот последняя актуальная (примерно на июнь 2014) версия компонента, которую я запилил под одного клиента: скачать. Пользуйтесь как есть, пожалуйста. Измененные блоки (менялся только component.php) я выделил фразой customization (конкретно для клиента менял еще некоторые строчки). Кодировка cp1251.
Оформление заказа почти идеально, но есть минус - если гость вводит e-mail, который есть в базе, ему дадут от ворот поворот - мол такой пользователь уже есть. А если подойти с точки зрения покупателя, это ломает - вспоминать пароль, или еще что. В общем, лояльность падает. Исправим ситуацию (сразу хочу огорчить - решение подразумевает +2 байта в системном компоненте, так что если вам не пойдет - пост бесполезен (хотя, вы можете просто вынести компонент в свое пространство, код все равно будет рабочим). [spoiler] Речь пойдет про компонент sale.order.ajax, одношаговое оформление заказа. Почему нельзя вынести компонент в свое пространство и изменить? Потому что это центровой компонент магазина, который постоянно улучшается компанией Битрикс, и лично я против его изменения. Так как же подошел к проблеме я.
Все методы ниже - методы класса CSaleHandlers, внутри которого содержатся необходимые обработчики событий.
Также класс имеет переменную
private static $bGuestOrder = false;
Поехали
1. Событие OnSaleComponentOrderOneStepProcess
//AddEventHandler('sale', 'OnSaleComponentOrderOneStepProcess', Array('CSaleHandlers', 'OnSaleComponentOrderOneStepProcessHandler'));
public static function OnSaleComponentOrderOneStepProcessHandler($arResult, $arUserResult, $arParams) {
if (empty($arResult['ERROR']) && $arUserResult['CONFIRM_ORDER']=='Y' && !$GLOBALS['USER']->IsAuthorized()) {
if ($arUser = CUser::GetList($by='id', $order='asc', array('=EMAIL' => $arUserResult['USER_EMAIL']))->Fetch()) {
if (!in_array(1, CUser::GetUserGroup($arUser['ID']))) {
$GLOBALS['USER']->Authorize($arUser['ID']);
self::$bGuestOrder = true;
}
}
}
}
Перед самым созданием заказа, перехватываем исполнение и смотрим - если пользователь с введенным e-mail, есть, то авторизуем его. От греха подальше, НЕ авторизуем если пользователь из группы админов. Это достаточно важный момент, потому что ошибка может произойти на любой строчке кода, и тогда гость может остаться админом.
В переменной self::$bGuestOrder запоминаем, что заказ создает гость.
2. Событие OnOrderUpdate
//AddEventHandler('sale', 'OnOrderUpdate', Array('CSaleHandlers', 'OnOrderUpdateHandler'));
public static function OnOrderUpdateHandler($ID, $arFields) {
if (self::$bGuestOrder && $GLOBALS['USER']->IsAuthorized() && isset($arFields['PRICE'])) {
$_SESSION['SAVED_UID'] = $GLOBALS['USER']->GetID();
$GLOBALS['USER']->Logout();
}
}
Разавторизовываем пользователя после создания заказа (в понятиях кода, а не сайта). Почему нельзя использовать OnOrderAdd? Потому что после добавления идет еще привязка корзины пользователя, и мы потеряем ее в случае OnOrderAdd. Также в сессии запоминаем предыдущий ID пользователя, который нам пригодится
3. Событие OnSaleComponentOrderOneStepComplete
//AddEventHandler('sale', 'OnSaleComponentOrderOneStepComplete', Array('CSaleHandlers', 'OnSaleComponentOrderOneStepCompleteHandler'));
public static function OnSaleComponentOrderOneStepCompleteHandler($ID, $arOrder, $arParams) {
if ($ID <= 0) {
if (self::$bGuestOrder) {
$GLOBALS['USER']->Logout();
}
}
}
Здесь мы страхуемся и делаем логаут пользователю, если случилась ошибка при создании заказа.
4. Событие OnSaleComponentOrderOneStepFinal
//AddEventHandler('sale', 'OnSaleComponentOrderOneStepFinal', Array('CSaleHandlers', 'OnSaleComponentOrderOneStepFinalHandler'));
public static function OnSaleComponentOrderOneStepFinalHandler($ID, $arOrder, $arParams) {
if ((!$GLOBALS['USER']->IsAuthorized() && $_SESSION['SAVED_UID']!=$arOrder['USER_ID']) ||
($GLOBALS['USER']->IsAuthorized() && $GLOBALS['USER']->GetID()!=$arOrder['USER_ID'])
) {
$arOrder = array();
}
}
Здесь мы запрещаем просмотр заказа на финальном шаге (оплата), если это гость и не создал его только что сам.
По идее все. Где же надо поправить системный компонент sale.order.ajax/component.php?
Для версии Магазина до 12.5.4. примерно на 2079 строчке (но строчки постоянно скачут при изменениях, так что ориентироваться лучше на окружающий код) идет выборка созданного заказа с проверкой пользователя - вот пользователя надо закомментировать:
После версии 12.5.4 модуля Магазин, код иной:
Обратите внимание. Данное изменение компонента может работать только вкупе с данными обработчиками. Иначе доступ к финальному шагу (системе оплаты) получает любой пользователь.
Изменения компонента не было бы, если бы реализованная идея, просьба поддержать.
Класс необходимых обработчиков вы можете скачать ниже. Достаточно просто подключить его в init.php
Антон, спасибо за ответ! Сделал все как тут написано, но не до конца работает! В смысле, у меня 2 раза получилось сделать заказ гостем и все на этом! В чем может быть причина?!
Так, я скачал папку "salr.order.ajax". Закинул её в bitrix/components/bitrix/ . В файл bitrix/php_interface/init.php закинул классы необходимых обработчиков из файла sale_handler_guest_order.php
И 2 раза удалось сделать заказ. Ошибок не выдает, просто после нажатия кнопки "Заказать" очищается страница.
Антон день добрый, а после добавление вашего кода, проверка обязательных полей не работает. работает только с email адресом. как и где нужно подправить?! спасибо заранее!
Антон день добрый, а после добавление вашего кода, проверка обязательных полей не работает. работает только с email адресом. как и где нужно подправить?! спасибо заранее!
Влад, к сожалению, не знаю даже почему такой характер ошибки выдает, это надо смотреть вам с разработчиком. Код и все это оформление достаточно сложная штука, я распространяю это как есть. Без поддержки.
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».