[СДЕЛАЙ САМ] SendIt и MiniShop2 - заказ в 1 клик - быстро, просто и бесплатно.
Приветствую, решил зафиксировать для себя и поделится с сообществом, прежде всего с новичками, актуальным способом быстро и без боли добавить в интернет-магазин на базе MiniShop2 функцию «Заказать в 1 клик.»
Функционирование модальных окон обеспечивает Bootstrap. Уточняю этот момент, потому в JS, который будет представлен далее, используются методы открытия и закрытия модального окна, и если вы используете самописные модальные окна или фреймворки отличные от Bootstrap эти методы нужно будет заменить на аналогичные из ваших библиотек.
Инструкция
1. Скачиваем и устанавливаем из репозитория modstore компоненты SendIt и MiniShop2, если ещё этого не сделали.
2. Везде где нужно иметь возможность быстрого заказа, добавляем кнопку
3. Создаем модальное окно с формой заказа
4. Создаем чанк пресет fast_order
5. Создаём хук, или, другими словами, сниппет, oneClickHook со следующим кодом:
6. Напишем JS, который обработает ответ сервера: закроет модалку, покажет уведомление, сделает переадресацию на оплату, если нужно. Так же этот скрипт заполнит поле с ID товара в нашей форме при открытии модального окна.
Я потратил 30 минут на реализацию этого функционала, вы же теперь успеете не только всё сделать, но и чайку попить)))
ДРУГОЙ ВАРИАНТ РЕАЛИЗАЦИИ МОЖНО ПОСМОТРЕТЬ ТУТ
Функционирование модальных окон обеспечивает Bootstrap. Уточняю этот момент, потому в JS, который будет представлен далее, используются методы открытия и закрытия модального окна, и если вы используете самописные модальные окна или фреймворки отличные от Bootstrap эти методы нужно будет заменить на аналогичные из ваших библиотек.
Инструкция
1. Скачиваем и устанавливаем из репозитория modstore компоненты SendIt и MiniShop2, если ещё этого не сделали.
2. Везде где нужно иметь возможность быстрого заказа, добавляем кнопку
<button class="btn btn-warning" data-product-id="{$id}" type="button" data-bs-toggle="modal" data-bs-target="#oneClickModal"> Купить в один клик </button>У кнопки обязательно должен быть атрибут data-product-id со значение ID добавляемого товара.3. Создаем модальное окно с формой заказа
<div class="modal fade" id="oneClickModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Купить в один клик</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form data-si-form="fastOrderForm" data-si-preset="fast_order">
<input type="hidden" name="delivery" value="1">
<input type="hidden" name="payment" value="1">
<input type="hidden" name="options[]" value="">
<input type="hidden" name="id" value="">
<div class="mb-3">
<label class="form-label">Имя получателя</label>
<input type="text" class="form-control" name="receiver">
</div>
<div class="mb-3">
<label class="form-label">Email</label>
<input type="email" class="form-control" name="email">
</div>
<div class="mb-3">
<label class="form-label">Количество</label>
<input type="number" class="form-control" name="count" value="1" min="1">
</div>
<button type="submit" class="btn btn-primary">Заказать</button>
</form>
</div>
</div>
</div>
</div>Отмечу, что SendIt в данном случае нужен только для валидации полей и отправки формы, при желании можно написать свою реализацию этих функций или использовать другое решение.4. Создаем чанк пресет fast_order
'fast_order' => [
'hooks' => 'oneClickHook',
'validate' => 'receiver:required,email:email:required,id:required',
'successMessage' => 'Заказ оформлен!',
'fieldNames' => 'receiver==Получатель,email==Почта,id==ID товара',
'validationErrorMessage' => 'Исправьте ошибки!'
]В форме обязательно должны быть поля с именами delivery, payment и id. Поскольку мы делаем форму быстрого заказа выбор способов оплаты и доставки я не предоставляю, однако, если такая необходимость есть в вашем проекте, вы можете предоставить пользователю выбор. При этом имейте в виду, если для различных способов доставки доступны различные способы оплаты, логику их взаимодействия писать придётся самостоятельно, так как скрипты MiniShop2, отвечающие за это, тут не подключаются.5. Создаём хук, или, другими словами, сниппет, oneClickHook со следующим кодом:
<?php
$values = $hook->getValues();
$ms2 = $modx->getService('minishop2');
$ms2->initialize('web');
$ms2->cart->clean();
$count = (float)$values['count'] ?: 1;
$ms2->cart->add((int)$values['id'], $count, $values['options']); // добавляем товар в корзину
$ms2->order->config['json_response'] = true; // просим вернуть нам json
// добавляем поля в заказ
$ms2->order->add('receiver', $values['receiver']);
$ms2->order->add('email', $values['email']);
$ms2->order->add('delivery', $values['delivery']);
$ms2->order->add('payment', $values['payment']);
$ms2->order->submit(); // отправляем заказОбратите внимание ни какой код после отправки заказа выполнен не будет, т.к. мы попросили MiniShop2 вернуть нам json, он сделает всё, что должен, и принудительно завершит работу. При этом все встроенные механизмы этого модуля отработают, а именно: будут отправлены письма клиенту и менеджеру, если вы не отключили эту функцию, будет сформирована ссылка на оплату.6. Напишем JS, который обработает ответ сервера: закроет модалку, покажет уведомление, сделает переадресацию на оплату, если нужно. Так же этот скрипт заполнит поле с ID товара в нашей форме при открытии модального окна.
document.addEventListener('DOMContentLoaded', () => {
const oneClickModal = document.getElementById('oneClickModal')
oneClickModal .addEventListener('show.bs.modal', function (e) {
oneClickModal .querySelector('[name="id"]').value = e.relatedTarget.dataset.productId;
});
document.addEventListener('si:send:success', (e) => {
const {action, target, result, headers, Sending} = e.detail;
const modal = bootstrap.Modal.getInstance(oneClickModal );
modal.hide();
if(result.data.redirect){
setTimeout(() =>{
window.location.href = result.data.redirect
}, 3000);
}
});
});7. Укажем в системной настройке ms2_email_manager куда отправлять уведомления о новом заказе и всё готово.Я потратил 30 минут на реализацию этого функционала, вы же теперь успеете не только всё сделать, но и чайку попить)))
ДРУГОЙ ВАРИАНТ РЕАЛИЗАЦИИ МОЖНО ПОСМОТРЕТЬ ТУТ
Комментарии: 66
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
Но в модальном окне выдает следующее:
И не совсем понял, chunks/forms/oneclickorder.tpl нужно в корне сайта создавать?
{$id}
{$_modx->resource.id}
[[+id]]
[[*id]]
Для карточки товара помогло — [[*id]]
Для списка с товарами — {$id}
Как вывести название товара в модальном окне в карточке (странице) товара — понятно, просто указать [[*pagetitle]] и все.
Подскажите, а как можно вывести название товара в модальное окно в списке (категории) товаров (pagetitle выводит название ресурса категории)?
Кнопке добавить data-pagetitle
В js
Это ссылка
Это js
Это input
Если на этой странице поместить вывод формы в модальное окно
то происходит ошибка
и главная страница неотображается
Если убрать optionFilters, все работает.
Можете подсказать куда копать?
Кстати, модалка в примере под Bootstrap 5. Меняйте классы под себя.
Подключил 5 бутстрап.
Uncaught TypeError: bootstrap.Modal.getInstance is not a function
Uncaught TypeError: can't access property «hide», modal is null
А вот уведомления должны показываться, если нет ошибок в JS.
Подключил js bootstrap 5, вставил все как в примере.
По итогу заказ с модалки улетает, но модалка не закрывается и нет уведомлений. Но это баг вероятнее всего из-за уже подключенных скриптов bs4. Если Артур поможет адаптировать скрипт под bs4, то можно было бы выложить пример для bootstrap 4. Сам не силен в скриптах.
а после оформления заказа, вернуть назад прежнее содержимое корзини
Ответ гарантированно должен быть и проверенно работает
Но пока на данный момент решение может быть только следующим (примерно):
1. Временно сохраняем текущую корзину в сессию через $ms2->cart->get();
2. Очищаем корзину
3. Добавляем в нее новый товар
4. Создаем заказ.
5. Если не пустая сессия с сохраненной корзиной закидываем ее опять в корзину через $ms2->cart->set($_SESSION['tmp_cart'])
очень удобно создаешь сколько угодно тебе корзин, называешь их как тебе надо, типа — присмотрел к др, подраки на нг, ит.д
Лежат себе и кушать не просят, актуализируются автоматически.
Если сделать грамотно, очень удобно будет. Корзины хранятся в бд, доступны менеджерам из админки, в любой момент могут их посмотреть, помочь клиенту дособрать, или оформить любую из корзин.
Если у вас страница спасибо, то я бы на ней вызвал сниппет восстановления корзины.
Если у вас редирект на платежку — то тут сложнее. Корзину лучше бы писать куда-то в профиль пользователя и после его возвращения восстанавливать ее. На сессии лучше не надеяться.
Через профиль пользователя не выйдет, т.к. заказы оформляются от анонимов. Пробовал через кэш, но пока не выходит. Видимо надо кэшировать куда-то в файл и потом забирать от туда же.
Есть надежда, что когда-нибудь @Николай Савин уберёт die() из обработчика заказа)))
Крутой способ заказа в 1 клик. Возник только вопрос такой:
У товара есть модификации, используется дополнение msOptionsPrice2, которые влияют на стоимость товара.
Как передать значение модификации в попап? Заказ создается но с ценой по умолчанию для товара, а не с выбранной модификацией.
Может подскажет кто-нибудь, куда копать.
После успешной отправки формы не выводится указанный в чанке нужный мне 'successMessage', а выводится (не могу найти откуда) сообщение с текстом «Заказ успешно создан»
Где нужно проверить/исправить?
Актуализируйте плиз, всё по статье рабочее?
если пресет не прописывать в sendit.inc.php то письмо о заказе прилетает на почту (и в письме кстати нет ID товара), но в заказах minishop не показывается
если прописать пресет, то ругается что ID не заполнен…
если вручную даже прописать или вообще из пресета убрать обязательность поля ID то после нажатия на кнопку просто ничего не происходит…
в чем может быть причина? всё как в статье, за исключением иправления косяка в JS — oncLickModal.
Значит до сервера ID не доходит. Смотри ошибки в консоли
Failed to load resource: the server responded with a status of 500 ()
const response = await fetch(url, this.fetchOptions);
куда копать? права на папку sendit пересмотреть?
надо было понизить версию PHP -_//