skip to Main Content

On a Woocommerce store, I am trying to create a checkbox during the checout for a "hand written card" (or whatever anyone calls it). I create the field save it during checkout and showing it appropriately on the admin page. No problems here.

However, I want to add a fee for that. I implement a check for the field but I cant figure it out how to pass the data to save the fee. I tried the following but the fee appears in the final cart table but is not calculated or shown on the thank you page or admin > order.

What I tried:

<?php
//add card fee if checkbox field is checked
add_action( 'woocommerce_cart_calculate_fees', 'add_custom_fee' );
function add_custom_fee( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) ){return;}
    
    //if on post data there is gift_card_checkbox that is 'checked' then add fee
    parse_str($_POST['post_data'], $post_data);
    if ( isset( $post_data['gift_card_checkbox'] ) && $post_data['gift_card_checkbox'] == 1 ) {
        $fee = 1;
        WC()->cart->add_fee('Gift card', $fee, true, '');
    }
}


add_action( 'woocommerce_checkout_create_order', 'add_custom_fee_checkout', 20, 2 );
function add_custom_fee_checkout( $order, $data ) {

    $gift_card = get_post_meta($order->get_id(), 'gift_card_checkbox', true);
    if ($gift_card && $gift_card == 1) {
    //if (isset($_POST['gift_card_checkbox']) && $_POST['gift_card_checkbox'] == 1) { 
    
        //test1
        $order->add_fee('Gift card 1', 1);
    
        //test2
        $order->add_item(
            new WC_Order_Item_Fee(
                array(
                    'name' => "Gift card 2",
                    'amount' => 2,
                    'tax_status' => 'taxable',
                    'total' => 2
                )
            )
        );
        
        //test3
        WC()->cart->add_fee('Gift card 3', 3, true, '');
    }
}
?>

2

Answers


  1. add a custom checkbox field to the WooCommerce checkout page after the order notes section. It uses the woocommerce_after_order_notes action hook to add the field. The add_custom_checkbox_to_checkout function is responsible for rendering the checkbox field. It uses the woocommerce_form_field function to generate the checkbox field HTML. The value of the checkbox is retrieved from the WooCommerce session using WC()->session->get('handwritten_card').

    // Add the custom checkbox field to the checkout page
    add_action( 'woocommerce_after_order_notes', 'add_custom_checkbox_to_checkout' );
    function add_custom_checkbox_to_checkout( $checkout ) {
        echo '<div id="custom_checkbox_field">';
        // Generate the checkbox field with the label "Handwritten Card"
        woocommerce_form_field( 'handwritten_card', array(
            'type' => 'checkbox',
            'class' => array( 'input-checkbox' ),
            'label' => 'Handwritten Card',
        ), WC()->session->get( 'handwritten_card' ));
        echo '</div>';
    }
    

    add a JavaScript script to the footer of the page using the wp_footer action hook. The script uses jQuery to detect the change event of the checkbox and triggers the update_checkout event when the checkbox is changed. This event is used to update the checkout page and recalculate the totals.

    // Add JavaScript script to handle checkbox change event
    add_action( 'wp_footer', 'custom_checkbox_script' );
    function custom_checkbox_script() {
        ?>
        <script type="text/javascript">
            jQuery(document).ready(function($) {
                // Detect checkbox change event
                $(document).on('change', '#handwritten_card', function() {
                    $(document.body).trigger('update_checkout');
                });
            });
        </script>
        <?php
    }
    

    Below code defines the woo_add_cart_fee function, which is hooked to the woocommerce_cart_calculate_fees action. This function is responsible for adding a fee to the cart when the checkbox is checked and removing the fee when the checkbox is unchecked. It first checks if the request is a valid submission and then parses the POST data to retrieve the checkbox value. The checkbox value in the session is reset to null. If the checkbox is checked, it adds a fee named "Gift card" with a value of 2 to the cart using $woocommerce->cart->add_fee(). It also sets the checkbox value in the WooCommerce session using WC()->session->set('handwritten_card', sanitize_text_field($data['handwritten_card'])). If the checkbox is unchecked, it removes the "Gift card" fee from the cart using $woocommerce->cart->remove_fee().

    // Add or remove a fee based on the checkbox value
    function woo_add_cart_fee() {
        global $woocommerce;
    
        // Check if the request is a valid submission
        if ( ! $_POST || ( is_admin() && ! is_ajax() ) ) {
            return;
        }
    
        // Parse the POST data to retrieve the checkbox value
        parse_str($_POST['post_data'], $data);
    
        // Reset the checkbox value in the session
        WC()->session->set( 'handwritten_card', null );
    
        // Check if the checkbox is checked
        if ( isset( $data['handwritten_card'] ) && $data['handwritten_card'] == 1 ) {
            // Add a fee to the cart named "Gift card" with a value of 2
            $woocommerce->cart->add_fee( 'Gift card', 2, true, '' );
            // Set the checkbox value in the session
            WC()->session->set( 'handwritten_card', sanitize_text_field( $data['handwritten_card'] ) );
        } else {
            // Remove the "Gift card" fee from the cart if the checkbox is unchecked
            foreach ( $woocommerce->cart->get_fees() as $fee_key => $fee ) {
                if ( $fee->name === 'Gift card' ) {
                    $woocommerce->cart->remove_fee( $fee_key );
                    break;
                }
            }
        }
    }
    add_action( 'woocommerce_cart_calculate_fees', 'woo_add_cart_fee' );
    

    OUTPUT

    enter image description here

    Login or Signup to reply.
  2. If anyone is coming across this wondering why the fee is showing on the checkout page but not on the thank you page or in the order…the reason it was happening to me was that I was making use of $_POST['post_data'] on the checkout page to get the form fields.

    I posted my solution on another stackoverflow question here: https://stackoverflow.com/a/77656386/4484799

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search