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

Вопрос или проблема

В разделе оформления заказа Woocommerce, я пытаюсь добавить флажок, который добавляет дополнительный продукт подписки. Это работает хорошо, и я воспользовался помощью здесь

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

Я использовал этот код, и он работает, но цена товара не изменяется на странице оплаты PayPal.

        // Отобразить пользовательское поле при оформлении заказа
    add_action( 'woocommerce_checkout_before_terms_and_conditions', 'custom_checkbox_checkout_field' );
    function custom_checkbox_checkout_field() {
        $value = WC()->session->get('add_a_product');

        woocommerce_form_field( 'cb_add_product', array(
            'type'          => 'checkbox',
            'label'         => '  ' . __('Пожалуйста, отметьте здесь для получения VIP членства'),
            'class'         => array('form-row-wide'),
        ), $value == 'yes' ? true : false );
    }


    // jQuery Ajax запрос
    add_action( 'wp_footer', 'checkout_custom_jquery_script' );
    function checkout_custom_jquery_script() {
        // Только страница оформления заказа
        if( is_checkout() && ! is_wc_endpoint_url() ):

        // Удалить "ship_different" индивидуальную сессию WC при загрузке
        if( WC()->session->get('add_a_product') ){
            WC()->session->__unset('add_a_product');
        }
        if( WC()->session->get('product_added_key') ){
            WC()->session->__unset('product_added_key');
        }
        // Код jQuery Ajax
        ?>
        <script type="text/javascript">
        jQuery( function($){
            if (typeof wc_checkout_params === 'undefined')
                return false;

            $('form.checkout').on( 'change', '#cb_add_product', function(){
                var value = $(this).prop('checked') === true ? 'yes' : 'no';

                $.ajax({
                    type: 'POST',
                    url: wc_checkout_params.ajax_url,
                    data: {
                        'action': 'add_a_product',
                        'add_a_product': value,
                    },
                    success: function (result) {
                        $('body').trigger('update_checkout');
                        //console.log(result);
                    }
                });
            });
        });
        </script>
        <?php
        endif;
    }

    // PHP обработчик Ajax-запроса WordPress
    add_action( 'wp_ajax_add_a_product', 'checkout_ajax_add_a_product' );
    add_action( 'wp_ajax_nopriv_add_a_product', 'checkout_ajax_add_a_product' );
    function checkout_ajax_add_a_product() {
        if ( isset($_POST['add_a_product']) ){
            WC()->session->set('add_a_product', esc_attr($_POST['add_a_product']));
            echo $_POST['add_a_product'];
        }
        die();
    }

    // Добавление или удаление бесплатного продукта
    add_action( 'woocommerce_before_calculate_totals', 'adding_removing_specific_product' );
    function adding_removing_specific_product( $cart ) {
        if (is_admin() && !defined('DOING_AJAX'))
            return;

        if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
            return;

        // ЗДЕСЬ ID конкретного товара
        $product_id = 179;

        if( WC()->session->get('add_a_product') == 'yes' && ! WC()->session->get('product_added_key') )
        {

        foreach ( $cart->get_cart() as $cart_item ) {
            $cart_item_key = $cart->add_to_cart( $product_id );
            WC()->session->set('product_added_key', $cart_item_key);

             // Получить ID продукта (или вариации)
             $product_id = $cart_item['data']->get_id();

             // ПОЛУЧИТЬ НОВУЮ ЦЕНУ (код, который нужно заменить вашим)
             $new_price = get_post_meta( $product_id, 'pro_price_extra_info', true );

             // Обновлённая цена элемента корзины
             $cart_item['data']->set_price( floatval( $new_price ) );
        }
        }
        elseif( WC()->session->get('add_a_product') == 'no' && WC()->session->get('product_added_key') )
        {
            $cart_item_key = WC()->session->get('product_added_key');
            $cart->remove_cart_item( $cart_item_key );
            WC()->session->__unset('product_added_key');
        }
    }

Я решил свою проблему. этот код может помочь другим в будущем.

            // Отобразить пользовательское поле при оформлении заказа
            add_action( 'woocommerce_checkout_before_terms_and_conditions', 'custom_checkbox_checkout_field' );
            function custom_checkbox_checkout_field() {
                $value = WC()->session->get('add_a_product');

                woocommerce_form_field( 'cb_add_product', array(
                    'type'          => 'checkbox',
                    'label'         => '&nbsp;&nbsp;' . __('Пожалуйста, отметьте здесь для получения VIP членства'),
                    'class'         => array('form-row-wide'),
                ), $value == 'yes' ? true : false );
            }


            // jQuery Ajax запрос
            add_action( 'wp_footer', 'checkout_custom_jquery_script' );
            function checkout_custom_jquery_script() {
                // Только страница оформления заказа
                if( is_checkout() && ! is_wc_endpoint_url() ):

                // Удалить "ship_different" индивидуальную сессию WC при загрузке
                if( WC()->session->get('add_a_product') ){
                    WC()->session->__unset('add_a_product');
                }
                if( WC()->session->get('product_added_key') ){
                    WC()->session->__unset('product_added_key');
                }
                // Код jQuery Ajax
                ?>
                <script type="text/javascript">
                jQuery( function($){
                    if (typeof wc_checkout_params === 'undefined')
                        return false;

                    $('form.checkout').on( 'change', '#cb_add_product', function(){
                        var value = $(this).prop('checked') === true ? 'yes' : 'no';

                        $.ajax({
                            type: 'POST',
                            url: wc_checkout_params.ajax_url,
                            data: {
                                'action': 'add_a_product',
                                'add_a_product': value,
                            },
                            success: function (result) {
                                $('body').trigger('update_checkout');
                                //console.log(result);
                            }
                        });

                        if(value == 'no'){
                            window.location.reload();
                        }
                    });
                });
                </script>
                <?php
                endif;
            }

            // PHP обработчик Ajax-запроса WordPress
            add_action( 'wp_ajax_add_a_product', 'checkout_ajax_add_a_product' );
            add_action( 'wp_ajax_nopriv_add_a_product', 'checkout_ajax_add_a_product' );
            function checkout_ajax_add_a_product() {
                if ( isset($_POST['add_a_product']) ){
                    WC()->session->set('add_a_product', esc_attr($_POST['add_a_product']));
                    echo $_POST['add_a_product'];
                }
                die();
            }

            // Добавление или удаление бесплатного продукта
            add_action( 'woocommerce_before_calculate_totals', 'adding_removing_specific_product' );
            function adding_removing_specific_product( $cart ) {
                if (is_admin() && !defined('DOING_AJAX'))
                    return;

                if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
                    return;

                $has_sub = wcs_user_has_subscription( '', '179', 'active' );

                $product_id = 179;

                if( WC()->session->get('add_a_product') == 'yes' && ! WC()->session->get('product_added_key') ){
                    // ЗДЕСЬ ID конкретного товара

                    foreach ( $cart->get_cart() as $cart_item ) {       

                         // Получить ID продукта (или вариации)
                         $product_idnew = $cart_item['data']->get_id();
                         // ПОЛУЧИТЬ НОВУЮ ЦЕНУ (код, который нужно заменить вашим)
                         $new_price = get_post_meta( $product_idnew, 'pro_price_extra_info', true );
                         $old_price = $cart_item['data']->get_price();

                         if($new_price == NULL){
                            $cart_item['data']->set_price( floatval( $old_price ) );
                         } else {
                            $cart_item['data']->set_price( floatval( $new_price ) );
                         }

                    }

                    $cart_item_key = $cart->add_to_cart( $product_id );
                    WC()->session->set('product_added_key', $cart_item_key);

                } elseif( WC()->session->get('add_a_product') == 'no' && WC()->session->get('product_added_key') ) {

                    $cart_item_key = WC()->session->get('product_added_key');
                    $cart->remove_cart_item( $cart_item_key );      
                    WC()->session->__unset('product_added_key');        

                }elseif ( $has_sub ) {
                    foreach ( $cart->get_cart() as $cart_item ) {       

                         // Получить ID продукта (или вариации)
                         $product_idnew = $cart_item['data']->get_id();
                         // ПОЛУЧИТЬ НОВУЮ ЦЕНУ (код, который нужно заменить вашим)
                         $new_price = get_post_meta( $product_idnew, 'pro_price_extra_info', true );
                            $cart_item['data']->set_price( floatval( $new_price ) );

                    }
                }

            }
            function woo_in_cart($product_id) {
                global $woocommerce;         
                foreach($woocommerce->cart->get_cart() as $key => $val ) {
                    $_product = $val['data'];

                    if($product_id == $_product->id ) {
                        return true;
                    }
                }         
                return false;
            }
            add_action( 'woocommerce_cart_loaded_from_session', 'adding_vip_product' );
            function adding_vip_product( $cart ) {
                $product_id = 179;
                if(woo_in_cart($product_id) ) {

                    foreach ( $cart->get_cart() as $cart_item ) {       

                         // Получить ID продукта (или вариации)
                         $product_idnew = $cart_item['data']->get_id();
                         // ПОЛУЧИТЬ НОВУЮ ЦЕНУ (код, который нужно заменить вашим)
                         $new_price = get_post_meta( $product_idnew, 'pro_price_extra_info', true );
                         if($new_price != 0){
                            $cart_item['data']->set_price( floatval( $new_price ) );
                         }

                    }

                }
            }

.

Ответ или решение

В WooCommerce иногда требуется дополнительная функциональность для улучшения пользовательского опыта. Одна из таких задач — добавление продукта и изменение цен на другие продукты в корзине при помощи чекбокса. Представленный ниже код решает эту задачу, предоставляя возможность добавления дополнительного подписного продукта через чекбокс на странице оформления заказа.

Функционал добавления чекбокса:

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

Код для отображения чекбокса:

add_action('woocommerce_checkout_before_terms_and_conditions', 'custom_checkbox_checkout_field');
function custom_checkbox_checkout_field() {
    $value = WC()->session->get('add_a_product');
    woocommerce_form_field('cb_add_product', array(
        'type' => 'checkbox',
        'label' => '&nbsp;&nbsp;' . __('Please check here to get VIP Membership'),
        'class' => array('form-row-wide'),
    ), $value == 'yes' ? true : false);
}

Реализация AJAX-запроса:

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

Код для AJAX-запроса:

add_action('wp_footer', 'checkout_custom_jquery_script');
function checkout_custom_jquery_script() {
    if (is_checkout() && !is_wc_endpoint_url()):
?>
<script type="text/javascript">
jQuery(function($){
    if (typeof wc_checkout_params === 'undefined')
        return false;

    $('form.checkout').on('change', '#cb_add_product', function(){
        var value = $(this).prop('checked') === true ? 'yes' : 'no';

        $.ajax({
            type: 'POST',
            url: wc_checkout_params.ajax_url,
            data: {
                'action': 'add_a_product',
                'add_a_product': value,
            },
            success: function (result) {
                $('body').trigger('update_checkout');
            }
        });

        if(value == 'no'){
            window.location.reload();
        }
    });
});
</script>
<?php
    endif;
}

Серверная обработка заявки:

При получении AJAX-запроса происходит изменение состояния сессии через функции в WooCommerce. Это позволяет добавлять или удалять продукт из корзины.

Код для обработки AJAX-запроса:

add_action('wp_ajax_add_a_product', 'checkout_ajax_add_a_product');
add_action('wp_ajax_nopriv_add_a_product', 'checkout_ajax_add_a_product');
function checkout_ajax_add_a_product() {
    if (isset($_POST['add_a_product'])){
        WC()->session->set('add_a_product', esc_attr($_POST['add_a_product']));
        echo $_POST['add_a_product'];
    }
    die();
}

Работа с корзиной:

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

Основные моменты котировки новых цен:

  1. Получение новых цен с использованием get_post_meta.
  2. Обновление цен в корзине через set_price.

Код для обработки корзины:

add_action('woocommerce_before_calculate_totals', 'adding_removing_specific_product');
function adding_removing_specific_product($cart) {
    if (is_admin() && !defined('DOING_AJAX'))
        return;
    if (did_action('woocommerce_before_calculate_totals') >= 2)
        return;

    $product_id = 179; // ID подписки

    if(WC()->session->get('add_a_product') == 'yes' && !WC()->session->get('product_added_key')) {
        foreach ($cart->get_cart() as $cart_item) {
            $new_price = get_post_meta($cart_item['data']->get_id(), 'pro_price_extra_info', true);
            $cart_item['data']->set_price(floatval($new_price));

            $cart_item_key = $cart->add_to_cart($product_id);
            WC()->session->set('product_added_key', $cart_item_key);
        }
    } elseif(WC()->session->get('add_a_product') == 'no' && WC()->session->get('product_added_key')) {
        $cart_item_key = WC()->session->get('product_added_key');
        $cart->remove_cart_item($cart_item_key);
        WC()->session->__unset('product_added_key');
    }
}

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

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

Капча загружается...