Отключите кнопку оформить заказ и отобразите сообщение, если страна XX НЕ выбрана, а корзина на странице оформления заказа содержит конкретный товар в WooCommerce

#wordpress #woocommerce #product #checkout #country

Вопрос:

У кого-нибудь есть какие-либо идеи, как справиться с таким сценарием? Я хочу отобразить сообщение с уведомлением и отключить кнопку «Оформить заказ» на странице оформления заказа, когда выбрана страна, не являющаяся страной XX, и корзина содержит определенный товар (не подлежащий доставке в другую страну).

Я мог бы сделать это с помощью Jquery, но не могу получить доступ к кнопке размещения заказа, так как ее форма обновляется с помощью AJAX каждый раз, когда я меняю платежный адрес. Это то, к чему я пришел так далеко:

 add_action( 'woocommerce_checkout_before_customer_details', 'display_shipping_notice' );
function display_shipping_notice() {
    echo '<div class="shipping-notice woocommerce-error" role="alert" style="display:none">We cannot ship this product to your country. Please remove it from the cart to continue!</div>';
    
}


add_action( 'woocommerce_after_checkout_form', 'show_shipping_notice_js' );
function show_shipping_notice_js(){
    ?>
    <script>
        jQuery(function($){
            var countryCode  = 'LV', // Set the country code (That will display the message)
                countryField = 'select#billing_country'; // The Field selector to target
            
            function showHideShippingNotice( countryCode, countryField ){
                if( $(countryField).val() !== countryCode amp;amp; $('.shop_table tr').hasClass('id-27733')){
                    $('.shipping-notice').show();                   
                    $('.woocommerce-checkout-payment').hide();
                    
                }
                else {
                    $('.shipping-notice').hide();
                    $('.woocommerce-checkout-payment').show();
                }
            }

            // On Ready (after DOM is loaded)
            showHideShippingNotice( countryCode, countryField );

            // On billing country change (Live event)
            $('form.checkout').on('change', countryField, function() {
                showHideShippingNotice( countryCode, countryField );
            });
        });
    </script>
    <?php
}

function cart_item_class( $class, $values, $values_key ) {
    if ( isset( $values[ 'product_id' ] ) ) {
        $class .= ' id-' . $values[ 'product_id' ];
    }
    return $class;
}
add_filter( 'woocommerce_cart_item_class', 'cart_item_class', 10, 3 );
 

Ответ №1:

Нет необходимости использовать jQuery или AJAX, также нет необходимости отображать пользовательское сообщение через HTML-раздел, так как это можно сделать с помощью wc_add_notice() крючка(ов) WooCommerce.

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


Если вы хотите выполнить эту проверку только на странице оформления заказа, вы можете использовать woocommerce_order_button_html крючок:

 function filter_woocommerce_order_button_text( $button ) {        
    // The targeted product ids
    $targeted_ids = array( 30, 815 );

    // Flag
    $found = false;

    // Loop through cart items
    foreach ( WC()->cart->get_cart() as $cart_item ) {
        if ( array_intersect( $targeted_ids, array( $cart_item['product_id'], $cart_item['variation_id'] ) ) ) {
            $found = true;
            break;
        }
    }

    // True
    if ( $found ) {
        // Get billing country
        $billing_country = WC()->customer->get_billing_country();
    
        // Multiple country codes can be added, separated by a comma
        $countries = array( 'BE', 'LV' );
    
        // Checks if a value NOT exists in an array
        if ( ! in_array( $billing_country, $countries ) ) {
            $style  = 'style="background:Silver !important; color:white !important; cursor: not-allowed !important; text-align:center;"';
            $text   = apply_filters( 'woocommerce_order_button_text', __( 'Place order', 'woocommerce' ) );
            $button = '<a class="button"' . $style . '>' . $text . '</a>';
            
            // Clear all other notices          
            wc_clear_notices();
            
            // Notice
            wc_add_notice( __( 'We cannot ship this product to your country. Please remove it from the cart to continue!', 'woocommerce' ), 'error' ); 
        }
    }
    
    return $button;
}
add_filter( 'woocommerce_order_button_html', 'filter_woocommerce_order_button_text', 10, 1 );
 

Или для комбинации корзины и страницы оформления заказа вы можете использовать woocommerce_check_cart_items крючок:

 function action_woocommerce_check_cart_items() {        
    // The targeted product ids
    $targeted_ids = array( 30, 815 );

    // Flag
    $found = false;

    // Loop through cart items
    foreach ( WC()->cart->get_cart() as $cart_item ) {
        if ( array_intersect( $targeted_ids, array( $cart_item['product_id'], $cart_item['variation_id'] ) ) ) {
            $found = true;
            break;
        }
    }

    // True
    if ( $found ) {
        // Get billing country
        $billing_country = WC()->customer->get_billing_country();
        
        // Multiple country codes can be added, separated by a comma
        $countries = array( 'BE', 'LV' );
    
        // Checks if a value NOT exists in an array
        if ( ! in_array( $billing_country, $countries ) ) {
            // Notice
            wc_add_notice( __( 'We cannot ship this product to your country. Please remove it from the cart to continue!', 'woocommerce' ), 'error' ); 
            
            // Remove proceed to checkout button
            remove_action( 'woocommerce_proceed_to_checkout', 'woocommerce_button_proceed_to_checkout', 20 );
        }
    }
}   
add_action( 'woocommerce_check_cart_items' , 'action_woocommerce_check_cart_items', 10, 0 );
 

Комментарии:

1. Эй, есть ли возможность добавить дополнительный класс a для этого продукта $targeted_ids, если выбрана страна !== $страны? Тогда я мог бы визуально пометить продукт с помощью css?

2. @jam да, вы можете сделать это с помощью woocommerce_cart_item_class крючка фильтра