We see on ecommerce websites that with each payment method you choose while checking out, there is often a service charge or even a discount associated. It is also noteworthy that the service charge for Cash-on-Delivery is higher than that for alternative payment methods. This is to increase the chances of pre-payments. Pre-payments help to not just to reduce the risk of not getting paid by the customer, but also to ensure cashflow in the business. In case of no service fee associated with payment methods, there may be discounts offered when you choose to pay with methods other than Cash-on-Delivery.
You also may want to add discounts against certain payment methods depending on schemes or promotions that you may want to run. Discounts are attractive in general to customers, and help in increasing sales. In this post, we will show you the various ways you can add charges or discounts for different payment methods in WooCommerce and consequently reap benefits of the same.
Adding Percentage Discounts for different Payment methods via Code Snippets
You can achieve this by adding code snippets in the functions.php file of your child theme.
The code below adds a discount to the total amount when PayPal is chosen as the payment method on WooCommerce checkout page. By assigning a value to $percent, you can specify the percentage of discount you wish to apply on the desired payment method. The default payment methods in WooCommerce are Direct Bank Transfer (bacs), Check payments (cheque), Cash on Delivery (cod) and PayPal (paypal), with their ids mentioned in the brackets.
add_action( 'woocommerce_cart_calculate_fees','ts_add_discount', 20, 1 ); function ts_add_discount( $cart_object ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; // Mention the payment method e.g. cod, bacs, cheque or paypal $payment_method = 'paypal'; // The percentage to apply $percent = 2; // 2% $cart_total = $cart_object->subtotal_ex_tax; $chosen_payment_method = WC()->session->get('chosen_payment_method'); //Get the selected payment method if( $payment_method == $chosen_payment_method ){ $label_text = __( "PayPal Discount" ); // Calculating percentage $discount = number_format(($cart_total / 100) * $percent, 2); // Adding the discount $cart_object->add_fee( $label_text, -$discount, false ); } } add_action( 'woocommerce_review_order_before_payment', 'ts_refresh_payment_method' ); function ts_refresh_payment_method(){ // jQuery ?> <script type="text/javascript"> (function($){ $( 'form.checkout' ).on( 'change', 'input[name^="payment_method"]', function() { $('body').trigger('update_checkout'); }); })(jQuery); </script> <?php }
You will need two functions here- one to do the job of adding appropriate discounts or fees, and one to keep a tab on changes in selection of the payment method by the user, for which we use javascript. The woocommerce_cart_calculate_fees and woocommerce_review_order_before_payment hooks are used to add these two functions respectively.
The values that the payment methods have for Direct Bank Transfer, Cheque, Cash-on-Delivery and PayPal are bacs, cheque, cod and paypal respectively. The add_fee() function is an in-built method of the WC_Cart class in WooCommerce.
This will result in the discount amount getting deducted from the subtotal, and the total will thus be displayed:
With little modification, you can mention discounts for multiple payment methods in the same code snippet:
add_action( 'woocommerce_cart_calculate_fees','ts_add_discount', 20, 1 ); function ts_add_discount( $cart_object ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; $label_text=__(""); $percent=0; // Mention the payment method e.g. cod, bacs, cheque or paypal $cart_total = $cart_object->subtotal_ex_tax; $chosen_payment_method = WC()->session->get('chosen_payment_method'); //Get the selected payment method if( $chosen_payment_method == "paypal" ){ $label_text = __( "PayPal Discount" ); // The percentage to apply $percent = 2; // 2% } else if( $chosen_payment_method == "bacs"){ $label_text = __( "Direct Bank Transfer Discount" ); // The percentage to apply $percent = 3; // 3% } else if( $chosen_payment_method == "cheque"){ $label_text = __( "Cheque Payment Discount" ); // The percentage to apply $percent = 2; // 2% } else { $label_text = __( "Cash-on-Delivery Discount" ); // The percentage to apply $percent = 0; // 0% } // Calculating percentage $discount = number_format(($cart_total / 100) * $percent, 2); // Adding the discount $cart_object->add_fee( $label_text, -$discount, false ); } add_action( 'woocommerce_review_order_before_payment', 'ts_refresh_payment_method' ); function ts_refresh_payment_method(){ // jQuery ?> <script type="text/javascript"> (function($){ $( 'form.checkout' ).on( 'change', 'input[name^="payment_method"]', function() { $('body').trigger('update_checkout'); }); })(jQuery); </script> <?php }
Adding Flat Discount Amounts for different Payment methods via Code Snippets
Suppose you wish to mention an amount instead of a percentage. You can do it using the same snippet again, by eliminating the step where you calculate the percentage and accepting the discount amount as input based on each payment method:
add_action( 'woocommerce_cart_calculate_fees','ts_add_discount', 20, 1 ); function ts_add_discount( $cart_object ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; $label_text=__(""); $discount_amount=0; // Mention the payment method e.g. cod, bacs, cheque or paypal $cart_total = $cart_object->subtotal_ex_tax; $chosen_payment_method = WC()->session->get('chosen_payment_method'); //Get the selected payment method if( $chosen_payment_method == "paypal" ){ $label_text = __( "PayPal Discount" ); // The discount amount to apply $discount_amount = 200; } else if( $chosen_payment_method == "bacs"){ $label_text = __( "Direct Bank Transfer Discount" ); // The discount amount to apply $discount_amount = 150; } else if( $chosen_payment_method == "cheque"){ $label_text = __( "Cheque Payment Discount" ); // The discount amount to apply $discount_amount = 100; } else { $label_text = __( "Cash-on-Delivery Discount" ); // The discount amount to apply $discount_amount = 0; } // Adding the discount $cart_object->add_fee( $label_text, -$discount_amount, false ); } add_action( 'woocommerce_review_order_before_payment', 'ts_refresh_payment_method' ); function ts_refresh_payment_method(){ // jQuery ?> <script type="text/javascript"> (function($){ $( 'form.checkout' ).on( 'change', 'input[name^="payment_method"]', function() { $('body').trigger('update_checkout'); }); })(jQuery); </script> <?php }
To add a service charge, you simply have to change the sign of one of the arguments in the add_fee function from “-” to “+” or no sign at all which implies positive.
add_action( 'woocommerce_cart_calculate_fees','ts_add_discount', 20, 1 ); function ts_add_discount( $cart_object ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; $label_text=__(""); $service_charge=0; // Mention the payment method e.g. cod, bacs, cheque or paypal $cart_total = $cart_object->subtotal_ex_tax; $chosen_payment_method = WC()->session->get('chosen_payment_method'); //Get the selected payment method if( $chosen_payment_method == "paypal" ){ $label_text = __( "PayPal Service Charge" ); // The service charge to apply $service_charge=200; } else if( $chosen_payment_method == "bacs"){ $label_text = __( "Direct Bank Transfer Service Charge" ); // The service charge to apply $service_charge=100; } else if( $chosen_payment_method == "cheque"){ $label_text = __( "Cheque Payment Service Charge" ); // The service charge to apply $service_charge=150; } else { $label_text = __( "Cash-on-Delivery Service Charge" ); // The service charge to apply $service_charge=250; } // Adding the service charge $cart_object->add_fee( $label_text, $service_charge, false ); } add_action( 'woocommerce_review_order_before_payment', 'ts_refresh_payment_method' ); function ts_refresh_payment_method(){ // jQuery ?> <script type="text/javascript"> (function($){ $( 'form.checkout' ).on( 'change', 'input[name^="payment_method"]', function() { $('body').trigger('update_checkout'); }); })(jQuery); </script> <?php }
In this way, a service charge will be applied as per the selected payment method:
Adding Discounts for different Payment methods for logged in users only (via Code Snippets)
If you wish to offer these discounts only for logged in users (as requested through a comment on this post), you need to simply add a condition that checks for whether the user is logged in or not. This can be done by the function is_user_logged_in(). The code snippet below shows how you can add percentage discounts for a particular payment method for logged in users only.
add_action( 'woocommerce_cart_calculate_fees','ts_add_discount', 20, 1 ); function ts_add_discount( $cart_object ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; if (is_user_logged_in()){ // Mention the payment method e.g. cod, bacs, cheque or paypal $payment_method = 'paypal'; // The percentage to apply $percent = 2; // 2% $cart_total = $cart_object->subtotal_ex_tax; $chosen_payment_method = WC()->session->get('chosen_payment_method'); //Get the selected payment method if( $payment_method == $chosen_payment_method ){ $label_text = __( "PayPal Discount" ); // Calculating percentage $discount = number_format(($cart_total / 100) * $percent, 2); // Adding the discount $cart_object->add_fee( $label_text, -$discount, false ); } } } add_action( 'woocommerce_review_order_before_payment', 'ts_refresh_payment_method' ); function ts_refresh_payment_method(){ // jQuery ?> <script type="text/javascript"> (function($){ $( 'form.checkout' ).on( 'change', 'input[name^="payment_method"]', function() { $('body').trigger('update_checkout'); }); })(jQuery); </script> <?php }
You can use any of the code snippets in this post depending on your requirement. You need to simply add a condition- if (is_user_logged_in()) inside that code snippet if you want to restrict this to logged in users alone.
Adding Charges or Discounts for different Payment methods via Plugins
If you don’t want to add code snippets, there is an easy way out to achieve the same – plugins! There are both free and paid plugins that offer different features.
Payment Gateway Based Fees and Discounts for WooCommerce
This is a free plugin by us that lets you add fees, discounts, taxes etc. and even set the minimum and maximum cart amounts as the criteria for the same. You can even round the fee after applying the discount. And you can do all this with an easy-to-use interface accessible via the dashboard:- Discounts Per Payment Method for WooCommerce (Free)
This is a free plugin by WPCodelibrary that provides a simple interface inside your WordPress Dashboard to set discounts for the default payment methods provided by WooCommerce. It however does not have a feature to add service charges or fees.
- Payment Gateway Based Fees and Discounts for WooCommerce ($39)
This premium plugin by us comes with a whole set of features where you can add fees as well as discounts for different payment methods based on country, state, product category etc. Besides this, you can also apply taxes on the fees (excluding shipping charges) using the plugin. The interface is simple and user-friendly, and you can also apply different discounts and fees for individual products.
I use the PayU payment gateway that works in Latin America. PayU allows you to pay with credit cards (Visa, Mastercard and Amex) and also debit card.
I only wish to apply discount when selecting pay with Mastercard.
Is this possible?
Hi Eduardo,
This is not directly possible. You may have to check with PayU for this.
Hi! Excellent work! How to make this code active for logged in users only? Thakns for help
Hi Luke, thank you. I have added a section for you and updated this post. Please refer to the section titled “Adding Discounts for different Payment methods for logged in users only (via Code Snippets)”. You may add that condition to any of the code snippets depending on your requirement. Hope this is helpful.
Mam, How can we set the maximum discount amount limit? Like up to rs.500 or rs.200 etc…
And also how to exclude some product or category from above discount like wallet top-up etc…
Hello, Great Code, and thank you for share it, But about if the order is on the admin backend?
Thanks, this code is great allowing me the flexibility to do what I need.
But, I have one problem, the lin:
$(‘body’).trigger(‘update_checkout’);
does not update the discount information in the cart.
I have checked and the form change function is firing.
Any suggestions?
Hello,
Thank you for the great snippets. I noticed that your first example (with the 2% discount) seems to break once the discount is over $999. At that point, the discount goes to a very low number, like $1 or $2 depending on the order total. Do you have any idea how to resolve this issue?