Как добавить платные доп опции к доставке определенным методом?
Необходимо добавить доп. опции к доставке определенным методом.
Вот допустим выбрали мы платную доставку до дома, но нужен выбор платной опции разгрузка или разгрузка и подъем товара на этаж, как правильно это реализовать, получилось модифицировать код от Мишы, но работает корректно только если кликать по методу доставки и обновлять страницу через 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' ] ); } }
Дополнительно:
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос
У Вас почти правильная схема, но 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'])); } });
Добавление 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);
Важный момент: стоимость из формы нельзя полностью доверять пользователю. Сейчас пользователь технически может подменить
333на любое значение. Лучше хранить допустимые варианты в массиве и проверять выбранный ключ:$prices = [ '0' => 0, 'unload' => 333, 'floor' => 777, ];
А в сессии хранить не цену, а ключ варианта. Тогда при пересчёте Вы берёте цену из серверного массива. Это безопаснее и не даст подменить стоимость через DevTools.
Если опция должна сохраняться в заказе, добавьте её в meta заказа через
woocommerce_checkout_create_order. Иначе сбор попадёт в total, но менеджер потом не всегда поймёт, какую услугу выбрал клиент.