Как работает корзина в OpenCart 2.3

Как работает корзина Opencart 2.3 и почему ее не так просто изменить (но у нас все получится). Цель: сделать одностраничное оформление заказа без регистраций и смс.

Ввиду последнего обновления opencart и грядущих, которые переписывают контроллеры – примеры кода беcполезны, главное общий ход размышлений.

Загрузка начинается с контроллера checkout/checkout. В нем происходит подготовка страницы и вывод “болванки” под работу корзины. Далее работает все на js, обработчиках которые по шагам ведут пользователя к победному заказу.
0 Шаг. Его пользователи не видят – он происходит в tpl части контроллера checkout/checkout. Определяется зарегистрирован ли покупатель, если не зарегистрирован вызывается контроллер checkout/login (Чтобы увидеть шаг 1.) – либо контроллер для зарегистрированных пользователей (здесь не рассматривается).
1 Шаг. На этом этапе заказчик делает первый выбор – зарегистрироваться, войти или оформить заказ без регистрации.

Для оформления без регистрации (обязательно разрешить в админке) исследуем форму:

Сначала идет проверка зарегистрирован ли пользователь. Очень похоже на наследие прошлой версии, так как мы еще в шаге 0 проверили это. В браузере смотрим id кнопки, которая поможет оформить без регистрации: button-account. И находим обработчик для таковой кнопки. Обработчик получает значение радио-кнопки, оно важно – так как является названием следующего контроллера.

Получая значение этой кнопки “guest” – переходим к шагу 2. Так же, просмотрев контроллер на предмет изменений каких либо данных в сессии или других местах понимаем, что контроллер только ПОЛУЧАЕТ данные, но не сохраняет их куда либо. Этот факт разрешает нам безболезненно пропустить шаг 1 и сразу перейти к 2.

2 Шаг. Запрос к контроллеру checkout/guest.

Этот контроллер важен, так как устанавливает в сессию (хранилище данных для каждого, кто вошел на сайт) дефолтные значения важных для opencart переменных. Его вызывать будем по любому. Далее, установив стандартные значения и получив нужные для шаблона переменные – он его вызывает.

Открываем tpl файл, написанный в контроллере, видим много-много html с формами, но интересует нас js. В js наблюдаются по порядку: сортировки полей, ajax запросы при изменении некоторых полей, можно прикрепить какой то файл.. И все, обработчика для кнопки отправить нет. Значит файл нам по сути не нужен, отправляемся искать его к контроллеру шага 0.

На данном этапе обработчик кнопки отправки платежной информации собирает данные со всей формы, пакует их в json и отправляет контроллеру checkout/guest/ и функции в нем save.

Для того, чтобы не заниматься долгом разбором формы можно “перехватить” данные.

Разберемся с функцией save контроллера checkout/guest:

  • Проверка не зарегистрирован ли пользователь
  • Проверка есть ли у него чего в корзине
  • Еще разок проверка можно ли гостям заказывать
  • Если до сих пор все хорошо – идет проверка полей
  • Самый интересный пункт – заполнение полей. Здесь то мы и остановим работу стандартного контроллера и напишем ответ – запишем в json все данные, которые получили при заполнении формы.
$json = $this->request->post;

Заполнив правильно все поля – получаем массив, который пригодится нам для заполнения фейковыми данными.

Возвращаем все на место, Смотрим что происходит далее. Далее мы видим снова развилку в логике:

  • Может быть нужна доставка
  • Если нужна – может стоять галочка совпадения адреса, может нет.
  • Если не нужны доставка – пропуск кучи шагов.

Выберем для себя что доставка нужна всегда (добавим “самовывоз” в методы доставки), так же что адрес плательщика совпадает. Почему так? Потому, что 2 адреса – оплаты и доставки – в СНГ не нужны, да и за границей, не так часто люди используют функционал налогов.

Шаг 4. (3 шаг пропущен галочкой совпадения адреса). Запрос к контроллеру checkout/shipping_method. Никаких данных ему не отправляется, все уже записано в сессию (важное замечание).

Этот контроллер так же ничего не меняет, только получает данные формы, НО при успешном его вызове – сразу посылается второй ajax запрос на контроллер checkout/guest_shipping, который заполняет в тихую Шаг 3. Это тоже важный контроллер, который пишет в сессию дефолтные значения.

На этом этапе у нас висит форма добавления комментария и выбор доставки. Так же в сессию уже записаны все данные пользователя, следующие действия выполнятся по нажатию кнопки “Продолжить” на Шаге 4. и мы перейдем к следующему:

Шаг 5. По нажатию кнопки продолжить js отправляет ajax запрос контроллеру checkout/shipping_method, его методу save. В этом месте на всякий случай проверяется минимальное количество продукции в корзине, но мы предварительно выключили контроль в админке, радиокнопка доставки гарантированно установлена и все проверки пройдут успешно. И главное – будет сохранен комментарий и способ доставки.

В случае удачного прохождения этого этапа – идет запрос к checkout/payment_method. Опять таки важный контроллер, который заполняет некоторые дефолтные значения.

Он получает методы оплаты и выводит их в форму (и комментарий).

Нажатие кнопки “продолжить” – делает все по накатанной. Вызываем функцию save, валидируем, пишем что не так, вдруг что – и стучимся к следующему контроллеру.

Шаг 6. checkout/confirm.

Этот контроллер окончательно проверяет нужные шаги, оформляет заказ. Но опять таки в локальное хранилище, вызывая следующий контроллер – оплаты.

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

Подытожим что нам нужно сделать:

  1. Поменять в контроллере checkout/checkout вызов шаблона на, к примеру, checkout2.tpl.
  2. В нем написать кучу ajax вызовов для получения данных (скопировать с существующих скриптов, вырезав функции save)
  3. По кнопке проверить данные – вызвать по очереди все функции save()
  4. Если все хорошо – получить ответ от последнего этапа с табличкой заказа и кнопкой “продолжить”, которая сгенерирована каким либо платежным модулем.

Порядок запросов:

  1. checkout/guest
  2. checkout/guest/save
  3. checkout/shipping_method
  4. checkout/guest_shipping/save
  5. checkout/shipping_method/save
  6. checkout/payment_method
  7. checkout/payment_method/save

Так же придется в checkout/shipping_method/save и checkout/payment_method/save скопировать получение методом достави и оплаты (они в начале контроллера) в начало функции.

Такой порядок Позволит не нарушить логику заказа и все будет работать как надо.

Файлы с osStore 2.3, которые использовались при написании статьи (внимание, заменяют системные!):
1pagecart2.3.zip

Тоже самое, но модулем: web-porosya-page-cart1.0.ocmod (2.3)

UPD: опенкарт как обычно что-то поменял втихую и куча модулей сломалась. На этот раз валидация почты. Если ошибка в корзине на эту тему – пот патч: guest2. (пока только на новейшей сборке опенкарта 2.3.0.2 чистого, русские сборки не поменялись)

Один комментарий к записи “Как работает корзина в OpenCart 2.3”

  1. Спасибо за такой профессиональный разбор вопроса! За то что объяснили саму логику…
    Как же долго я Вас искал… А то все статьи с грубым удалением\комментированием кода и как следствие кучей ошибок.
    И за файлы с примером, отдельное спасибо. )

  2. Здравствуйте спасибо за статью, хотел спросит а что если пересобрать оформление самому, если у меня дропшипер и все работает по api информации о продукте выводится из api, тогда придется сделать модуль корзины самому? opencart ведь используются записи о товаре из бд? если сделать модуль корзины отдельно, тогда как взаимодействовать корзину с пользователям при оформления товара.

    1. Тут больше вопрос к наполнению корзины, а не оформления заказа. Если товаров нет в бд – зачем тогда нужен опенкарт?

      “Обмануть” опенкарт можно тут на этапе добавления товара в корзину. Например добавлять его в “товары”.

      Опенкарт хранит в бд id сессии и id товаров, которые в корзине. id сессии в куках каждого юзера.

      1. Действительно, сейчас например уже начинаю думать зачем мне опенкарт? шаг за шагом работы с api (не из db) подозреваю что использую только mvc опенкарт, что бы не использовать полностью свое, все же могу перехватывать регистрацию полностью данные пользователя?

        1. Через session id можно – на нее все завязано и можно руками все заполнять (написать свои модели и подменить их в контроллерах)

          opencart для этой ситуации не лучший выбор)

  3. Правильно ли я понимаю, что имеет место установить Ваш модуль и проблема, возможно, решится?

      1. Длительного заказа в OpenCart. Я так понял, что Вы создали своё решение – красивый и компактный способ заказа – и выложили это модулем?
        Просто я сейчас ставил через админку и получил след. ошибку: http://i.imgur.com/PT4mG0d.png .
        Не в том ли проблема, что админка доступна у меня не по “/admin”, а по “/secret/admin” ?

  4. Спасибо, это помогло – теперь получается установить.
    Однако после загрузки модуля в корзине ничего не изменилось. Возможно, нужны какие-то дополнительные махинации, о которых я не подумал?
    Вообще, я почему пробую Ваш вариант – у меня вовсе нерабочий дефолтный способ оплаты: http://i.imgur.com/qj8cVlf.png

      1. Защищал папки system/storage, обновлял в менеджере дополнений, чистил браузерный кэш – не помогает. Можете поделиться, пожалуйста, всеми необходимым файлами, связанными с корзиной? Или всё это было в модуле?

        1. Все в модуле, я его неоднократно устанавливал на ocStore 2.3 – просто работает и все, здесь указана детальная инструкция как работает модуль – проверяйте функции и переменные по очереди все, другого пути выяснить нет.

  5. Такая проблема: убираю Имя-Фамилия-default@email.com из полей (ну не нужны они там, и пусть поля будут пустые) и сразу возникает ошибка. Возвращаю обратно, но ошибка остается. Помогает только откат всех файлов. Как очистить поля?

    1. Выходит они там нужны =)

      Если все-таки убирать, то можно на стороне контроллера подставлять фейковые, если пустая строка.
      Еще более длинный и правильный путь – найти где идет прям оформление заказа (так же на стороне контроллера) – и убрать проверку имени-фамилии там.

      1. Проверка имени нужна! Но при нажатии “”проверить”. Как сделать, чтобы проверки не было при вводе?

        1. Самый простой способ в шаблоне вывода подставить туда не placeholder=”Имя”, а value”Имя”, все кто не хочет заполнять имя будут названы как Имя

          1. Вы опять не поняли. По порядку: в файле guest2.tpl заданы placeholder и value – . Так вот, placeholder задан правильно – этот текст исчезает при клике. А value вообще не нужен! – этот текст надо удалять клиенту, и это идиотизм – так никто не делает. Но если я очищаю параметр value, сразу идет ошибка на сайте “Имя должно быть от 1 до 32 символов!”. И мне не нужны данные про клиента “Имя, Фамилия, default@email.com…”! Этот текст он должен заполнить на пустых полях!

  6. Здравствуйте. Как сделать, чтобы в этом модуле защита от роботов(стандартная opencart) не писала “Проверочный код не совпадает с изображением!”, сразу когда мы переходим в оформление заказа и еще не ввели защитный код. Спасибо.

    1. Надо много переписывать, в нем не предусматривалась такая возможность. Нужно посмотреть в какой момент проверка цепляется и отменить ее. А потом когда надо включить обратно.

  7. Если на сайте есть товары со скидкой, то после нажатия на кнопку “Проверить” все скидки на сайте для текущей сессии пропадают.
    И товар в заказ попадает без скидки и все товары после этого отображаются везде в магазине без скидок.
    Помогает только удаление куки.

        1. Тогда все верно, статья про 2,3 – раньше корзина работала чуть не так. Вообще в любых других может не работать, opencart в этом плане очень капризный.

  8. да, блин, проверил
    на чистой ocStore 2.3.0.2.3
    установил модулем

    всё работает чётко

    нужно обновлять и переносить всё(((

  9. А подскажите плиз, в чем может быть проблема, на валюте по умолчанию (USD) модуль работает отлично, если меняю валюту на гривну, то в корзине нажимая на кнопку “ПРОВЕРИТЬ” не срабатывает аякс запрос а просто перезагружает страницу и ничего не происходит

    1. 1. Самая частая – не та версия опенкарта
      2. Нужно посмотреть ошибки сервера, там написано в чем проблема

  10. Здравствуйте! Когда пытаюсь купить подарочный сертификат, страница оформления заказа обновляется при нажатии кнопки “проверить”. Как быть?

    1. Модуль не рассчитан на подарочные сертификаты, это простейшая корзина для разбора как оно работает.

  11. Добрый день. Пытаюсь разобраться с оформлением заказ в Opencart 3.0. Если вы разбирались с этим вопросом может подскажете. При нажатии на первом шаге идёт обращение к серверу. Ели да то к какому контроллеру и какому действию.

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

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