Woocommerce created fee is not saved in order

134 Views Asked by At

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, '');
    }
}
?>
1

There are 1 best solutions below

4
Bhautik On

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