I have created a checkbox (It does not look like a checkbox anymore) that apply/remove a coupong on change. This works good. But the total does not update on the apply, the page has to be refreshed. I have build this function with some cut and paste from other functions, it was once a radio field, and it might not be the best practise. The coupong ads a discount for 500 SEK.
But how to do I recalculate the total after the coupong is applied?
As you can see in the end, I have tried WC()->cart->calculate_totals();.
This is the site and checkout: https://www.klubbtryck.se/nif/kassa/
This is my code:
// Add a custom checkout field
add_action( 'woocommerce_review_order_after_shipping', 'checkout_shipping_form_delivery_addition_nifny', 20 );
function checkout_shipping_form_delivery_addition_nifny(){
$domain = 'wocommerce';
if ( WC()->session->get( 'chosen_shipping_methods' )[0] == 'local_pickup:3' ) :
echo '<tr class="delivery-radio"><th>' . __('Gift Card', $domain) . '</th><td>';
$chosen = WC()->session->get('chosen_delivery');
$chosen = empty($chosen) ? WC()->checkout->get_value('delivery') : $chosen;
$chosen = empty($chosen) ? 0 : $chosen;
if( $chosen == 1){ $chosen = true; } else { $chosen = false; }
// Add a custom checkbox field
woocommerce_form_field( 'radio_delivery', array(
'type' => 'checkbox',
'label' => '<label for="radio_delivery" class="checkbox-label"><span class="presentkortbesk">I have a gift card</span><span class="priset">-500kr</span></label>',
'class' => array( 'form-row-wide' ),
'required' => false,
//'default' => false,
), $chosen );
echo '</td></tr>';
endif;
}
// jQuery - Ajax script
add_action( 'wp_footer', 'checkout_delivery_script_nifny' );
function checkout_delivery_script_nifny() {
// Only checkout page
if ( ! is_checkout() ) return;
?>
<script type="text/javascript">
jQuery( function($){
if (typeof wc_checkout_params === 'undefined')
return false;
$('form.checkout').on('change', 'input[name=radio_delivery]', function(e){
e.preventDefault();
var d = $(this).prop('checked') === true ? 1 : 0;
//var d = $(this).val();
//alert('value: '+d);
$.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: {
'action': 'delivery',
'delivery': d,
},
success: function (result) {
$('body').trigger('update_checkout');
//console.log(result); // just for testing | TO BE REMOVED
},
error: function(error){
//console.log(error); // just for testing | TO BE REMOVED
}
});
});
});
</script>
<?php
}
// Get Ajax request and saving to WC session
add_action( 'wp_ajax_delivery', 'wc_get_delivery_ajax_data_nifny' );
add_action( 'wp_ajax_nopriv_delivery', 'wc_get_delivery_ajax_data_nifny' );
function wc_get_delivery_ajax_data_nifny() {
if ( isset($_POST['delivery']) ){
WC()->session->set('chosen_delivery', sanitize_key( $_POST['delivery'] ) );
echo json_encode( $delivery ); // Return the value to jQuery
}
die();
}
// Add a custom dynamic delivery fee
add_action( 'woocommerce_cart_calculate_fees', 'add_packaging_fee_nifny', 20, 1 );
function add_packaging_fee_nifny( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Only for targeted shipping method
if ( WC()->session->get( 'chosen_shipping_methods' )[0] != 'local_pickup:3' )
return;
if( WC()->session->get( 'chosen_delivery' ) == 1 ){
if (!in_array('nynashamn2020', WC()->cart->get_applied_coupons())) {
WC()->cart->apply_coupon('card2020');
//WC()->cart->calculate_totals();
}
} else {
if (in_array('nynashamn2020', WC()->cart->get_applied_coupons())) {
WC()->cart->remove_coupon('card2020');
}
}
}
You should replace woocommerce_cart_calculate_fees hook that is only made for Fees with similar woocommerce_before_calculate_totals more appropriated hook as follows:
// Add a custom dynamic delivery fee
add_action( 'woocommerce_before_calculate_totals', 'add_packaging_fee_nifny' );
function add_packaging_fee_nifny( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Only for targeted shipping method
if ( WC()->session->get( 'chosen_shipping_methods' )[0] != 'local_pickup:3' )
return;
if( WC()->session->get( 'chosen_delivery' ) == 1 ){
if (!in_array('nynashamn2020', WC()->cart->get_applied_coupons())) {
WC()->cart->apply_coupon('card2020');
//WC()->cart->calculate_totals();
}
} else {
if (in_array('nynashamn2020', WC()->cart->get_applied_coupons())) {
WC()->cart->remove_coupon('card2020');
}
}
}
Code goes in functions.php file of the active child theme (or active theme). It should better works.
Related
In Woocommerce checkout page, I'am trying to add a check box on checkout page
I have referred to these articles
woocommerce custom checkout field to add fee to order ajax
Checkbox field that add / remove a custom fee in WooCommerce
Add a checkout checkbox field that enable a percentage fee in Woocommerce
add_action( 'woocommerce_review_order_before_order_total', 'checkout_shipping_form_packing_addition', 20 );
function checkout_shipping_form_packing_addition( ){
echo '<tr class="packing-select"><th>';
woocommerce_form_field( 'add_gift_box', array(
'type' => 'checkbox',
'class' => array('add_gift_box form-row-wide'),
'label' => __('Hỗ trợ cài đặt'),
'placeholder' => __(''),
));
echo '</th><td>';}
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
}}
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'])) {
$sl = WC()->cart->get_cart_contents_count();
$extracost = 50000 * $sl; // not sure why you used intval($_POST['state']) ?
WC()->cart->add_fee( 'Hỗ trợ cài đặt x '.$sl.'', $extracost );
}}
add_filter( 'woocommerce_form_field' , 'remove_order_comments_optional_fields_label', 10, 4 );
function remove_order_comments_optional_fields_label( $field, $key, $args, $value ) {
// Only on checkout page for Order notes field
if( 'add_gift_box' === $key && is_checkout() ) {
$optional = ' <span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
$field = str_replace( $optional, '', $field );
}
return $field;
}
It does not work as I would like. What I am doing wrong?
Any help is appreciated.
You really need to use Wordpress Ajax with WC_sessions to make it work like in "Add a checkout checkbox field that enable a percentage fee in Woocommerce" answer thread.
Here is your revisited code:
// Display the custom checkbow field in checkout
add_action( 'woocommerce_review_order_before_order_total', 'fee_installment_checkbox_field', 20 );
function fee_installment_checkbox_field(){
echo '<tr class="packing-select"><th>';
woocommerce_form_field( 'installment_fee', array(
'type' => 'checkbox',
'class' => array('installment-fee form-row-wide'),
'label' => __('Support installation'),
'placeholder' => __(''),
), WC()->session->get('installment_fee') ? '1' : '' );
echo '</th><td>';
}
// jQuery - Ajax script
add_action( 'wp_footer', 'checkout_fee_script' );
function checkout_fee_script() {
// Only on Checkout
if( is_checkout() && ! is_wc_endpoint_url() ) :
if( WC()->session->__isset('installment_fee') )
WC()->session->__unset('installment_fee')
?>
<script type="text/javascript">
jQuery( function($){
if (typeof wc_checkout_params === 'undefined')
return false;
$('form.checkout').on('change', 'input[name=installment_fee]', function(){
var fee = $(this).prop('checked') === true ? '1' : '';
$.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: {
'action': 'installment_fee',
'installment_fee': fee,
},
success: function (result) {
$('body').trigger('update_checkout');
},
});
});
});
</script>
<?php
endif;
}
// Get Ajax request and saving to WC session
add_action( 'wp_ajax_installment_fee', 'get_installment_fee' );
add_action( 'wp_ajax_nopriv_installment_fee', 'get_installment_fee' );
function get_installment_fee() {
if ( isset($_POST['installment_fee']) ) {
WC()->session->set('installment_fee', ($_POST['installment_fee'] ? true : false) );
}
die();
}
// Add a custom calculated fee conditionally
add_action( 'woocommerce_cart_calculate_fees', 'set_installment_fee' );
function set_installment_fee( $cart ){
if ( is_admin() && ! defined('DOING_AJAX') || ! is_checkout() )
return;
if ( did_action('woocommerce_cart_calculate_fees') >= 2 )
return;
if ( 1 == WC()->session->get('installment_fee') ) {
$items_count = WC()->cart->get_cart_contents_count();
$fee_label = sprintf( __( "Support installation %s %s" ), '×', $items_count );
$fee_amount = 50000 * $items_count;
WC()->cart->add_fee( $fee_label, $fee_amount );
}
}
add_filter( 'woocommerce_form_field' , 'remove_optional_txt_from_installment_checkbox', 10, 4 );
function remove_optional_txt_from_installment_checkbox( $field, $key, $args, $value ) {
// Only on checkout page for Order notes field
if( 'installment_fee' === $key && is_checkout() ) {
$optional = ' <span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
$field = str_replace( $optional, '', $field );
}
return $field;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works on Woocommerce version 3.6.5 with Storefront theme.
I am trying to modify the code based on this question:
// Display the checkout field in cart page totals section
add_action( 'woocommerce_cart_totals_before_order_total', 'display_priority_fee_checkbox_field', 20 );
function display_priority_fee_checkbox_field(){
echo '<tr class="installment-section">
<th>'.__("Priority Dispatch").'</th><td>';
woocommerce_form_field( 'priority_fee', array(
'type' => 'checkbox',
'class' => array('form-row-wide'),
'label' => __(' $20.00'),
), WC()->session->get('priority_fee') ? '1' : '' );
echo '<div class="tooltip">?
<span class="tooltiptext">'.__("By selecting this option... ").'</span>
</div></td>';
}
// Remove "(optional)" text from the field
add_filter( 'woocommerce_form_field' , 'remove_optional_txt_from_priority_fee_checkbox', 10, 4 );
function remove_optional_txt_from_priority_fee_checkbox( $field, $key, $args, $value ) {
// Only on checkout page for Order notes field
if( 'priority_fee' === $key ) {
$optional = ' <span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
$field = str_replace( $optional, '', $field );
}
return $field;
}
// jQuery :: Ajax script
add_action( 'wp_footer', 'priority_fee_js_script' );
function priority_fee_js_script() {
// On Order received page, remove the wc session variable if it exist
if ( is_wc_endpoint_url('order-received')
&& WC()->session->__isset('priority_fee') ) :
WC()->session->__unset('priority_fee');
// On Cart page: jQuert script
elseif ( is_cart() ) :
?>
<script type="text/javascript">
jQuery( function($){
if (typeof woocommerce_params === 'undefined')
return false;
var c = 'input[name=priority_fee]';
$(document.body).on( 'click change', c, function(){
console.log('click');
var fee = $(c).is(':checked') ? '1' : '';
$.ajax({
type: 'POST',
url: woocommerce_params.ajax_url,
data: {
'action': 'priority_fee',
'priority_fee': fee,
},
success: function (response) {
setTimeout(function(){
$(document.body).trigger('added_to_cart');
}, 500);
},
});
});
});
</script>
<?php
endif;
}
// Get Ajax request and saving to WC session
add_action( 'wp_ajax_priority_fee', 'priority_fee_ajax_receiver' );
add_action( 'wp_ajax_nopriv_priority_fee', 'priority_fee_ajax_receiver' );
function priority_fee_ajax_receiver() {
if ( isset($_POST['priority_fee']) ) {
$priority_fee = $_POST['priority_fee'] ? true : false;
// Set to a WC Session variable
WC()->session->set('priority_fee', $priority_fee );
echo $priority_fee ? '1' : '0';
die();
}
}
// Add a custom calculated fee conditionally
add_action( 'woocommerce_cart_calculate_fees', 'set_priority_fee' );
function set_priority_fee( $cart ){
if ( is_admin() && ! defined('DOING_AJAX') )
return;
if ( WC()->session->get('priority_fee') ) {
$item_count = $cart->get_cart_contents_count();
$fee_label = 'Discount';
$fee_amount = -2;
$cart->add_fee( $fee_label, $fee_amount );
}
}
But the discount is not showing up. Also, I nneed the discount to be applied to the SUBTOTALS so that tax is recalculated as well (which the code does not do, it applies the discount after taxes).
How can I set a negative fee(discount) when checkbox is checked and also have the discount applied before tax calculation?
EDIT: Okay, I got it to work with the taxes by changing the last part:
// Set the discount
add_action( 'woocommerce_cart_calculate_fees', 'checkout_set_discount', 20, 1 );
function checkout_set_discount( $cart ) {
if ( ( is_admin() && ! defined('DOING_AJAX') ) )
return;
$subtotal = WC()->cart->get_subtotal();
$percentage = 1;
$discount = $subtotal * $percentage / 100;
if( WC()->session->get('priority_fee') ) {
$cart->add_fee( sprintf( __( 'Discount', 'woocommerce') ), -$discount );
}
}
but this only works with a percentage based discount. How can I instead use a fixed discount?
Based on Display a checkbox that add a fee in Woocommerce checkout page answer code I am trying to change usage to Cart page, rather than checkout page per clients request.
So far I managed to display custom fee check box on cart page and trigger Ajax.
However Cart totals are not updated.
If someone can help on code or point me in right direction?
// Display the custom checkbox field in cart
add_action( 'woocommerce_cart_totals_before_order_total', 'fee_installment_checkbox_field', 20 );
function fee_installment_checkbox_field(){
echo '<tr class="packing-select"><th>Priority Dispatch</th><td>';
woocommerce_form_field( 'priority_fee', array(
'type' => 'checkbox',
'class' => array('installment-fee form-row-wide'),
'label' => __(' $20.00'),
'placeholder' => __(''),
), WC()->session->get('priority_fee') ? '1' : '' );
echo '<div class="tooltip">?
<span class="tooltiptext">By selecting this option... </span>
</div></td>';
}
// jQuery - Ajax script
add_action( 'wp_footer', 'woo_add_cart_fee' );
function woo_add_cart_fee() {
// Only on Checkout
if( ! is_wc_endpoint_url() ) :
if( WC()->session->__isset('priority_fee') )
WC()->session->__unset('priority_fee')
?>
<script type="text/javascript">
jQuery( function($){
//if (typeof wc_add_to_cart_params === 'undefined')
// return false;
$('tr.packing-select').on('change', 'input[name=priority_fee]', function(){
console.log('tests');
var fee = $(this).prop('checked') === true ? '1' : '';
$.ajax({
type: 'POST',
//url: wc_add_to_cart_params.ajax_url,
data: {
'action': 'priority_fee',
'priority_fee': fee,
},
success: function (response) {
$('body').trigger('added_to_cart');
},
});
});
});
</script>
<?php
endif;
}
// Get Ajax request and saving to WC session
add_action( 'wp_ajax_priority_fee', 'get_priority_fee' );
add_action( 'wp_ajax_nopriv_priority_fee', 'get_priority_fee' );
function get_priority_fee() {
if ( isset($_POST['priority_fee']) ) {
WC()->session->set('priority_fee', ($_POST['priority_fee'] ? true : false) );
}
die();
}
// Add a custom calculated fee conditionally
add_action( 'woocommerce_cart_calculate_fees', 'set_priority_fee' );
function set_priority_fee( $cart ){
if ( is_admin() && ! defined('DOING_AJAX') )
return;
if ( did_action('woocommerce_cart_calculate_fees') >= 2 )
return;
if ( 1 == WC()->session->get('priority_fee') ) {
$items_count = WC()->cart->get_cart_contents_count();
$fee_label = sprintf( __( "PRIORITY DISPATCH %s %s" ), '×', $items_count );
$fee_amount = 20;
WC()->cart->add_fee( $fee_label, $fee_amount );
}
}
add_filter( 'woocommerce_form_field' , 'remove_optional_txt_from_installment_checkbox', 10, 4 );
function remove_optional_txt_from_installment_checkbox( $field, $key, $args, $value ) {
// Only on checkout page for Order notes field
if( 'priority_fee' === $key ) {
$optional = ' <span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
$field = str_replace( $optional, '', $field );
}
return $field;
}
Additionally is this the way this should be done, or is there an easier way to do it?
There are some mistakes in your code. Also, on cart page, jQuery events and Ajax behavior are a bit different, so it requires some changes:
// Display the checkout field in cart page totals section
add_action( 'woocommerce_cart_totals_before_order_total', 'display_priority_fee_checkbox_field', 20 );
function display_priority_fee_checkbox_field(){
echo '<tr class="installment-section">
<th>'.__("Priority Dispatch").'</th><td>';
woocommerce_form_field( 'priority_fee', array(
'type' => 'checkbox',
'class' => array('form-row-wide'),
'label' => __(' $20.00'),
), WC()->session->get('priority_fee') ? '1' : '' );
echo '<div class="tooltip">?
<span class="tooltiptext">'.__("By selecting this option... ").'</span>
</div></td>';
}
// Remove "(optional)" text from the field
add_filter( 'woocommerce_form_field' , 'remove_optional_txt_from_priority_fee_checkbox', 10, 4 );
function remove_optional_txt_from_priority_fee_checkbox( $field, $key, $args, $value ) {
// Only on checkout page for Order notes field
if( 'priority_fee' === $key ) {
$optional = ' <span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
$field = str_replace( $optional, '', $field );
}
return $field;
}
// jQuery :: Ajax script
add_action( 'wp_footer', 'priority_fee_js_script' );
function priority_fee_js_script() {
// On Order received page, remove the wc session variable if it exist
if ( is_wc_endpoint_url('order-received')
&& WC()->session->__isset('priority_fee') ) :
WC()->session->__unset('priority_fee');
// On Cart page: jQuert script
elseif ( is_cart() ) :
?>
<script type="text/javascript">
jQuery( function($){
if (typeof woocommerce_params === 'undefined')
return false;
var c = 'input[name=priority_fee]';
$(document.body).on( 'click change', c, function(){
console.log('click');
var fee = $(c).is(':checked') ? '1' : '';
$.ajax({
type: 'POST',
url: woocommerce_params.ajax_url,
data: {
'action': 'priority_fee',
'priority_fee': fee,
},
success: function (response) {
setTimeout(function(){
$(document.body).trigger('added_to_cart');
}, 500);
},
});
});
});
</script>
<?php
endif;
}
// Get Ajax request and saving to WC session
add_action( 'wp_ajax_priority_fee', 'priority_fee_ajax_receiver' );
add_action( 'wp_ajax_nopriv_priority_fee', 'priority_fee_ajax_receiver' );
function priority_fee_ajax_receiver() {
if ( isset($_POST['priority_fee']) ) {
$priority_fee = $_POST['priority_fee'] ? true : false;
// Set to a WC Session variable
WC()->session->set('priority_fee', $priority_fee );
echo $priority_fee ? '1' : '0';
die();
}
}
// Add a custom calculated fee conditionally
add_action( 'woocommerce_cart_calculate_fees', 'set_priority_fee' );
function set_priority_fee( $cart ){
if ( is_admin() && ! defined('DOING_AJAX') )
return;
if ( WC()->session->get('priority_fee') ) {
$item_count = $cart->get_cart_contents_count();
$fee_label = sprintf( __( "PRIORITY DISPATCH %s" ), '× ' . $item_count );
$fee_amount = 20 * $item_count;
$cart->add_fee( $fee_label, $fee_amount );
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
In Woocommerce checkout page, I'am trying to add a check box on checkout page
I have referred to these articles
woocommerce custom checkout field to add fee to order ajax
Checkbox field that add / remove a custom fee in WooCommerce
Add a checkout checkbox field that enable a percentage fee in Woocommerce
add_action( 'woocommerce_review_order_before_order_total', 'checkout_shipping_form_packing_addition', 20 );
function checkout_shipping_form_packing_addition( ){
echo '<tr class="packing-select"><th>';
woocommerce_form_field( 'add_gift_box', array(
'type' => 'checkbox',
'class' => array('add_gift_box form-row-wide'),
'label' => __('Hỗ trợ cài đặt'),
'placeholder' => __(''),
));
echo '</th><td>';}
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
}}
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'])) {
$sl = WC()->cart->get_cart_contents_count();
$extracost = 50000 * $sl; // not sure why you used intval($_POST['state']) ?
WC()->cart->add_fee( 'Hỗ trợ cài đặt x '.$sl.'', $extracost );
}}
add_filter( 'woocommerce_form_field' , 'remove_order_comments_optional_fields_label', 10, 4 );
function remove_order_comments_optional_fields_label( $field, $key, $args, $value ) {
// Only on checkout page for Order notes field
if( 'add_gift_box' === $key && is_checkout() ) {
$optional = ' <span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
$field = str_replace( $optional, '', $field );
}
return $field;
}
It does not work as I would like. What I am doing wrong?
Any help is appreciated.
You really need to use Wordpress Ajax with WC_sessions to make it work like in "Add a checkout checkbox field that enable a percentage fee in Woocommerce" answer thread.
Here is your revisited code:
// Display the custom checkbow field in checkout
add_action( 'woocommerce_review_order_before_order_total', 'fee_installment_checkbox_field', 20 );
function fee_installment_checkbox_field(){
echo '<tr class="packing-select"><th>';
woocommerce_form_field( 'installment_fee', array(
'type' => 'checkbox',
'class' => array('installment-fee form-row-wide'),
'label' => __('Support installation'),
'placeholder' => __(''),
), WC()->session->get('installment_fee') ? '1' : '' );
echo '</th><td>';
}
// jQuery - Ajax script
add_action( 'wp_footer', 'checkout_fee_script' );
function checkout_fee_script() {
// Only on Checkout
if( is_checkout() && ! is_wc_endpoint_url() ) :
if( WC()->session->__isset('installment_fee') )
WC()->session->__unset('installment_fee')
?>
<script type="text/javascript">
jQuery( function($){
if (typeof wc_checkout_params === 'undefined')
return false;
$('form.checkout').on('change', 'input[name=installment_fee]', function(){
var fee = $(this).prop('checked') === true ? '1' : '';
$.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: {
'action': 'installment_fee',
'installment_fee': fee,
},
success: function (result) {
$('body').trigger('update_checkout');
},
});
});
});
</script>
<?php
endif;
}
// Get Ajax request and saving to WC session
add_action( 'wp_ajax_installment_fee', 'get_installment_fee' );
add_action( 'wp_ajax_nopriv_installment_fee', 'get_installment_fee' );
function get_installment_fee() {
if ( isset($_POST['installment_fee']) ) {
WC()->session->set('installment_fee', ($_POST['installment_fee'] ? true : false) );
}
die();
}
// Add a custom calculated fee conditionally
add_action( 'woocommerce_cart_calculate_fees', 'set_installment_fee' );
function set_installment_fee( $cart ){
if ( is_admin() && ! defined('DOING_AJAX') || ! is_checkout() )
return;
if ( did_action('woocommerce_cart_calculate_fees') >= 2 )
return;
if ( 1 == WC()->session->get('installment_fee') ) {
$items_count = WC()->cart->get_cart_contents_count();
$fee_label = sprintf( __( "Support installation %s %s" ), '×', $items_count );
$fee_amount = 50000 * $items_count;
WC()->cart->add_fee( $fee_label, $fee_amount );
}
}
add_filter( 'woocommerce_form_field' , 'remove_optional_txt_from_installment_checkbox', 10, 4 );
function remove_optional_txt_from_installment_checkbox( $field, $key, $args, $value ) {
// Only on checkout page for Order notes field
if( 'installment_fee' === $key && is_checkout() ) {
$optional = ' <span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
$field = str_replace( $optional, '', $field );
}
return $field;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works on Woocommerce version 3.6.5 with Storefront theme.
looking for some help here
so my plan is to have the option to change the product in the checkout page with some radio boxes.
something that looks like this
I've been trying to change the code bellow that is original to add fees.
My goal would be to have the different products on the radio box or at least that it change the quantity.
/**
* #snippet Dynamic Radio Buttons Fees - WooCommerce Checkout
* #how-to Watch tutorial # https://businessbloomer.com/?p=19055
* #sourcecode https://businessbloomer.com/?p=79316
* #author Rodolfo Melogli
* #compatible WooCommerce 3.5.1
* #donate $9 https://businessbloomer.com/bloomer-armada/
*/
// Part 1
// Display Radio Buttons
// Uses woocommerce_form_field()
add_action( 'woocommerce_review_order_before_payment', 'bbloomer_checkout_radio_choice' );
function bbloomer_checkout_radio_choice() {
$chosen = WC()->session->get('radio_chosen');
$chosen = empty( $chosen ) ? WC()->checkout->get_value('radio_choice') : $chosen;
$chosen = empty( $chosen ) ? 'no_option' : $chosen;
$args = array(
'type' => 'radio',
'class' => array( 'form-row-wide' ),
'options' => array(
'no_option' => 'No Option',
'option_1' => 'Option 1 ($10)',
'option_2' => 'Option 2 ($30)',
),
'default' => $chosen
);
echo '<div id="checkout-radio">';
echo '<h3>Customize Your Order!</h3>';
woocommerce_form_field( 'radio_choice', $args, $chosen );
echo '</div>';
}
// Part 2
// Add Fee and Calculate Total
// Based on session's "radio_chosen"
#2 Calculate New Total
add_action( 'woocommerce_cart_calculate_fees', 'bbloomer_checkout_radio_choice_fee', 20, 1 );
function bbloomer_checkout_radio_choice_fee( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
$radio = WC()->session->get( 'radio_chosen' );
if ( "option_1" == $radio ) {
$fee = 10;
} elseif ( "option_2" == $radio ) {
$fee = 30;
}
$cart->add_fee( __('Option Fee', 'woocommerce'), $fee );
}
// Part 3
// Refresh Checkout if Radio Changes
// Uses jQuery
add_action( 'wp_footer', 'bbloomer_checkout_radio_choice_refresh' );
function bbloomer_checkout_radio_choice_refresh() {
if ( ! is_checkout() ) return;
?>
<script type="text/javascript">
jQuery( function($){
$('form.checkout').on('change', 'input[name=radio_choice]', function(e){
e.preventDefault();
var p = $(this).val();
$.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: {
'action': 'woo_get_ajax_data',
'radio': p,
},
success: function (result) {
$('body').trigger('update_checkout');
}
});
});
});
</script>
<?php
}
// Part 4
// Add Radio Choice to Session
// Uses Ajax
add_action( 'wp_ajax_woo_get_ajax_data', 'bbloomer_checkout_radio_choice_set_session' );
add_action( 'wp_ajax_nopriv_woo_get_ajax_data', 'bbloomer_checkout_radio_choice_set_session' );
function bbloomer_checkout_radio_choice_set_session() {
if ( isset($_POST['radio']) ){
$radio = sanitize_key( $_POST['radio'] );
WC()->session->set('radio_chosen', $radio );
echo json_encode( $radio );
}
die();
}
code source
You'll not use woocommerce_cart_calculate_fees in this case since you're not adding any fees but rather changing the quantity of the products available in user cart.
So assuming no_option means (1:default), option_1 will change quantity to 10, and option_2 will change quantity to 20, you'd change the function bbloomer_checkout_radio_choice_set_session() to look something like this:
function bbloomer_checkout_radio_choice_set_session() {
if ( isset($_POST['radio']) ){
$radio = sanitize_key( $_POST['radio'] );
$cart = WC()->cart;
$cart_content = $cart->cart_contents;
foreach ( $cart_content as $cart_item_key => $cart_item ) {
if( 'no_option' === $radio ){
$cart->set_quantity($cart_item_key, 1);
}elseif( 'option_1' === $radio ){
$cart->set_quantity($cart_item_key, 10);
}elseif( 'option_2' === $radio ){
$cart->set_quantity($cart_item_key, 20);
}
}
}
echo json_encode( $_POST['radio'] ) ;
die();
}
The above is just an example of how to manipulate the cart products quantity, you'd need change the options and the function to match your exact needs.