/ Плагины / Оформление заказа

Оформление заказа

HIT

25.12.2016

4427

1

Страница оформления плагина woocommerce имеет определенную структуру и функционал. Но данная структура не совсем удобна. Доработаем страницу оформления, разбив на логические блоки: Заказ, Доставка, Форма оплаты, Информация о заказчике и т.д.

Оформление заказа (базовая структура)

Шаблон form-checkout.php
form name=»checkout»

woocommerce_checkout_billing (информация о заказчике)
woocommerce_checkout_shipping (информация о доставке)

h3 Заказ /h3
div id=»order_review» Order-review /div

/form

Шаблон review-order.php (Order-review)
table
позиции товара к покупке
итого
shipping (cart-shipping.php, ajax зависимость от введенной в woocommerce_checkout_billing информации, подробнее про доставку)
/table

div id=»payment» Форма оплаты /div (подключена хуком)

Кнопка Оформить заказ

Подготовил более наглядную схему за какую область оформления отвечает какой шаблон Woocommerce

Блок «Выбор способа доставки»

Шаблон который отвечает за вывод блока с выбором вариантов доставки находиться (почему-то) здесь: cart/cart-shipping.php.

Надпись Доставка, которая изначально там присутствует выводиться этой строкой:

echo wp_kses_post( $package_name );

Добавить заголовок «Выберите способ доставки» и общий вес заказа непосредственно в блок с доставкой, можно хуком

function action_woocommerce_review_order_before_shipping(  ) { 

echo '<h3>Выбор способа доставки</h3>';
	
global $woocommerce;
echo '<small class="total-weight">Общий вес: '; 

$total_weight = $woocommerce->cart->cart_contents_weight;
$total_weight .= ' '.get_option('woocommerce_weight_unit');
echo $total_weight;

echo '</small>';

}; 
         
add_action( 'woocommerce_review_order_before_shipping', 'action_woocommerce_review_order_before_shipping', 10, 0 );

Дорабатываем элементы

Если мы не используем функционал расчета доставки и применения купонов — можно отключить ajax обновление. Если отключать ajax не нужно — ниже есть способ без отключения.

// Отключить Ajax на странице оформления
jQuery(document.body).on('update_checkout', function(e){
    //e.preventDefault();
    //e.stopPropagation();
    e.stopImmediatePropagation();
    //console.log(e);
});

Переместить блок Формы оплаты

remove_action( 'woocommerce_checkout_order_review', 'woocommerce_checkout_payment', 20 );
add_action( 'woocommerce_after_order_notes', 'woocommerce_checkout_payment', 20 );
либо подключить к собственному хуку

Отключение расчета доставки

Если доставка довольно сложна и невозможно прописать ее в автоматическом режиме (например: если мы не сможем реально подсчитать какая нужна газель), то мы отключаем расчет доставки: просто оставляем в методах доставки Самовывоз и Доставка (с 0 ценой). При этом из формы информации о заказчике удаляем поля относящиеся доставки и наоборот из формы доставки удаляем поля касающиеся заказчика. И создаем скрипт при нажатии на пункт Доставка раскрывающий форму доставки.

#shipping_method_0_flat_rate-6 — id поля с пунктом Доставка

$(document).ready(function() {

	if($("<strong>#shipping_method_0_flat_rate-6</strong>").is(':checked')) { $('.shipping_address').show(); }

	$('.shipping_method').click(function(){

		if($("<strong>#shipping_method_0_flat_rate-6</strong>").is(':checked')) {
			$('.shipping_address').show();
			$('.shipping_address').html('<h3>Информация о доставке</h3><p class="form-row form-row form-row-wide address-field validate-required" id="shipping_address_1_field"><label for="shipping_address_1" class="">Адрес доставки <abbr class="required" title="обязательно">*</abbr></label><input type="text" class="input-text " name="shipping_address_1" id="shipping_address_1" placeholder="Адрес доставки (улица, дом, подъезд)*" autocomplete="address-line1" value=""></p><p class="form-row form-row form-row-wide address-field validate-required " id="shipping_city_field"><label for="shipping_city" class="">Населенный пункт <abbr class="required" title="обязательно">*</abbr></label><input type="text" class="input-text " name="shipping_city" id="shipping_city" placeholder="Населенный пункт*" autocomplete="address-level2" value=""></p><p class="form-row form-row form-row-first address-field validate-required validate-state" id="shipping_state_field"><label for="shipping_state" class="">Область/регион <abbr class="required" title="обязательно">*</abbr></label><input type="text" class="input-text " value="" placeholder="Область/Регион/Район" autocomplete="address-level1" name="shipping_state" id="shipping_state"></p>');
		} else {
			$('.shipping_address').html('<p class="form-row form-row form-row-wide address-field validate-required woocommerce-validated" id="shipping_address_1_field"><label for="shipping_address_1" class=""><abbr class="required" title="обязательно">*</abbr></label><input type="text" class="input-text " name="shipping_address_1" id="shipping_address_1" placeholder="Адрес доставки (улица, дом, подъезд)*" autocomplete="address-line1" value=" "></p><p class="form-row form-row form-row-wide address-field validate-required woocommerce-validated" id="shipping_city_field"><label for="shipping_city" class="">Населенный пункт <abbr class="required" title="обязательно">*</abbr></label><input type="text" class="input-text " name="shipping_city" id="shipping_city" placeholder="Населенный пункт*" autocomplete="address-level2" value=" "></p><p class="form-row form-row form-row-first address-field validate-required validate-state" id="shipping_state_field"><label for="shipping_state" class="">Область/регион <abbr class="required" title="обязательно">*</abbr></label><input type="text" class="input-text " value=" " placeholder="Область/Регион/Район" autocomplete="address-level1" name="shipping_state" id="shipping_state"></p>');
			$('.shipping_address').hide();
		}

	});

});

Данный вариант реализации не является полноценным решением, т.к. имеет ряд недостатков, и в своей основе имеет довольно примитивный подход

Взаимосвязь варианта доставки и полей

Метод для 2-х вариантов доставки (для 3-х и более не подойдет)

Если у нас есть варианты доставки и самовывоз, то было бы неплохо синхронизировать вариант доставки и предлагаемые для заполнения поля. При самовывозе необходимо чтобы поля доставки скрывались, а при выборе варианта доставки появлялись.

Проблема woocommerce проявляется в том, что форма Детали доставки раскрывается при нажатии заголовка Доставка по другому адресу? (#ship-to-different-address) и вместе с сокрытием поля отключается верификация полей доставки. При двух вариантах доставки (Самовывоз и Доставка) при их переключении можно поставить с помощью jquery событие (click) на id ship-to-different-address. При этом необходимо сделать, чтоб одно из полей изначально было активным, в зависимости от необходимости.

$('#shipping_method_0_flat_rate-2').attr('checked',true);

$('input:radio[name="shipping_method[0]"]').on('change', function () {
    $("#ship-to-different-address-checkbox").click();
});

Для того чтобы поля доставки были изначально открытыми необходимо установить настройку доставки в опциях woocommerce
Назначение доставки > По умолчанию для адреса доставки клиента

В поле город можно по-умолчанию сделать автоподставление
$(«#shipping_city»).val(«Ростов-на-Дону»);

Метод для 3-х и более вариантов доставки

Изначально делаем доставку (один из вариантов) и поля доставки активными. Далее jquery-магия

$('input:radio[name="shipping_method[0]"]').on('change', function () {

	if($("#shipping_method_0_local_pickup-2").is(":checked")) {

		if($("#ship-to-different-address-checkbox").is(":checked")) {		
			$("#ship-to-different-address-checkbox").click();
		}	
		else {
			
		}

	}

	else {

		if($("#ship-to-different-address-checkbox").is(":checked")) {		
			
		}	
		else {
			$("#ship-to-different-address-checkbox").click();
		}

	}

});

В этом случае мы проверяем активно ли поле Самовывоз (#shipping_method_0_local_pickup-2) и в зависимости от этого проверяем скрытый (я его скрываю) checkbox (Доставка по другому адресу? #ship-to-different-address).

Без отключения ajax

Ajax на странице оформления заказа так или иначе нужен (для тех же купонов). Поэтому немного изменим (изменения коснулись первой строки, т.к. элементы DOM были еще не созданы) универсальный скрипт отключения доставочных полей. #shipping_method_0_local_pickup-3 — id поля с самовывозом.

$('body').on('change', 'input:radio[name="shipping_method[0]"]', function(e) {

	if($("#shipping_method_0_local_pickup-3").is(":checked")) {

		if($("#ship-to-different-address-checkbox").is(":checked")) {		
			$("#ship-to-different-address-checkbox").click();
		}	
		else {
			
		}

	}

	else {

		if($("#ship-to-different-address-checkbox").is(":checked")) {		
			
		}	
		else {
			$("#ship-to-different-address-checkbox").click();
		}

	}

});

Два пункта самовывоза

jQuery('body').on('change', 'input:radio[name="shipping_method[0]"]', function() {

	if(jQuery('#shipping_method_0_local_pickup-1').is(':checked')) {

		if(jQuery('#ship-to-different-address-checkbox').is(':checked')) {		
			jQuery('#ship-to-different-address-checkbox').click();			
		}

	} else if(jQuery('#shipping_method_0_local_pickup-2').is(':checked')) {

		if(jQuery('#ship-to-different-address-checkbox').is(':checked')) {			
			jQuery('#ship-to-different-address-checkbox').click();			
		}

	} else {

		if(jQuery('#ship-to-different-address-checkbox').is(':checked')) {	
			
		} else {
			jQuery('#ship-to-different-address-checkbox').click();			
		}

	}

});

И на всякий случаем включаем изначальный выбор на какую-либо доставку

$('#shipping_method_0_flat_rate-4').attr('checked',true);

Напоминание: в настройках доставки Назначение доставки должно быть выбрано — По умолчанию для адреса доставки клиента

Отключение платежного адреса при Самовывозе

Данный способ сделан примитивно, на чистом jQuery, но прекрасно подойдет для простого отключения обязательного поля адрес (в блоке данные плательщика) при выборе варианта доставки Самовывоз.

jQuery('body').on('change', 'input:radio[name="shipping_method[0]"]', function() {

	var address = $('#billing_address_1_field input').val();
	setTimeout(function(){

		if( jQuery('#shipping_method_0_local_pickup-10').is(':checked') ) {
			$('#billing_address_1_field').hide();
			$('#billing_city_field').hide();
			if(address === ''){ 
				$('#billing_address_1_field input').val('_');
			};				
		} else {
			$('#billing_address_1_field').show();
			$('#billing_city_field').show();
			if(address === '_'){ 
				$('#billing_address_1_field input').val('');
			};				
		}

	}, 800);	

});

Изначально (при загрузке страницы) должен быть выбран любой другой вариант доставки, кроме Самовывоза.

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

Варианты оформления для физ. лица и юр. лица

Задача сделать 2 варианта оформления заказа для физ. лица и для юр. лица. Создание этого функционала описано в статье Юр. или физ. лицо при оформлении

Верификация телефона (ajax)

Если телефон введен не корректно, то при нажатии кнопки Оформить заказ выведется уведомление об этом. Но при этом если в поле ввести символы вместо цифр, то полю ajax добавится значение woocommerce-validated, т.е. как бы прошедшее валидацию.

Чтобы это исправить нужно в файл woocommerce/assets/js/frontend/checkout.js (причем на сайт загружается checkout.min.js) добавить внутри функции validate_field: function( e ) (примерно 200 строка) следующую проверку:

if ( $parent.is( '.validate-phone' ) ) {
	if ( $this.val() ) {

		var pattern = new RegExp(/^([0-9\s\/\+\-\#\_\(\)]*)$/);

		if ( ! pattern.test( $this.val()  ) ) {
			$parent.removeClass( 'woocommerce-validated' ).addClass( 'woocommerce-invalid woocommerce-invalid-phone' );
			validated = false;
		}
	}
}

[warning]Но при следующем обновлении WC данная проверка сотрется[/warning]

Поэтому данную функцию лучше прописать в своем файле скриптов:

jQuery('body').on('change', '.validate-phone input', function() {
	var pattern = new RegExp(/^([0-9\s\/\+\-\#\_\(\)]*)$/);
	if ( ! pattern.test( $('.validate-phone input').val()  ) ) {
		$('.validate-phone').removeClass( 'woocommerce-validated' ).addClass( 'woocommerce-invalid woocommerce-invalid-phone woocommerce-invalid-required-field' );
	}
});

Но у данного метода есть небольшой изъян, при нажатии кнопки Оформить заказ (#place_order) полю, даже если оно заполнено не корректно добавляется класс woocommerce-validated. И даже при попытке привязать функцию к триггерам

jQuery(document).on( 'update_checkout', function(){  });
jQuery(document).on( 'init_checkout', function(){  });

ничего не выходит. Происходит это потому что в файле checkout.js в конце валидации есть функция проверяющая у полей параметр validated, который принимает значения внутри функции validate_field и вот перебить эту проверку внешним файлом мы не можем.

Вот доп. функция которая решает (несколько примитивно) данный вопрос:

jQuery('body').on( 'click','#place_order', function(){
	var pattern = new RegExp(/^([0-9\s\/\+\-\#\_\(\)]*)$/);

	if ( ! pattern.test( $('.validate-phone input').val()  ) ) {
		setTimeout(function(){ 
			$('.validate-phone').removeClass( 'woocommerce-validated' ).addClass( 'woocommerce-invalid woocommerce-invalid-phone woocommerce-invalid-required-field' ); 
		}, 1000);
	}	
});

Тэги: ,

Поделится информацией с друзьями

  • Похожие записи
  • Комментарии
  • Вложения
Интеграция Woocommerce с 1С

Интеграция Woocommerce с 1С

Интеграция Woocommerce с 1С — довольно сложная тема с множеством нюансов. Буду описывать на что стоит обращать внимание, с какими проблемами пришлось столкнуться. Плагин 1С:Предприятие Data Exchange Так как не Читать далее »

Пользовательский метод доставки

Пользовательский метод доставки

Создадим пользовательский метод доставки для Woocommerce 3.0. Метод создадим в виде плагина. Создадим для пользовательского метода уведомление при превышении веса (лимит установлен на 0): т.е. если у нас будет в Читать далее »

Кнопки WC

Кнопки WC

Давно хотел подробно разобрать тему с кнопками WC. Кнопки меняют свой вид и функционал в зависимости от типа продукта, наличия, и других факторов. Так же в движке магазина Woocommerce множество Читать далее »

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

1 комментарий

  1. Аватар
    Тарас

    ОСТОРОЖНО МНОГО  ГРАМ. ОШИБОК
     
    Хотел реализовать на странице оформления заказа поочередное заполнение формы сначала доставка потом оплата потом имя и тп. 
    вот скрин 
    К чему я пришол так как не нашел информации по етому поводу может кому-то поможет 
    Я использовал woocommerce saphali lite для кастомных форм 
    тоже использовал Checkout Address Autocomplete for WooCommerce чтоб подтягивать адреса с гугл апи
    и Integrate NP Shipping для апи новой почты
    мне нужно было чтоб форма доставки встала вверху страницы и була позначена 1 номером и чтоб все поля былы не активны 
    что я и зделал код делал для себя так что коменты с огромным количеством грам.  ошибок!  смотрите скрин фото 
     
    $(function(){ 
    /*Перетаскуем способ оплати в верх */
     $('.col-1').prepend( $('ul.wc_payment_methods.payment_methods.methods') );
    $('ulul.wc_payment_methods.payment_methods.methods').detach().prependTo('.col-1');
     $('.col-1').prepend('<h2 class="carttitle number payment">Способ оплаты</h2>');
     
    /*Способ доставки */
     
     $('.col-1').prepend( $('ul#shipping_method') );
    $('ul#shipping_method').detach().prependTo('.col-1');
     $('.col-1').prepend('<h2 class="carttitle number delivery">Способ доставки</h2>');
     
    /*функция отставляет виконнання скрипта*/
      setTimeout(function () {
    /*  удаление старой позицыи доставки*/
      $('tfoot tr.shipping').css('display', 'none');
      /*удаление старой позицыи оплаты*/
    $('#payment .payment_methods').css('display', 'none'); 
    /*оплата отключить дефолтний чек*/
      $('.wc_payment_method input').prop('checked', false);
    $('#wc_payment_method ').prop('checked', false);
      $('#shipping_method input').prop('checked', false);
    $('#shipping_method ').prop('checked', false);
    }, 3000); // время в мс
     
    /*выключаем поля*/
     
    /*имя та фамилия*/
    $(".woocommerce-billing-fields input").attr('disabled', true).css('cursor','not-allowed').css('opacity',0.3);
    /*оплата чеки*/
    $(".wc_payment_methods input").attr('disabled', true).css('cursor','not-allowed').css('opacity',0.3);
    /*самовывоз*/
    $(".woocommerce-billing-fields select").attr('disabled', true).css('cursor','not-allowed').css('opacity',0.3);
    /*оплата слова*/
    $(".wc_payment_methods").attr('disabled', true).css('cursor','not-allowed').css('opacity',0.3);
    /*h2 оплаты*/
    $(".number.payment").attr('disabled', true).css('cursor','not-allowed').css('opacity',0.3);
     
     
    /*Проверяем на checked input доставки если да то открываем форму вибора оплаты*/
    $('body').on('click', "ul#shipping_method", function(){
    if ($("ul#shipping_method input").attr("checked") == 'checked' ) {
     $(".wc_payment_methods").attr('disabled', false).css('cursor','default').css('opacity',1);
    $(".wc_payment_methods input").attr('disabled', false).css('cursor','default').css('opacity',1);
    $(".number.payment").attr('disabled', false).css('cursor','default').css('opacity',1);}
    else
    {};
          });
    /*проверяем на checked input оплати если да то открываем поле имя та фамилия*/
    $('body').on('click', ".wc_payment_methods input", function(){
    if ($(".wc_payment_methods input").attr("checked") == 'checked' ) {
    $(".woocommerce-billing-fields input").attr('disabled', false).css('cursor','default').css('opacity',1).css('filter','blur(0px)');
    $(".carttitle.number.info").attr('disabled', false).css('cursor','default').css('opacity',1).css('filter','blur(0px)');
    $(".carttitle.number.info").attr('disabled', false).css('cursor','default').css('opacity',1).css('filter','blur(0px)');
    $(".woocommerce-billing-fields select").attr('disabled', false).css('cursor','default').css('opacity',1).css('filter','blur(0px)');
    };
     
         });
    /*удаляем поля другой получатель и чекбокс */
    $('.woocommerce-shipping-fields .shipping_address').remove();
      $('.woocommerce-form__label.woocommerce-form__label-for-checkbox.checkbox').remove();
      $('.col-1 .woocommerce-account-fields').remove();
    /*удаляем дефолтний ИТОГО*/
    $(".order-total").css('display', 'none');
    /*меняем без доставки на всего */
    $(".cart-subtotal th").text('Всего :');
    });
     

Оформление заказа Оформление заказа
Запись на прием
Рекомендации для васЗапись на приемOpttour.ru
Спасибо! Наш менеджер свяжется с Вами в течении 5 минут.