woocommerce custom checkout field to add fee to order ajax
Solution 1
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 );
}
}
Solution 2
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, '' );
}
}
adam
Updated on June 06, 2022Comments
-
adam almost 2 years
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.
-
adam almost 8 yearsThank you. I'll check this out.
-
Buster almost 7 yearsThis worked great! But out of curiosity, how did the jquery trigger('update_checkout') fire the function woo_add_cart_fee?
-
Ewout almost 7 yearsupdate_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 executingwoo_add_cart_fee()
-
Tuna Zenginbaş over 4 yearsIt works perfectly. How can I apply it to below of add to cart section instead of checkout page?
-
Christer Fernstrom about 4 yearsPerfect. I spent two hours trying to make something like this to work. I didn't know about the update_checkout
-
user3766894 almost 3 yearsThank 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.
-
Ewout almost 3 years@user3766894 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.