Диагностика задачи: зачем менять стоимость оплаты по способу оплаты
По умолчанию WooCommerce не предоставляет возможности динамически менять стоимость платежа в зависимости от выбранного способа оплаты. Однако в ряде случаев это необходимо: например, добавить комиссию за оплату через определённый платежный шлюз или, наоборот, предоставить скидку при использовании определённого метода.
В типовой настройке WooCommerce можно задать фиксированные комиссии через плагины, но для более гибкой логики потребуется кастомный код.
Как работает изменение стоимости оплаты в WooCommerce
WooCommerce позволяет изменять итоговую сумму заказа через фильтр woocommerce_cart_calculate_fees. Используя этот хук, можно добавлять дополнительные сборы или скидки.
Для определения выбранного способа оплаты в админке и на странице оформления заказа применяется WC()->session->get('chosen_payment_method'). На этом основании и строим условие для добавления или изменения комиссии.
Пошаговое решение: добавление комиссии на выбранный способ оплаты
add_action('woocommerce_cart_calculate_fees', 'custom_payment_gateway_fee', 20, 1);function custom_payment_gateway_fee( $cart ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; // Получаем выбранный способ оплаты $chosen_gateway = WC()->session->get('chosen_payment_method'); if ( ! $chosen_gateway ) return; // Пример: добавить комиссию 5% при оплате через 'cod' (наложенный платеж) if ( 'cod' === $chosen_gateway ) { $percentage = 0.05; $fee = $cart->subtotal * $percentage; $cart->add_fee( 'Комиссия за наложенный платёж', $fee, true ); }};Обратите внимание, что комиссия рассчитывается от $cart->subtotal, а третий параметр true указывает, что комиссия облагается налогом.
Как проверить, что решение сработало
- Откройте страницу оформления заказа (checkout).
- Выберите способ оплаты «Наложенный платеж» (cash on delivery).
- Убедитесь, что в итоговой сумме появилась дополнительная строка «Комиссия за наложенный платёж» с правильной суммой.
- Попробуйте сменить способ оплаты — комиссия должна исчезнуть или измениться.
Частые ошибки и как их исправить
- Отсутствие выбранного способа оплаты в сессии: если
WC()->session->get('chosen_payment_method')возвращает пустое значение, комиссия не добавится. Проверьте, что сессия инициализирована, а способ оплаты выбран. - Комиссия не отображается на фронтенде: возможно, код добавлен не в functions.php активной темы или используется кэширование. Очистите кэш и проверьте логи.
- Неверный расчет комиссии: убедитесь, что используете правильное свойство корзины (
$cart->subtotalили$cart->total) в зависимости от задачи. - Комиссия дублируется после обновления страницы: проверьте, что код не вызывается несколько раз, особенно если используется AJAX на странице оформления заказа.
Практические советы по безопасности и производительности
- Не используйте фиксированные комиссии в коде без возможности настройки через админку — добавьте опцию в
wp_optionsдля удобства изменения. - Добавляйте комиссию только на фронтенде, исключая административные запросы, чтобы избежать искажений данных.
- Проверяйте совместимость с кеширующими плагинами и AJAX-обновлением корзины, чтобы комиссия корректно отображалась.
- При большом количестве условий лучше использовать отдельный класс или отдельный плагин, чтобы не засорять functions.php.
Сравнение способов реализации комиссии по способу оплаты
| Способ | Плюсы | Минусы | Пример |
|---|---|---|---|
| Код в functions.php | Быстро, гибко | Сложно поддерживать, требует навыков | Пример выше |
| Плагин WooCommerce Payment Fees | Удобный UI, без кода | Может влиять на производительность, платные функции | ссылка |
| Кастомный плагин | Чистый код, масштабируемость | Требует разработки | Разработка под проект |
Дополнительный пример: установка отрицательной комиссии (скидки) по способу оплаты
add_action('woocommerce_cart_calculate_fees', 'custom_payment_gateway_discount', 20, 1);function custom_payment_gateway_discount( $cart ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; $chosen_gateway = WC()->session->get('chosen_payment_method'); if ( $chosen_gateway === 'bacs' ) { // Банковский перевод $discount = $cart->subtotal * 0.1; // 10% скидка $cart->add_fee( 'Скидка за оплату банковским переводом', -$discount, false ); }}Учтите, что отрицательная комиссия работает как скидка, третий параметр false указывает, что скидка без налога.