php - Tarifa de actualización dinámica basada en botones de radio en el pago de Woocommerce



jquery ajax (1)

Código actualizado en julio de 2018: ahora también funciona para usuarios no registrados

Esto necesita Ajax y no se puede hacer sin él ... Aquí está la forma de Ajax. En este código tienes todo, así que elimina las personalizaciones relacionadas antes de probarlo (es decir, elimina los botones de radio de la plantilla y todo el código relacionado) ...

El código completo (no se necesita nada más) :

// Customizing Woocommerce radio form field
add_action( 'woocommerce_form_field_radio', 'custom_form_field_radio', 20, 4 );
function custom_form_field_radio( $field, $key, $args, $value ) {
    if ( ! empty( $args['options'] ) && is_checkout() ) {
        $field = str_replace( '</label><input ', '</label><br><input ', $field );
        $field = str_replace( '<label ', '<label style="display:inline;margin-left:8px;" ', $field );
    }
    return $field;
}

// Add a custom dynamic packaging fee
add_action( 'woocommerce_cart_calculate_fees', 'add_packaging_fee', 20, 1 );
function add_packaging_fee( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    $packing_fee = WC()->session->get( 'chosen_packing' ); // Dynamic packing fee
    $fee = $packing_fee === 'box' ? 9.00 : 3.00;
    $cart->add_fee( __( 'Packaging fee', 'woocommerce' ), $fee );
}

// Add a custom radio fields for packaging selection
add_action( 'woocommerce_review_order_after_shipping', 'checkout_shipping_form_packing_addition', 20 );
function checkout_shipping_form_packing_addition( )
{
    $domain       = 'wocommerce';

    echo '<tr class="packing-select"><th>' . __('Packing options', $domain) . '</th><td>';

    $chosen   = WC()->session->get('chosen_packing');
    $chosen   = empty($chosen) ? WC()->checkout->get_value('radio_packing') : $chosen;
    $chosen   = empty($chosen) ? 'bag' : $chosen;

    // Add a custom checkbox field
    woocommerce_form_field( 'radio_packing', array(
        'type' => 'radio',
        'class' => array( 'form-row-wide packing' ),
        'options' => array(
            'bag' => __('In a bag '.wc_price(3.00), $domain),
            'box' => __('In a gift box '.wc_price(9.00), $domain),
        ),
        'default' => $chosen,
    ), $chosen );

    echo '</td></tr>';
}

// jQuery - Ajax script
add_action( 'wp_footer', 'checkout_shipping_packing_script' );
function checkout_shipping_packing_script() {
    if ( ! is_checkout() )
        return; // Only checkout page
    ?>
    <script type="text/javascript">
    jQuery( function($){
        $('form.checkout').on('change', 'input[name=radio_packing]', function(e){
            e.preventDefault();
            var p = $(this).val();
            $.ajax({
                type: 'POST',
                url: wc_checkout_params.ajax_url,
                data: {
                    'action': 'woo_get_ajax_data',
                    'packing': p,
                },
                success: function (result) {
                    $('body').trigger('update_checkout');
                    console.log('response: '+result); // just for testing | TO BE REMOVED
                },
                error: function(error){
                    console.log(error); // just for testing | TO BE REMOVED
                }
            });
        });
    });
    </script>
    <?php

}

// Php Ajax (Receiving request and saving to WC session)
add_action( 'wp_ajax_woo_get_ajax_data', 'woo_get_ajax_data' );
add_action( 'wp_ajax_nopriv_woo_get_ajax_data', 'woo_get_ajax_data' );
function woo_get_ajax_data() {
    if ( isset($_POST['packing']) ){
        $packing = sanitize_key( $_POST['packing'] );
        WC()->session->set('chosen_packing', $packing );
        echo json_encode( $packing );
    }
    die(); // Alway at the end (to avoid server error 500)
}

El código va en el archivo function.php de su tema hijo activo (o tema activo). Probado y funciona .

Así que estoy desarrollando un complemento para woocommerce, y he agregado una selección para empacar, ya sea en una bolsa de plástico o en Cartoon Box, cada una con un costo diferente.

Una vez que el usuario selecciona una de las opciones, necesito WordPress para actualizar los precios y actualizar el costo agregando la tarifa correcta usando:

WC_Cart $cart->add_fee( 'Emballagegebyr', intval($fees));

¿Cuál es la mejor manera de agregar la tarifa WC_Cart y actualizar el precio? y cómo debería ser el código?

¿Y está bien usar $ _GET y $ _POST para obtener los valores o incluso mejor? ¿Hay alguna manera de usar AJAX para actualizar el precio sin actualizar la página?

Actualmente, estoy usando $ _GET para obtener los datos del navegador mediante el siguiente código

function at87_add_custom_fees( WC_Cart $cart ){
    $fees = 3; // fee amount
    $fees = isset($_GET['test']) ? $_GET['test'] : 3;

    $cart->add_fee( 'Emballagegebyr', intval($fees));
}

y mi plan es entonces quizás agregar un código Javascript como el siguiente para luego usar el botón de opción para actualizar la página y pasar la opción seleccionada.

add_action( 'wp_footer', 'woocommerce_add_gift_box' );
function woocommerce_add_gift_box() {
    if (is_checkout()) {
    ?>
    <script type="text/javascript">
    jQuery( document ).ready(function( $ ) {
       // $('#add_gift_box').click(function(){
    //       jQuery('body').trigger('update_checkout');
    //    });

        $("#pakpose1 input:radio").change(function(){
    // Do something interesting here
            alert("test");
        });
    });
    </script>
    <?php
    }
}

Sin embargo, no estoy seguro de si esta es la forma más inteligente de hacerlo, y si hay otra manera, eso podría ser mejor y qué efecto de seguridad podría tener, tal vez hay algunos ganchos que pueden hacer el mismo trabajo.

Por cierto: para obtener los botones de radio en la página de pago, hice el complemento de tal manera que anula el woocommerce review-order.php y agregué los botones de radio en esa plantilla de la siguiente manera:

<tr class="packing-selections">
      <th>Pakning</th>
      <td>
                <input type="radio" id="pakpose1" name="pakpose" value="pakpose" checked="checked">Pak i pose <?php echo get_woocommerce_currency_symbol() ?>3.00<br>
                <input type="radio" id="pakpose2" name="pakpose" value="pakkasse">Pak i papkasse <?php echo get_woocommerce_currency_symbol() ?>9.00
     </td>
</tr>




woocommerce