Альтернативная концовка. Оформляем заказ miniShop2 через API. Часть 5.

27.06.2018
13121

Алоха, спортсмены! Сегодня мы с вами сделаем программное оформление заказа miniShop2, минуя его сниппеты. Плюс данного способа в том, что мы с вами польностью можем задать свою логику оформления заказа, что будет некой индивидуальной фишкой нашего лендинга.

Для начала я создал новый шаблон “Товар” и “Категория товаров” оставил их пустыми. Сделал я это на тот случай, если в дальнейшем сайт масштабируется из лендинга в многостраничник. Так же необходимо в системных настройках, в разделе miniShop2 указать данные шаблоны по умолчанию для новых категорий и товаров (это настройки ms2_template_category_default и ms2_template_product_default).

Когда мы это сделали, можем создавать в корне нашего сайта категорию товаров и в ней наши 6 карточек товара. У вас должно получиться примерно, как у меня:

  API miniShop2

Теперь я вам должен пояснить логику, по которой у нас все будет работать. У нас будут выведены товары с кнопкой “Купить”, по нажатию на которую будет открываться модальное окно заказа товара со следующими полями:

  • Имя пользователя
  • E-mail
  • Телефон
  • Комментарий к заказу

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

Теперь давайте выведем наши товары на главной странице. Для этого нам необходимо создать чанк “productTpl” со следующим содержимым:

<div class="col-md-4 col-sm-6">
    <div class="product-single text-center">
        {if $image?}
            <img src="{$image}" alt="{$pagetitle}" title="{$pagetitle}" class="img-responsive"/>
        {else}
            <img src="{'assets_url' | option}components/minishop2/img/web/ms2_small.png"
                 srcset="{'assets_url' | option}components/minishop2/img/web/ms2_small@2x.png 2x"
                 alt="{$pagetitle}" title="{$pagetitle}"/>
        {/if}
        <h4>{$pagetitle}</h4>
        <h3>{$price} <span>руб.</span></h3>
        <a href="#offer{$id}" data-toggle="modal" data-target="#offer{$id}"><i class="icofont icofont-cart"></i> Buy Now</a>
    </div>
</div>

В данном чанке у нас используется шаблонизатор Fenom, поэтому не пугайтесь незнакомых тегов.

И в месте вывода товаров нам необходимо вызвать сниппет msProducts со следующими параметрами:

[[msProducts?
	&parents=`5`
	&tpl=`productTpl`
]]

Отлично! Мы с вами вывели наши товары. Теперь нам нужно создать еще один чанк “productModalTpl”, в котором мы будем выводить модальное окно. Каждому товару у нас будет соответствовать свое модальное окно.

<div class="modal fade" id="offer{$id}" tabindex="-1" role="dialog" aria-labelledby="offer{$id}">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
	  <form action="[[~12]]" method="POST" class="ajax_form_offer" id="offermodalform{$id}">
          <input type="hidden" name="pagetitle" value="[[*pagetitle:htmlent]]">
          <input type="hidden" name="id" value="{$id}">
          <input type="hidden" name="href" value="[[~[[*id]]? &scheme=`full`]]">
          <div class="modal-header">
        	<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
        	<h4 class="modal-title" id="myModalLabel">Buy Now {$pagetitle}</h4>
          </div>
          <div class="modal-body">
        	<div class="message"></div>
            <div class="form-group hidden">
            	<label>Имя</label>
            	<input class="form-control" name="user" placeholder="" type="text">
              </div>
              <div class="form-group hidden">
            	<label>Имя</label>
            	<input class="form-control" name="username" placeholder="" type="text">
              </div>
            <div class="form-group">
                <input type="text" name="name" class="form-control" placeholder="Name">
            </div>
            <div class="form-group">
                <input type="email" name="email" class="form-control" placeholder="Email">
            </div>
            <div class="form-group">
                <input type="text" name="phone" class="form-control" placeholder="+7 (999) 123-45-67">
            </div>
            <div class="form-group">
                <textarea class="form-control" name="text" cols="30" rows="10"></textarea>
            </div>
          </div>
          <div class="modal-footer">
        	<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
        	<button type="submit" class="btn btn-primary">Submit</button>
          </div>
        </form>
    </div>
  </div>
</div>

Класс! Теперь по клику на кнопку “Buy Now” у нас будет открываться соответствующее модальное окно. В атрибуте тега form action у меня прописан идентификатор ресурса, в котором вызван сниппет-обработчик заказа.

  API miniShop2

Также нам нужно вызвать сниппет msProducts после чанка Modals в шаблоне:

[[msProducts?
    &parents=`5`
    &tpl=`productModalTpl`
]]

Следующим шагом будет создание ресурса, в котором мы будем обрабатывать заказ. Я скопировал наш ресурс с обработкой подписки и назвал его “Оформление заказа”, а внутри вызвал пока не существующий сниппет “setoffer”:

  API miniShop2

Класс! Теперь создаем сниппет “setoffer” и можно пока написать валидацию данных:

<?php
$output = array();
$output['success'] = true;
// проверяем, что идет ajax запрос
if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
    // проверяем антиспам поля и ID ресурса
    if($_REQUEST["user"]=='' && $_REQUEST["username"]=='' && $_REQUEST['id']){
        // проверяем поле name
        if($_REQUEST['name']==''){
            $output['success'] = false;
            $output['message'] = "Заполните все обязательные поля";
            $output['fields'][] = "name";
        }
        // проверяем поле email
        if($_REQUEST['email']==''){
            $output['success'] = false;
            $output['message'] = "Заполните все обязательные поля";
            $output['fields'][] = "email";
        }
        // проверяем поле phone
        if($_REQUEST['phone']==''){
            $output['success'] = false;
            $output['message'] = "Заполните все обязательные поля";
            $output['fields'][] = "phone";
        }
        // если проверка прошла успешно - оформляем заказ
        if($output['success']){
            $output['success'] = true;
            $output['message'] = "Ваш заказ оформлен";
        }
    }else{
        $output['success'] = false;
        $output['message'] = "Данные не прошли проверку валидности или у вас не указан ID товара";
    }
}else{
    $output['success'] = false;
    $output['message'] = "Данные не прошли проверку валидности, попробуйте позже";
}

echo json_encode($output);

И в чанке scripts напишем отправку наших данных на сервер с помощью jQuery. Получится он должен аналогично скрипту для подписки пользователя:

$('.ajax_form_offer').submit(function(e){
    e.preventDefault();
    var msg = $(this).serialize();
    var url = $(this).attr("action");
    $.ajax({
        type: "POST",
        url: url,
        data: msg,
        dataType: "json",
        success: function(data){
            if(data.success){
                miniShop2.Message.success(data.message);
            }else{
                miniShop2.Message.error(data.message);
            }
        }
    })
});

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

<?php
$output = array();
$output['success'] = true;
// проверяем, что идет ajax запрос
if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
    // проверяем антиспам поля и ID ресурса
    if($_REQUEST["user"]=='' && $_REQUEST["username"]=='' && $_REQUEST['id']){
        // проверяем поле name
        if($_REQUEST['name']==''){
            $output['success'] = false;
            $output['message'] = "Заполните все обязательные поля";
            $output['fields'][] = "name";
        }
        // проверяем поле email
        if($_REQUEST['email']==''){
            $output['success'] = false;
            $output['message'] = "Заполните все обязательные поля";
            $output['fields'][] = "email";
        }
        // проверяем поле phone
        if($_REQUEST['phone']==''){
            $output['success'] = false;
            $output['message'] = "Заполните все обязательные поля";
            $output['fields'][] = "phone";
        }
        // если проверка прошла успешно - оформляем заказ
        if($output['success']){
            // инициализируем miniShop2
            $scriptProperties = array(
        	  'json_response' => true,
        	  'max_count' => 1000,
        	  'allow_deleted' => false,
        	  'allow_unpublished' => false
        	);
        	
        	$miniShop2 = $modx->getService('minishop2','miniShop2', MODX_CORE_PATH . 'components/minishop2/model/minishop2/', $scriptProperties);
        	
        	// опции товара, если они необходимы
        	$option = array();
        	/*$option = array(
        	  "option1" => "value1",
        	  "option2" => "value2",
        	);*/
        	// инициализируем miniShop2 в текущем контексте
        	$miniShop2->initialize($modx->context->key, $scriptProperties);
        	// чистим корзину
        	$miniShop2->cart->clean();
        	// добавляем товар в корзину
        	$arr = json_decode($miniShop2->cart->add($_REQUEST["id"],1,$option), true);
        	
        	// логируем каждый шаг
        	$modx->log(E_ERROR, print_r($arr,1));
        	
        	// формируем заказ
        	$miniShop2->order->add('receiver', $_REQUEST['name']);
        	$miniShop2->order->add('email', $_REQUEST["email"]);
        	$miniShop2->order->add('phone', $_REQUEST["phone"]);
        	$miniShop2->order->add('comment', $_REQUEST["text"]);
        	$miniShop2->order->add('payment', 1);
        	$miniShop2->order->add( 'delivery', 1);
	        $orderfeed = $miniShop2->order->submit();
        	
        	$arr = json_decode($orderfeed,true);
        	
        	// логируем каждый шаг
        	$modx->log(E_ERROR, print_r($arr,1));
        	
	        if($arr['success']==true&&$arr["data"]["msorder"]){
	            $output["location"] = $modx->makeUrl(13,'',array('msorder' => $arr["data"]["msorder"]));
	        }
        	
            $output['success'] = true;
            $output['message'] = "Ваш заказ оформлен";
        }
    }else{
        $output['success'] = false;
        $output['message'] = "Данные не прошли проверку валидности или у вас не указан ID товара";
    }
}else{
    $output['success'] = false;
    $output['message'] = "Данные не прошли проверку валидности, попробуйте позже";
}

echo json_encode($output);

И мы немного модернизировали скрипт отправки данных на сервер:

$('.ajax_form_offer').submit(function(e){
    e.preventDefault();
    var $btn = $('.ajax_form_offer button[type=submit]').button('loading');
    var msg = $(this).serialize();
    var url = $(this).attr("action");
    $.ajax({
        type: "POST",
        url: url,
        data: msg,
        dataType: "json",
        success: function(data){
            if(data.success){
                miniShop2.Message.success(data.message);
                if(data.data.msorder){
    				window.location.href = "[[~13]]?msorder="+data.data.msorder;
    			}
            }else{
                miniShop2.Message.error(data.message);
            }
        }
    })
});

Таким вот незатейливым образом мы с вами реализовали свою логику при оформлении заказа miniShop2. Спасибо, за внимание!

Альтернативная концовка. Оформляем заказ miniShop2 через API. Часть 5.

0 Число голосов: 9
4
5
1
9

Комментарии ()

  1. Николай 21 октября 2019, 22:37 # 0
    Добрый вечер, сделал как у вас все расписано, но к сожалению не срабатывает открытие модельного окна. Может ли быть причинной то, что у меня bootstrap 4, а не 3 как у вас в уроке?
    1. Вячеслав 22 июня 2022, 12:02(Комментарий был изменён) # 0
      Не добавляет заказ и даже не начинается валидация данных. Все подключено скрипт ниже джиквери, что может быть не так? И если у меня оплата через Юмани и мне нужно чтобы после нажатия Submit клиент переходит к оплате как это сделать? Bootstrap 5 у меня, но Джиквери подключена для Мсерч2.

      Наши клиенты

      Многие компании уже доверяют нам. Будьте в их числе!

      Хотите реализовать проект?

      Контакты

      Напишите нам - мы расскажем вам много интересного!


      Пермь, ул. Крупской 34, офис 510