woocommerce custom checkout field to add fee to order ajax
Asked Answered
S

3

15

I'm trying to ad a custom fee to the order total upon checkout. I've added a checkbox within woocommerce

add_action( 'woocommerce_after_checkout_billing_form', 'add_box_option_to_checkout' );
function add_box_option_to_checkout( $checkout ) {
    echo '<div id="message_fields">';
    woocommerce_form_field( 'add_gift_box', array(
        'type'          => 'checkbox',
        'class'         => array('add_gift_box form-row-wide'),

        'label'         => __('Ilość pudełek ozdobnych - 25 PLN/szt'),
        'placeholder'   => __(''),
        ), $checkout->get_value( 'add_gift_box' ));
}

Included a custom js file which schould handle the event

jQuery( document ).ready(function( $ ) {

  $('#add_gift_box').click(function(){
        var data = {
            action: 'woocommerce_add_gift_box',
            state: '200',
        };
        jQuery.ajax({
            type: 'POST',
            url: wc_checkout_params.ajax_url,
            data: data,
            success: function (code) {
                console.log(code);
                jQuery('body').trigger('update_checkout');
            },
            dataType: 'html'
        });

  });
});

And a php fee handling function

function woo_add_cart_fee( $data ){
  if ( is_admin() && ! defined( 'DOING_AJAX' ) || ! $_POST )  return;

  $extracost = 0;
  if (isset($_POST['state'])) {
    $extracost = intval($_POST['state']);
  }
  WC()->cart->add_fee( 'Ozdobne pudełka:', $extracost );

}
add_action( 'woocommerce_cart_calculate_fees', 'woo_add_cart_fee' );


add_action('wp_ajax_woocommerce_add_gift_box', 'woo_add_cart_fee', 10);
add_action('wp_ajax_nopriv_woocommerce_add_gift_box', 'woo_add_cart_fee', 10);

For some reasons the value of $_POST['state'] isn't added, the function works when I give a hard coded value, I've tried many option but cant get this to work.

I've seen similar posts but none of them had the answer.

Schultz answered 20/8, 2015 at 13:5 Comment(2)
Did you ever figure this out?Fruitcake
Not yet - I will post an update when I find the answer, now I used the checkout adons plugin to achieve thisSchultz
B
34

The post data is sent by the AJAX functions in 'post_data', serialized. So to get the value of your checkbox, you only need to parse_str() this!

parse_str( $_POST['post_data'], $post_data );

then you can get your 'add_gift_box' option from $post_data['add_gift_box']. Note that upon order completion, this 'post_data' element is not available anymore and everything is in $_POST.

Complete example, based on your code:


1) adding the checkbox to the checkout

add_action( 'woocommerce_after_checkout_billing_form', 'add_box_option_to_checkout' );
function add_box_option_to_checkout( $checkout ) {
    echo '<div id="message_fields">';
    woocommerce_form_field( 'add_gift_box', array(
        'type'          => 'checkbox',
        'class'         => array('add_gift_box form-row-wide'),

        'label'         => __('Ilość pudełek ozdobnych - 25 PLN/szt'),
        'placeholder'   => __(''),
        ), $checkout->get_value( 'add_gift_box' ));
        echo '</div>';
}

2) script to update cart when checkbox clicked (no need for extra AJAX requests!)

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');
        });
    });
    </script>
    <?php
    }
}

3) action to add the fee

add_action( 'woocommerce_cart_calculate_fees', 'woo_add_cart_fee' );
function woo_add_cart_fee( $cart ){
        if ( ! $_POST || ( is_admin() && ! is_ajax() ) ) {
        return;
    }

    if ( isset( $_POST['post_data'] ) ) {
        parse_str( $_POST['post_data'], $post_data );
    } else {
        $post_data = $_POST; // fallback for final checkout (non-ajax)
    }

    if (isset($post_data['add_gift_box'])) {
        $extracost = 25; // not sure why you used intval($_POST['state']) ?
        WC()->cart->add_fee( 'Ozdobne pudełka:', $extracost );
    }

}
Beetlebrowed answered 17/6, 2016 at 15:26 Comment(7)
Thank you. I'll check this out.Schultz
This worked great! But out of curiosity, how did the jquery trigger('update_checkout') fire the function woo_add_cart_fee?Kike
update_checkout will send all checkout form data to WooCommerce and update the totals. One of the actions triggered during this update (server side) is woocommerce_cart_calculate_fees, hence it is executing woo_add_cart_fee()Beetlebrowed
It works perfectly. How can I apply it to below of add to cart section instead of checkout page?Digestible
Perfect. I spent two hours trying to make something like this to work. I didn't know about the update_checkoutBrynnbrynna
Thank you for your code @Ewout. It works. Do you have any idea om how to get this code to work on the woocommerce_review_order_after_shipping hook? It breaks if I try that.Antonetta
@Antonetta that hook is in a dynamic part of the page that is being refreshed by AJAX, and the jQuery (written in 2016) is a bit dated and doesn't handle live elements. You could try (untested): JS jQuery( function( $ ) { $(document).on('click','#add_gift_box',function(){ $('body').trigger('update_checkout'); }); }); But it's possible it won't work at all because that template isn't part of the <form>. So you may need to sync.Beetlebrowed
S
6

This is awesome!! Thanks a lot. I've changed it a little bit to add a percentage instead. I know this is not a better answer but I have no reputation to push your answer up. For whoever was stuck like me..

add_action( 'woocommerce_cart_calculate_fees', 'woo_add_cart_fee' ); function woo_add_cart_fee( $cart ){
  global $woocommerce;

    if ( ! $_POST || ( is_admin() && ! is_ajax() ) ) {
    return;
}

if ( isset( $_POST['post_data'] ) ) {
    parse_str( $_POST['post_data'], $post_data );
} else {
    $post_data = $_POST; // fallback for final checkout (non-ajax)
}

if (isset($post_data['add_gift_box'])) {

$percentage = 0.01;
$surcharge = ( $woocommerce->cart->cart_contents_total + $woocommerce->cart->shipping_total ) * $percentage;    
$woocommerce->cart->add_fee( 'Surcharge', $surcharge, true, '' );
}

}
Strep answered 29/11, 2016 at 2:35 Comment(0)
W
0

Here is a slight variation that asks a donor if they are willing to add 3% to their order to cover the credit card processing fees.

I use this on a site where visitors can make donations using woocommerce. I needed to provide them with the option to add the fees, rather than just adding it in cart blanche.

My answer is simply a hybrid of the previous ones, with small modification, hope it helps someone.

/**********************************************************************/
// add extra fee option at checkout
// See: https://mcmap.net/q/760571/-woocommerce-custom-checkout-field-to-add-fee-to-order-ajax

add_action( 'woocommerce_after_checkout_billing_form', 'add_fee_option_to_checkout' );
function add_fee_option_to_checkout( $checkout ) {
    echo '<div id="message_fields" class="bank-fees" span style="
    border: 2px solid orange;
    padding: 10px;
    margin: 10px 0;
    ">
    <h3>Pay Bank Fee?</h3>
    <p>Thanks for your donation! Our bank charges a 3% credit card processing fee. Tick the box if you are willing to pay the fee on top of your donation. ';
    woocommerce_form_field( 'add_fee_option', array(
        'type'          => 'checkbox',
        'class'         => array('add_fee_option form-row-wide'),

        'label'         => __('Pay bank transaction fees? '),
        'placeholder'   => __(''),
        ), $checkout->get_value( 'add_fee_option' ));
        echo '</div>';
}

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

add_action( 'woocommerce_cart_calculate_fees', 'woo_add_cart_fee' ); function woo_add_cart_fee( $cart ){
  global $woocommerce;

    if ( ! $_POST || ( is_admin() && ! is_ajax() ) ) {
    return;
}

if ( isset( $_POST['post_data'] ) ) {
    parse_str( $_POST['post_data'], $post_data );
} else {
    $post_data = $_POST; // fallback for final checkout (non-ajax)
}

if (isset($post_data['add_fee_option'])) {

$percentage = 0.03;  // 3%
$surcharge = ( $woocommerce->cart->cart_contents_total + $woocommerce->cart->shipping_total ) * $percentage;    
$woocommerce->cart->add_fee( 'Bank Fee', $surcharge, true, '' );
}

}
Warfourd answered 27/1 at 4:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.