Η αντικαταβολή παραμένει ένας από τους πιο «ακριβούς» τρόπους πληρωμής για ένα e-shop. Όχι τεχνικά, αλλά επιχειρησιακά. Γι’ αυτό και η ανάγκη για μια σταθερή έξτρα χρέωση είναι απόλυτα λογική.
Το WooCommerce δεν προσφέρει εγγενώς ρύθμιση για fees ανά τρόπο πληρωμής. Υπάρχουν plugins, αλλά για ένα απλό, σταθερό σενάριο, η χρήση plugin είναι συνήθως υπερβολή. Περισσότερο code surface, περισσότερα updates, περισσότερα σημεία αστοχίας.
Αντίθετα, ένα μικρό, σωστά τοποθετημένο snippet λύνει το πρόβλημα καθαρά. Το κρίσιμο σημείο, ειδικά το 2026, δεν είναι πώς προσθέτεις το fee, αλλά πότε και σε ποιο checkout.
Δύο checkouts, δύο διαφορετικές πραγματικότητες
Σήμερα στο WooCommerce συνυπάρχουν δύο checkout συστήματα:
- Classic checkout (shortcode)
Το παραδοσιακό checkout, βασισμένο σε PHP templates, jQuery και AJAX (update_checkout).
Είναι ακόμα το πιο διαδεδομένο, ειδικά σε custom themes. - Block checkout
Το νεότερο checkout των WooCommerce Blocks. Βασίζεται στο Store API, React state και server-side recalculations. Δεν λειτουργεί με τον ίδιο τρόπο, ούτε συγχρονίζεται πάντα άμεσα με το PHP session.
Η βασική, καθαρή λύση (χωρίς εξαιρέσεις)
Ας ξεκινήσουμε από το απλό και σωστό: προσθέτουμε έξτρα χρέωση μόνο όταν ο χρήστης έχει επιλέξει αντικαταβολή. Χωρίς local pickup. Χωρίς edge cases. Χωρίς plugins.
/**
* WooCommerce - Add a flat Cash on Delivery (COD) fee
* Works with both classic shortcode checkout and Block checkout.
*/
add_action( 'woocommerce_cart_calculate_fees', function( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
return;
}
if ( ! WC()->session || ! $cart ) {
return;
}
$cod_fee = 3; // Set your fee amount here.
// Primary source: WooCommerce session
$chosen_payment_method = WC()->session->get( 'chosen_payment_method' );
// Fallback for cases where session is not yet synced (common during checkout updates)
if ( $chosen_payment_method !== 'cod' ) {
if ( isset( $_POST['payment_method'] ) ) {
$chosen_payment_method = sanitize_text_field( wp_unslash( $_POST['payment_method'] ) );
} elseif ( isset( $_REQUEST['payment_method'] ) ) {
$chosen_payment_method = sanitize_text_field( wp_unslash( $_REQUEST['payment_method'] ) );
}
}
if ( $chosen_payment_method !== 'cod' ) {
return;
}
// Prevent duplicate fees on recalculation
foreach ( $cart->get_fees() as $fee ) {
if ( isset( $fee->id ) && $fee->id === 'cod_fee' ) {
return;
}
}
$cart->add_fee(
__( 'Αντικαταβολή', 'woocommerce' ),
$cod_fee,
false,
'cod_fee'
);
}, 20 );
Αυτό το snippet:
- δουλεύει στο shortcode checkout
- δουλεύει στο Block checkout
- δεν προσθέτει διπλά fees
Classic checkout: γιατί μερικές φορές δεν ανανεώνεται το fee
Στο κλασικό checkout, το WooCommerce θεωρητικά κάνει refresh τα totals όταν αλλάζει payment method. Το core script ακούει το change event και καλεί update_checkout.
Στην πράξη όμως:
- themes αφαιρούν ή καθυστερούν scripts
- custom checkout templates χάνουν events
- JS errors μπλοκάρουν listeners
- optimizations σπάνε το flow
Εαν δε εμφανίζεται το fee αρκεί να προσθέσουμε το παρακάτω
/**
* Force checkout refresh when payment method changes (classic checkout).
*/
add_action( 'wp_footer', function () {
if ( ! is_checkout() || is_wc_endpoint_url( 'order-received' ) ) {
return;
}
?>
<script>
(function($){
if (!window.jQuery) return;
$(document.body).on('change', 'input[name="payment_method"]', function () {
$(document.body).trigger('update_checkout');
});
})(jQuery);
</script>
<?php
}, 20 );
Block checkout: διαφορετικό μοντέλο, διαφορετική σκέψη
Στο Block checkout δεν υπάρχει update_checkout όπως το ξέρουμε. Η ανανέωση γίνεται αυτόματα μέσω Store API και state updates.