Conditionally adding a cart fee if no coupons are applied to cart - php

In WooCommerce, I am trying to figured out how to add a "Handling Fee" to every order when no coupons or promo codes are applied to cart.
Here's my "Fee" or "Handling Charge" code:
add_action( 'woocommerce_cart_calculate_fees','endo_handling_fee' );
function endo_handling_fee() {
global $woocommerce;
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$fee = 2.00;
$woocommerce->cart->add_fee( 'Handling', $fee, true, 'standard' );
}
Any ideas?
Thanks

Here I get the array of cart applied coupons and if there is no coupons applied to cart, then a fee is applied to cart.
Here is that code:
add_action( 'woocommerce_cart_calculate_fees','conditional_handling_fee' );
function conditional_handling_fee() {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Get the applied coupons + the count (in cart)
$applied_coupons_arr = WC()->cart->get_applied_coupons();
$applied_coupons_count = count($applied_coupons_arr);
$fee = 2.00;
if( 0 == $applied_coupons_count )
WC()->cart->add_fee( 'Handling - '.$applied_coupons_count, $fee, true, 'standard' );
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested and works.
Reference: WC_Cart class - get_applied_coupons() method

Related

Add a fee based on chosen shipping method in WooCommerce

In WooCommerce, I need to add a fee when user select specific shipping methods.
I have found "Add a fee based on shipping method and payment method in Woocommerce" answer, that looks like what I need.
I have tried the code and removed the pieces about payment method which I don't need.
The problem is that when I change the shipping method the fee is not added, looks like that I just keep the old value in the session.
This is my code:
// Add a conditional fee
add_action( 'woocommerce_cart_calculate_fees', 'add_cod_fee', 20, 1 );
function add_cod_fee( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$chosen_shipping_method_id = WC()->session->get( 'chosen_shipping_methods' )[0];
var_dump($chosen_shipping_method_id); die;
switch($chosen_shipping_method_id){
case 'flat_rate:3': {
$fee_text = __( "Spese per ritiro", "woocommerce" );
$cart->add_fee( $fee_text, 12, false );
break;
}
case 'flat_rate:4': {
$fee_text = __( "Spese per consegna a domicilio", "woocommerce" );
$cart->add_fee( $fee_text, 24, false );
break;
}
}
}
// Refresh checkout on payment method change
add_action( 'wp_footer', 'refresh_checkout_script' );
function refresh_checkout_script() {
// Only on checkout page
if( is_checkout() && ! is_wc_endpoint_url('order-received') ) :
?>
<script type="text/javascript">
jQuery(function($){
// On payment method change
$('form.woocommerce-checkout').on( 'change', '.shipping_method', function(){
// Refresh checkout
$('body').trigger('update_checkout');
});
})
</script>
<?php
endif;
}
It just keep the old value in $chosen_shipping_method_id
Your code works nicely if you comment var_dump($chosen_shipping_method_id); die;. Also the jQuery script is not needed as it was for payment methods that doesn't update checkout by default.
So there is something else that is making trouble in your case.
Now I have revisited a bit your code (it will work too):
// Add a conditional fee
add_action( 'woocommerce_cart_calculate_fees', 'flat_rate_based_fee', 20, 1 );
function flat_rate_based_fee( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' );
if( in_array( 'flat_rate:3', $chosen_shipping_methods ) ) {
$fee = array( 'text' => __( "Spese per ritiro", "woocommerce" ), 'amount' => 12 );
} elseif ( in_array( 'flat_rate:4', $chosen_shipping_methods ) ) {
$fee = array( 'text' => __( "Spese per consegna a domicilio", "woocommerce" ), 'amount' => 24 );
}
if( isset($fee) ) {
$cart->add_fee( $fee['text'], $fee['amount'], false );
}
}
Code goes in functions.php file of your active child theme (or active theme).
Tested and work (on Woocommerce 3.5.x and 3.6.x). See it working live on this test server.

Extra fee on WooCommerce checkout page not added to subtotal

I need to add Handling fee in checkout page for some state. For this I am using woocommerce add_fee option. But my problem is on checkout page the handling fee is showing but not add to subtotal. Here is my code
add_action( 'woocommerce_cart_calculate_fees','xa_custom_surcharge' );
function xa_custom_surcharge() {
global $woocommerce;
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$state= array('MH');
$surcharge = 10;
if ( in_array( WC()->customer->shipping_state, $state ) ) {
$woocommerce->cart->add_fee( 'Additional Charge', $surcharge, true, '' );
}
}
Can anyone please help me.
Your code is outdated since WooCommerce 3:
Properties can't not be accessed anymore on CRUD objects, so you should use instead methods like get_shipping_state() in your case.
global $woocommerce and $woocommerce->cart are outdated & replaced directly by WC()->cart
The WC_Cart Object $cart variable is available in the hooked function as an argument.
The correct code is:
add_action( 'woocommerce_cart_calculate_fees','add_custom_surcharge', 10, 1 );
function add_custom_surcharge( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$state = array('MH');
$surcharge = 10;
if ( in_array( WC()->customer->get_shipping_state(), $state ) ) {
$cart->add_fee( 'Additional Charge', $surcharge, true );
}
}
Now when using the Fee API, the fee amount is displayed as a total and added to gran total at the end, but NOT to the subtotal:
The subtotal in WooCommerce is made only from cart items subtotals…

Percentage discount based on user role and payment method in Woocommerce

I was trying to make a code snippet for functions.php which would apply a discount of 2 % for cart totals when the role "subscriber" and the payment method "credit-card" are both selected. My progress so far
function discount_when_role_and_payment(/* magic */) {
global $woocommerce;
if ( /* credit-card selected */ && current_user_can('subscriber') ) {
/* get woocommerce cart totals, apply 2% discount and return*/
}
return /*cart totals after discount*/;
}
add_filter( '/* magic */', 'discount_when_role_and_payment' );
Could anyone help complete this? Or atleast point to the right direction?
The following code will apply a discount of 2% to cart when a targeted payment method has been selected by a subscriber user role only on checkout page:
// Applying conditionally a discount
add_action( 'woocommerce_cart_calculate_fees', 'discount_based_on_user_role_and_payment', 20, 1 );
function discount_based_on_user_role_and_payment( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return; // Exit
// Only on checkout page for 'subscriber' user role
if ( ! ( is_checkout() && current_user_can('subscriber') ) )
return; // Exit
// HERE Below define in the array your targeted payment methods IDs
$targeted_payment_methods = array( 'paypal', 'stripe' );
// HERE define the percentage discount
$percentage = 2;
if( in_array( WC()->session->get('chosen_payment_method'), $targeted_payment_methods ) ){
// Calculation
$discount = $cart->get_subtotal() * $percentage / 100;
// Applying discount
$cart->add_fee( sprintf( __("Discount (%s)", "woocommerce"), $percentage . '%'), -$discount, true );
}
}
// Refreshing totals on choseen payment method change event
add_action( 'woocommerce_review_order_before_payment', 'refresh_payment_methods' );
function refresh_payment_methods(){
// Only on checkout page
if ( ! ( is_checkout() && current_user_can('subscriber') ) ) return;
// jQuery code
?>
<script type="text/javascript">
(function($){
$( 'form.checkout' ).on( 'change', 'input[name^="payment_method"]', function() {
$('body').trigger('update_checkout');
});
})(jQuery);
</script>
<?php
}
This code goes on function.php file of your active child theme (or active theme). tested and works.
To get the correct desired Payment methods IDs, you will have to inspect the html code around the payment methods radio buttons searching with your browser inspector tools:

Add a custom fee for a specific payment gateway in Woocommerce

How can I add a percentage to the total amount when choosing a payment (credit card)?
For example: If the customer pays for cash on delivery, then the base price, and if I chose online payment, then the percentage charged by me is added to the total amount?
Gateway ID for cash payment on delivery is set out: cod
Gateway ID for online payment is set out: tinkoff
add_action( 'woocommerce_after_calculate_totals', 'custom_fee_for_tinkoff' );
function custom_fee_for_tinkoff( $cart ) {
if ( is_checkout() || defined('WOOCOMMERCE_CHECKOUT') ) {
$payment_method = WC()->session->get( 'chosen_payment_method' );
if ($payment_method == 'tinkoff') {
$percentage = 0.025;
$surcharge = ( $cart->cart_contents_total + $cart->tax_total ) * $percentage;
$cart->add_fee( 'Комиссия банка', $surcharge, true, '' );
}
else { return; }
}
}
Image with problem
Try the following revisited code instead that should do the trick:
// Add a custom fee based o cart subtotal
add_action( 'woocommerce_cart_calculate_fees', 'custom_fee_for_tinkoff', 20, 1 );
function custom_fee_for_tinkoff ( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( ! ( is_checkout() && ! is_wc_endpoint_url() ) )
return; // Only checkout page
$payment_method = WC()->session->get( 'chosen_payment_method' );
if ( 'tinkoff' == $payment_method ) {
$surcharge = $cart->subtotal * 0.025;
$cart->add_fee( 'Комиссия банка', $surcharge, true );
}
}
// jQuery - Update checkout on methode payment change
add_action( 'wp_footer', 'custom_checkout_jqscript' );
function custom_checkout_jqscript() {
if ( ! ( is_checkout() && ! is_wc_endpoint_url() ) )
return; // Only checkout page
?>
<script type="text/javascript">
jQuery( function($){
$('form.checkout').on('change', 'input[name="payment_method"]', function(){
$(document.body).trigger('update_checkout');
});
});
</script>
<?php
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.

Add fee based on specific payment methods in WooCommerce

In WooCommerce I need to apply a custom handling fee for a specific payment gateway. I have this piece of code from here: How to Add Handling Fee to WooCommerce Checkout.
This is my code:
add_action( 'woocommerce_cart_calculate_fees','endo_handling_fee' );
function endo_handling_fee() {
global $woocommerce;
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$fee = 5.00;
$woocommerce->cart->add_fee( 'Handling', $fee, true, 'standard' );
}
This function add a fee to all transactions.
Is it possible to tweak this function and make it apply for specific payment method only ?
The other problem is that I want this fee to be applied on cart. Is it possible?
I will welcome any alternative method as well. I know about the similar "Payment Gateway Based Fees" woo plugin, but I can't afford it.
2021 UPDATE
Note: All payment methods are only available on Checkout page.
The following code will add conditionally a specific fee based on the chosen payment method:
// Add a custom fee (fixed or based cart subtotal percentage) by payment
add_action( 'woocommerce_cart_calculate_fees', 'custom_handling_fee' );
function custom_handling_fee ( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$chosen_payment_id = WC()->session->get('chosen_payment_method');
if ( empty( $chosen_payment_id ) )
return;
$subtotal = $cart->subtotal;
// SETTINGS: Here set in the array the (payment Id) / (fee cost) pairs
$targeted_payment_ids = array(
'cod' => 8, // Fixed fee
'paypal' => 5 * $subtotal / 100, // Percentage fee
);
// Loop through defined payment Ids array
foreach ( $targeted_payment_ids as $payment_id => $fee_cost ) {
if ( $chosen_payment_id === $payment_id ) {
$cart->add_fee( __('Handling fee', 'woocommerce'), $fee_cost, true );
}
}
}
You will need the following to refresh checkout on payment method change, to get it work:
// jQuery - Update checkout on payment method change
add_action( 'woocommerce_checkout_init', 'payment_methods_refresh_checkout' );
function payment_methods_refresh_checkout() {
wc_enqueue_js( "jQuery( function($){
$('form.checkout').on('change', 'input[name=payment_method]', function(){
$(document.body).trigger('update_checkout');
});
});");
}
Code goes in functions.php file of your active child theme (or active theme). tested and works.
How to find a specific payment method ID in WooCommerce Checkout page?
The following will display on checkout payment methods the payment Id just for admins:
add_filter( 'woocommerce_gateway_title', 'display_payment_method_id_for_admins_on_checkout', 100, 2 );
function display_payment_method_id_for_admins_on_checkout( $title, $payment_id ){
if( is_checkout() && ( current_user_can( 'administrator') || current_user_can( 'shop_manager') ) ) {
$title .= ' <code style="border:solid 1px #ccc;padding:2px 5px;color:red;">' . $payment_id . '</code>';
}
return $title;
}
Code goes in functions.php file of your active child theme (or active theme). Once used, remove it.
Similar answer:
Add a custom fee for a specific payment gateway in Woocommerce
Add a fee based on shipping method and payment method in Woocommerce
Percentage discount based on user role and payment method in Woocommerce
First of all there are some key things we need to understand:
We are going to use the only filter hook which is woocommerce_cart_calculate_fees
In order to get user selected payment method we must retrieve it from user sessions using this method WC()->session->get( 'chosen_payment_method' )
calculate_fees() and calculate_totals() methods are not necessary.
We are going to add the fee using cart method WC()->cart->add_fee() which accepts two parameters – the first one, is the fee description, the second one – fee amount.
And one more thing – we will need a payment method slug, the easiest way to get it described in this tutorial https://rudrastyh.com/woocommerce/add-id-column-to-payment-methods-table.html
Let's go now:
add_action( 'woocommerce_cart_calculate_fees', 'rudr_paypal_fee', 25 );
function rudr_paypal_fee() {
if( 'paypal' == WC()->session->get( 'chosen_payment_method' ) ) {
WC()->cart->add_fee( 'PayPal fee', 2 ); // let's add a fee for paypal
}
}
It would be also great to refresh the checkout every time payment gateway is changed, it is easy to do using this code:
jQuery( function( $ ) {
$( 'form.checkout' ).on( 'change', 'input[name^="payment_method"]', function() {
$( 'body' ).trigger( 'update_checkout' );
});
});
That's it. Everything is described in details here as well: https://rudrastyh.com/woocommerce/charge-additional-fees-based-on-payment-gateway.html
For anyone else looking to do this, I wanted to add a fee for Bank Transfers (BACS), here is the method I used:
//Hook the order creation since it is called during the checkout process:
add_filter('woocommerce_create_order', 'my_handle_bacs', 10, 2);
function my_handle_bacs($order_id, $checkout){
//Get the payment method from the $_POST
$payment_method = isset( $_POST['payment_method'] ) ? wc_clean( $_POST['payment_method'] ) : '';
//Make sure it's the right payment method
if($payment_method == "bacs"){
//Use the cart API to add recalculate fees and totals, and hook the action to add our fee
add_action('woocommerce_cart_calculate_fees', 'my_add_bacs_fee');
WC()->cart->calculate_fees();
WC()->cart->calculate_totals();
}
//This filter is for creating your own orders, we don't want to do that so return the $order_id untouched
return $order_id;
}
function my_add_bacs_fee($cart){
//Add the appropriate fee to the cart
$cart->add_fee("Bank Transfer Fee", 40);
}
add_action( 'woocommerce_cart_calculate_fees','cod_fee' );
function cod_fee() {
global $woocommerce;
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// get your payment method
$chosen_gateway = WC()->session->chosen_payment_method;
//echo $chosen_gateway;
$fee = 5;
if ( $chosen_gateway == 'cod' ) { //test with cash on delivery method
WC()->cart->add_fee( 'delivery fee', $fee, false, '' );
}
}

Categories