Как добавить платные доп опции к доставке определенным методом?

Ссылка скопирована
1 ответ

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

// Добавление радио-кнопок add_action( 'woocommerce_review_order_before_payment', 'truemisha_checkout_options', 25 );   function truemisha_checkout_options() {   $chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' );  	// сначала получаем объект из сессий 	$selected = WC()->session->get( 'gift_wrap' ); 	// если пусто, то ставим значение 0 	$selected = empty( $selected ) ? '0' : $selected; 	      if( in_array( 'flat_rate:32', $chosen_shipping_methods ) ) { 		 	// выводим радио-кнопки 	echo '<div id="truemisha-checkout-radio"><h4>Разгрузка / Подъем на этаж</h4>';   	woocommerce_form_field( 		'gift_wrap', 		array( 			'type' => 'radio', 			'class' => array( 'form-row-wide', 'update_totals_on_change' ), 			'options' => array( 				'0' => 'Не нужно', 				'333' => 'Разгрузка', 				'777' => 'Разгрузка + Подъем на ваш этаж', 			), 		), 		$selected  	);   	echo '</div>';   } }   // пересчитываем заказ и добавляем сбор, если нужно add_action( 'woocommerce_cart_calculate_fees', 'truemisha_radio_choice_fee', 25 );   function truemisha_radio_choice_fee( $cart ) {   	// ничего не делаем в админке и если не AJAX-запрос 	if ( is_admin() && ! defined( 'DOING_AJAX' ) ) { 		return; 	}   	// получаем данные из сессий 	$value = WC()->session->get( 'gift_wrap' );   	// добавляем соответствующий сбор 	if ( $value ) { 		$cart->add_fee( 'Разгрузка / Подъем', $value); 	}   }   // сохраняем выбор радио-кнопки в сессии add_action( 'woocommerce_checkout_update_order_review', 'truemisha_set_session' );   function truemisha_set_session( $posted_data ) {   	parse_str( $posted_data, $output );   	if ( isset( $output[ 'gift_wrap' ] ) ){ 		WC()->session->set( 'gift_wrap', $output[ 'gift_wrap' ] ); 	}   }

// Добавление радио-кнопок add_action( 'woocommerce_review_order_before_payment', 'truemisha_checkout_options', 25 ); function truemisha_checkout_options() { $chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' ); // сначала получаем объект из сессий $selected = WC()->session->get( 'gift_wrap' ); // если пусто, то ставим значение 0 $selected = empty( $selected ) ? '0' : $selected; if( in_array( 'flat_rate:32', $chosen_shipping_methods ) ) { // выводим радио-кнопки echo '<div id="truemisha-checkout-radio"><h4>Разгрузка / Подъем на этаж</h4>'; woocommerce_form_field( 'gift_wrap', array( 'type' => 'radio', 'class' => array( 'form-row-wide', 'update_totals_on_change' ), 'options' => array( '0' => 'Не нужно', '333' => 'Разгрузка', '777' => 'Разгрузка + Подъем на ваш этаж', ), ), $selected ); echo '</div>'; } } // пересчитываем заказ и добавляем сбор, если нужно add_action( 'woocommerce_cart_calculate_fees', 'truemisha_radio_choice_fee', 25 ); function truemisha_radio_choice_fee( $cart ) { // ничего не делаем в админке и если не AJAX-запрос if ( is_admin() && ! defined( 'DOING_AJAX' ) ) { return; } // получаем данные из сессий $value = WC()->session->get( 'gift_wrap' ); // добавляем соответствующий сбор if ( $value ) { $cart->add_fee( 'Разгрузка / Подъем', $value); } } // сохраняем выбор радио-кнопки в сессии add_action( 'woocommerce_checkout_update_order_review', 'truemisha_set_session' ); function truemisha_set_session( $posted_data ) { parse_str( $posted_data, $output ); if ( isset( $output[ 'gift_wrap' ] ) ){ WC()->session->set( 'gift_wrap', $output[ 'gift_wrap' ] ); } }

Дополнительно:

Нужно решить такую задачу?

Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

Заказать помощь
Лучший ответ
1
Андрей PHP Ответ

У Вас почти правильная схема, но checkout WooCommerce пересчитывается через AJAX. Поэтому недостаточно сохранить значение в сессию один раз: нужно заставить checkout обновляться при выборе радио-кнопки и корректно сбрасывать выбранную опцию, если пользователь сменил способ доставки.

Поле лучше выводить в checkout и дать ему класс update_totals_on_change, а JS дополнительно вызвать update_checkout:

jQuery(function ($) {
  $(document.body).on('change', 'input[name="gift_wrap"]', function () {
    $(document.body).trigger('update_checkout');
  });
});

jQuery(function ($) { $(document.body).on('change', 'input[name="gift_wrap"]', function () { $(document.body).trigger('update_checkout'); }); });

Сохранение в сессию через woocommerce_checkout_update_order_review оставьте, но добавьте сброс, когда нужный метод доставки не выбран:

add_action('woocommerce_checkout_update_order_review', function ($posted_data) {
    parse_str($posted_data, $data);
 
    $chosen = WC()->session->get('chosen_shipping_methods', []);
    $method_is_active = in_array('flat_rate:32', $chosen, true);
 
    if (!$method_is_active) {
        WC()->session->set('gift_wrap', null);
        return;
    }
 
    if (isset($data['gift_wrap'])) {
        WC()->session->set('gift_wrap', wc_clean($data['gift_wrap']));
    }
});

add_action('woocommerce_checkout_update_order_review', function ($posted_data) { parse_str($posted_data, $data); $chosen = WC()->session->get('chosen_shipping_methods', []); $method_is_active = in_array('flat_rate:32', $chosen, true); if (!$method_is_active) { WC()->session->set('gift_wrap', null); return; } if (isset($data['gift_wrap'])) { WC()->session->set('gift_wrap', wc_clean($data['gift_wrap'])); } });

Добавление fee:

add_action('woocommerce_cart_calculate_fees', function ($cart) {
    if (is_admin() && !defined('DOING_AJAX')) {
        return;
    }
 
    $value = (int) WC()->session->get('gift_wrap');
 
    if ($value > 0) {
        $cart->add_fee('Разгрузка / Подъем', $value, false);
    }
}, 25);

add_action('woocommerce_cart_calculate_fees', function ($cart) { if (is_admin() && !defined('DOING_AJAX')) { return; } $value = (int) WC()->session->get('gift_wrap'); if ($value > 0) { $cart->add_fee('Разгрузка / Подъем', $value, false); } }, 25);

Важный момент: стоимость из формы нельзя полностью доверять пользователю. Сейчас пользователь технически может подменить 333 на любое значение. Лучше хранить допустимые варианты в массиве и проверять выбранный ключ:

$prices = [
    '0' => 0,
    'unload' => 333,
    'floor' => 777,
];

$prices = [ '0' => 0, 'unload' => 333, 'floor' => 777, ];

А в сессии хранить не цену, а ключ варианта. Тогда при пересчёте Вы берёте цену из серверного массива. Это безопаснее и не даст подменить стоимость через DevTools.

Если опция должна сохраняться в заказе, добавьте её в meta заказа через woocommerce_checkout_create_order. Иначе сбор попадёт в total, но менеджер потом не всегда поймёт, какую услугу выбрал клиент.

Другие ответы (0)

Пока нет других ответов. Будьте первым, кто поможет автору.

Ответить на вопрос

комментарий

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

Вам также может быть интересно