Add Fee Based on Specific Payment Methods in Woocommerce

Add fee based on specific payment methods in WooCommerce

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.

Sample Image


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

Add fee based on payment methods and cart items total in WooCommerce

You can't delete fees added by a plugin based on cart items total mount.

As your plugin doesn't handle a min or max cart amount condition, disable the fees first from it (or disable the plugin) and use instead the following:

add_action( 'woocommerce_cart_calculate_fees', 'fee_based_on_payment_method_and_total' );
function fee_based_on_payment_method_and_total( $cart ) {
if ( is_admin() && ! defined('DOING_AJAX') )
return;

$threshold_amount = 300; // Total amount to reach for no fees

$payment_method_id = WC()->session->get('chosen_payment_method');
$cart_items_total = $cart->get_cart_contents_total();

if ( $cart_items_total < $threshold_amount ) {
// For cash on delivery "COD"
if ( $payment_method_id === 'cod' ) {
$fee = 14.99;
$text = __("Fee");
}
// For credit cards (other payment gateways than "COD", "BACS" or "CHEQUE"
elseif ( ! in_array( $payment_method_id, ['bacs', 'cheque'] ) ) {
$fee = 19.99;
$text = __("Fee");
}
}

if( isset($fee) && $fee > 0 ) {
$cart->add_fee( $text, $fee, false ); // To make fee taxable change "false" to "true"
}
}

And the following code to refresh data on payment method change:

// jQuery - Update checkout on payment method change
add_action( 'wp_footer', 'custom_checkout_jquery_script' );
function custom_checkout_jquery_script() {
if ( is_checkout() && ! is_wc_endpoint_url() ) :
?>
<script type="text/javascript">
jQuery( function($){
$('form.checkout').on('change', 'input[name="payment_method"]', function(){
$(document.body).trigger('update_checkout');
});
});
</script>
<?php
endif;
}

Code goes in functions.php file of the active child theme (or active theme). Tested and works.

related: Add fee based on specific payment methods in WooCommerce

Add a fee based on chosen payment gateways and user roles

Maybe what you need is to find out the payment method id(s) enabled for mercado pago.

The following code will display on checkout page for administrators the payment ID(s) on checkout available payment methods nearby the payment method title:

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).

Sample Image

Once you found the related payment method id(s) you are looking for, remove this code.


I have revisited Check WooCommerce User Role and Payment Gateway and if they match - Apply fee answer code, handling multiple payment ids:

add_action( 'woocommerce_cart_calculate_fees', 'add_custom_fee' );
function add_custom_fee( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;

if ( ! is_user_logged_in() )
return;

## SETTINGS:
$user_roles = array( 'vendor', 'administrator' ); // Defined user roles
// Targeted payment method Ids
$payment_ids = array('cod', 'paypal');
$percentage = 5; // Fee percentage

$user = wp_get_current_user(); // Get current WP_User Object
$chosen_payment = WC()->session->get('chosen_payment_method'); // Choosen payment method
$cart_subtotal = $cart->subtotal; // Including taxes - to exclude taxes use $cart->get_subtotal()

// For matched payment Ids and user roles
if ( in_array( $chosen_payment, $payment_ids ) && array_intersect( $user->roles, $user_roles ) ) {
$fee_cost = $percentage * $cart_subtotal / 100; // Calculation
$cart->add_fee( __('Payment Fee'), $fee_cost, true ); // Add fee (incl taxes)
}
}

Now something was missing: The following that will refresh checkout on payment method choice:

// jQuery - Update checkout on payment method change
add_action( 'wp_footer', 'custom_checkout_jquery_script' );
function custom_checkout_jquery_script() {
if ( is_checkout() && ! is_wc_endpoint_url() ) :
?>
<script type="text/javascript">
jQuery( function($){
$('form.checkout').on('change', 'input[name="payment_method"]', function(){
$(document.body).trigger('update_checkout');
});
});
</script>
<?php
endif;
}

Code goes in functions.php file of your active child theme (or active theme). Tested and works.

Apparently Mercado pago payment plugin doesn't accept Fees.

Similar: Add fee based on specific payment methods in WooCommerce

Assign a percentage fee to WooCommerce payment methods based on user roles

You could also array_intersect() to check user roles, use IF / ELSE statements, instead of only multiple IF statements and optimize and compact the code as follows:

add_action('woocommerce_cart_calculate_fees', 'sm_credit_card_fee_role_gateway' );
function sm_credit_card_fee_role_gateway( $cart ){
if ( is_admin() && !defined('DOING_AJAX') )
return;

// Only on checkout page and logged in users
if ( ! ( is_checkout() && ! is_wc_endpoint_url() ) || ! is_user_logged_in() )
return;

$wpuser_object = wp_get_current_user();
$allowed_roles = array('administrator', 'default_wholesaler', 'wholesaler-non-vat-registered', 'shop_manager');

if ( array_intersect($allowed_roles, $wpuser_object->roles) ){
$payment_method = WC()->session->get('chosen_payment_method');

if ( 'cardgatecreditcard' === $payment_method ){
$percentage = 8.5;
}
elseif ( 'cardgateideal' === $payment_method ){
$percentage = 2;
}
elseif ( 'cardgategiropay' === $payment_method ){
$percentage = 3;
}
}
if ( isset($percentage) ) {
$surcharge = ($cart->cart_contents_total + $cart->shipping_total) * $percentage / 100;
$cart->add_fee( sprintf( __('Card Fee (%s)', 'woocommerce'), $percentage . '%' ), $surcharge, true );
}
}

Also something is missing to allow refresh checkout on payment gateway change:

// jQuery - Update checkout on payment method change
add_action( 'wp_footer', 'custom_checkout_jquery_script' );
function custom_checkout_jquery_script() {
if ( ( is_checkout() && ! is_wc_endpoint_url() ) && is_user_logged_in() ) :
?>
<script type="text/javascript">
jQuery( function($){
$('form.checkout').on('change', 'input[name="payment_method"]', function(){
$(document.body).trigger('update_checkout');
});
});
</script>
<?php
endif;
}

Code goes in functions.php file of the active child theme (or active theme). Tested and works.


Related: Add fee based on specific payment methods in WooCommerce

Add a custom fee for a specific payment gateway in Woocommerce

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.

Extra fee based on user ID, user role and payment method in WooCommerce checkout

Some comments/suggestions regarding your code attempt/question

  • The use of global $woocommerce; is not necessary, since $cart is passed to the callback function
  • You can group the conditions but also list them 1 by 1 for clarity.
    It is certainly not necessary to repeat the same conditions several times
  • But the most important, given the chosen payment method. In WooCommerce checkout when choosing a payment method, checkout totals are not refreshed. So something additional is required to refresh checkout "order review" section

So you get:

function action_woocommerce_cart_calculate_fees( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;

// 1. Only for 'b2bcustomer' user role
if ( ! current_user_can( 'b2bcustomer' ) ) return;

// 2. Exclude certain user ID
if ( get_current_user_id() == 1083 ) return;

// 3. Only for 'cod' payment method
if ( WC()->session->get( 'chosen_payment_method' ) != 'cod' ) return;

// Fee
$surcharge = 10;

// Applying
$cart->add_fee( __( 'B2B processing cost', 'woocommerce' ), $surcharge, true, '' );
}
add_action( 'woocommerce_cart_calculate_fees', 'action_woocommerce_cart_calculate_fees', 10, 1 );

// jQuery - Update checkout on method payment change
function action_wp_footer() {
if ( is_checkout() && ! is_wc_endpoint_url() ) :
?>
<script type="text/javascript">
jQuery( function($){
$( 'form.checkout' ).on( 'change', 'input[name="payment_method"]', function() {
$( document.body ).trigger( 'update_checkout' );
});
});
</script>
<?php
endif;
}
add_action( 'wp_footer', 'action_wp_footer' );

Add a fee based on chosen shipping method in WooCommerce

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.

Add a fee based on shipping method and payment method in Woocommerce

There is a mistake in your code and some additional code is needed. Try the following code that will add a specific fee when chosen payment method is Cash on delivery (cod) and when chosen shipping methods is "Free shipping":

// 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;

## ------ Your Settings (below) ------ ##
$your_payment_id = 'cod'; // The payment method
$your_shipping_method = 'free_shipping'; // The shipping method
$fee_amount = 19; // The fee amount
## ----------------------------------- ##

$chosen_payment_method_id = WC()->session->get( 'chosen_payment_method' );
$chosen_shipping_method_id = WC()->session->get( 'chosen_shipping_methods' )[0];
$chosen_shipping_method = explode( ':', $chosen_shipping_method_id )[0];

if ( $chosen_shipping_method == $your_shipping_method
&& $chosen_payment_method_id == $your_payment_id ) {
$fee_text = __( "Spese per pagamento alla consegna", "woocommerce" );
$cart->add_fee( $fee_text, $fee_amount, false );
}
}

// 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', 'input[name="payment_method"]', function(){
// Refresh checkout
$('body').trigger('update_checkout');
});
})
</script>
<?php
endif;
}

Code goes in functions.php file of your active child theme (or active theme). tested and works.

add fee not work in payment price in woocommerce checkout

Finally i solved the problem.
When we click in place order button, new ajax request sends with another posted data (custom data send directly as post data not post_data param).
And i set a condition to it and solved:

add_action( 'woocommerce_cart_calculate_fees', 'prefix_add_discount_line' );
function prefix_add_discount_line( $cart )
{
if(isset($_POST['post_data']))
{
parse_str($_POST['post_data'], $posted_data);
if( isset($posted_data['isWallet']) )
{
WC()->cart->add_fee( 'wallet', -$posted_data['walletUsed'] );
}
}

if(isset($_POST['isWallet']))
{
WC()->cart->add_fee( 'wallet', -$_POST['walletUsed'] );
}
}


Related Topics



Leave a reply



Submit