Диагностика задачи: зачем и когда нужно менять стоимость товара при оплате
В стандартном WooCommerce цена товара фиксирована при оформлении заказа и не меняется автоматически в процессе оплаты. Однако бывают бизнес-сценарии, когда необходимо корректировать стоимость, например, чтобы применить скидку при выборе определённого способа оплаты, добавить комиссию или изменить цену по другим бизнес-правилам, которые реализуются уже на этапе оплаты, а не на этапе корзины.
Типичные задачи:
- Добавить скидку при оплате через конкретный платёжный шлюз;
- Вычислить комиссию и добавить её к стоимости товара;
- Изменить стоимость товара динамически в зависимости от выбранного способа оплаты или условий;
- Автоматически обновить итоговую сумму заказа при изменении параметров оплаты.
Почему стандартные методы не подходят
WooCommerce рассчитывает цену товара и итоги заказа до выбора способа оплаты. В момент выбора способа оплаты обычно не предусмотрено изменение стоимости товара — чаще применяются купоны или сборы. Но если нужно изменить именно цену товара, а не добавить сбор, стандартных средств недостаточно.
Пошаговое решение: как автоматически изменить цену товара при выборе способа оплаты
1. Используем хук woocommerce_before_calculate_totals для изменения цены товара в корзине
Этот хук позволяет изменить цену товара в корзине перед расчетом итогов. Чтобы применить изменение только при определенном способе оплаты, нужно сначала проверить, какой способ оплаты выбран.
add_action('woocommerce_before_calculate_totals', 'change_product_price_based_on_payment_method', 20, 1); function change_product_price_based_on_payment_method($cart) {
if (is_admin() && !defined('DOING_AJAX')) return;
if (did_action('woocommerce_before_calculate_totals') >= 2) return; // Избегаем повторного применения
$chosen_payment_method = WC()->session->get('chosen_payment_method');
if (!$chosen_payment_method) return;
// Пример: скидка 10% при оплате 'cod' (наложенный платеж)
if ($chosen_payment_method === 'cod') {
foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
$original_price = $cart_item['data']->get_regular_price();
$discounted_price = $original_price * 0.9; // скидка 10%
$cart_item['data']->set_price($discounted_price);
}
}
}2. Обработка выбора способа оплаты через AJAX для обновления цены в реальном времени
По умолчанию выбор способа оплаты не вызывает пересчет корзины. Чтобы изменения цены отображались сразу, добавим JS скрипт, который будет обновлять корзину при смене способа оплаты:
add_action('wp_footer', 'refresh_cart_on_payment_method_change'); function refresh_cart_on_payment_method_change() {
if (!is_checkout()) return;
?>
<script type="text/javascript">
jQuery(function($){
$('form.checkout').on('change', 'input[name="payment_method"]', function(){
$('body').trigger('update_checkout');
});
});
</script>
<?php
}3. Проверка и сохранение выбранного способа оплаты в сессии
WooCommerce уже сохраняет выбранный способ оплаты в сессии, но если в вашем случае это не работает, можно принудительно сохранить его через AJAX-хук:
add_action('woocommerce_checkout_update_order_review', 'save_chosen_payment_method'); function save_chosen_payment_method($posted_data) {
parse_str($posted_data, $output);
if (!empty($output['payment_method'])) {
WC()->session->set('chosen_payment_method', sanitize_text_field($output['payment_method']));
}
}Проверка результата после внедрения
- Перейдите на страницу оформления заказа;
- Добавьте товар в корзину;
- Выберите способ оплаты, например,
наложенный платеж (cod); - Обратите внимание на изменение стоимости товара и итоговой суммы в блоке заказа;
- Смените способ оплаты на другой и убедитесь, что цена возвращается к исходной.
Если цена меняется корректно, значит код работает.
Частые ошибки и как их исправить
- Изменение цены не происходит: Проверьте, что выбран способ оплаты сохраняется в сессии, и что JS обновляет корзину при смене способа оплаты.
- Цена меняется, но итог суммы не обновляется: Убедитесь, что в JS вызывается событие
update_checkoutпри выборе способа оплаты. - Изменение цены применяется несколько раз: Добавьте проверку
did_action('woocommerce_before_calculate_totals') >= 2чтобы избежать повторного применения. - Конфликты с другими плагинами: Проверьте, не изменяют ли другие плагины цену в этом же хуке.
Практические советы по безопасности и производительности
- Не используйте хардкод цен в коде — лучше берите цену из базы и применяйте только коэффициент изменения;
- Минимизируйте количество повторных вызовов функции, чтобы избежать тормозов;
- Проверяйте и фильтруйте данные, особенно если используете пользовательский ввод;
- Для сложных скидок или комиссий рассмотрите использование стандартных сборов WooCommerce, так как они лучше интегрированы в логику расчёта.
Сравнение вариантов реализации изменения стоимости товара при оплате
| Метод | Плюсы | Минусы |
|---|---|---|
Изменение цены товара через woocommerce_before_calculate_totals | Гибкость, точечное изменение цены товара | Сложно поддерживать, возможны конфликты с другими плагинами |
Добавление сбора (fee) на оплату через woocommerce_cart_calculate_fees | Простая реализация, официально поддерживается | Сумма не меняет цену товара, а добавляется отдельным пунктом |
| Использование купонов | Простота, поддержка WooCommerce | Меняет итоговую сумму, но не цену товара в корзине |