Из-за часто меняющегося компонента оформления заказа приведенное здесь решение не является полным и окончательным, а следить за актуальностью я не могу. Поэтому прошу пост рассматривать лишь для подспорья в написании собственного кода, а не использовать "как есть".
ЗЫ: Вот последняя актуальная (примерно на июнь 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 ошибки), Chrome (1 успешно), FireFox (1 успешно). На своем сайте - FireFox (3 ошибки), Chrome (1 ошибка), правда, сайт работает на localhost.
Krikunov Slava, Долганин Антон, присоединяюсь к вопросу. Вообще замечено, что эта ошибка возникает, если оформить заказ, а потом зайти на confirm, например, с другого браузера. Можно ли как-то эту последнюю страницу confirm разрешить просматривать любым гостям? Ведь мы не авторизуем пользователя, после того, как он оформил этот заказ под гостем. А вдруг ему понадобится совершить оплату уже после того, как кончилась сессия.
Александра, это достаточно опасно. Так можно слить весь оборот магазина (перебрать ID заказов). Хотя сейчас можно делать рандомные номера заказов - это упрощает жизнь. Можно кастомизировать компонент и убрать проверку на владельца заказа. Боюсь с этим не смогу вам помочь тут.
Я так понимаю что при оформлении заказа, пользователя не должно регистрировать!? У меня регистрирует. Взял полностью Ваш компонент и функции обработчиков.
Антон, спасибо за ответ! Сделал все как тут написано, но не до конца работает! В смысле, у меня 2 раза получилось сделать заказ гостем и все на этом! В чем может быть причина?!
Так, я скачал папку "salr.order.ajax". Закинул её в bitrix/components/bitrix/ . В файл bitrix/php_interface/init.php закинул классы необходимых обработчиков из файла sale_handler_guest_order.php
И 2 раза удалось сделать заказ. Ошибок не выдает, просто после нажатия кнопки "Заказать" очищается страница.
Антон день добрый, а после добавление вашего кода, проверка обязательных полей не работает. работает только с email адресом. как и где нужно подправить?! спасибо заранее!
Антон день добрый, а после добавление вашего кода, проверка обязательных полей не работает. работает только с email адресом. как и где нужно подправить?! спасибо заранее!
Влад, к сожалению, не знаю даже почему такой характер ошибки выдает, это надо смотреть вам с разработчиком. Код и все это оформление достаточно сложная штука, я распространяю это как есть. Без поддержки.
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».