В чем проблема: неудачные оплаты и повторное использование способов оплаты
В WooCommerce иногда возникает задача автоматически отключать определенные способы оплаты, если клиент несколько раз подряд не смог успешно оплатить заказ. Это помогает избежать повторных ошибок, снизить нагрузку на платежные шлюзы и улучшить UX. Однако WooCommerce по умолчанию не содержит такого функционала.
Диагностика проблемы: как понять, что способ оплаты нужно отключить
Первым делом нужно отследить неудачные попытки оплаты. WooCommerce сохраняет статусы заказов, и для неудачных оплат обычно используется статус failed или cancelled. Важно понять, как часто пользователь пытался оплатить и с каким способом.
Для диагностики можно вывести логи или запросить историю заказов пользователя с этими статусами, а также отследить ID способа оплаты, который использовался.
Пример запроса заказов с неудачной оплатой для текущего пользователя
$failed_orders = wc_get_orders(array(
'customer_id' => get_current_user_id(),
'status' => 'failed',
'limit' => -1,
));
Далее нужно подсчитать, сколько раз конкретный способ оплаты использовался в неудачных заказах.
Пошаговое решение: автоматическое отключение способов оплаты по количеству неудач
Реализуем логику, которая при загрузке страницы оформления заказа проверяет количество неудачных оплат с каждым из доступных способов и исключает из списка способы, превысившие порог неудач.
Шаг 1. Создаем функцию фильтрации способов оплаты
add_filter('woocommerce_available_payment_gateways', 'disable_payment_gateways_on_failures');
function disable_payment_gateways_on_failures($available_gateways) {
$user_id = get_current_user_id();
if (!$user_id) {
return $available_gateways; // Только для авторизованных
}
$fail_limit = 3; // Порог неудачных оплат для блокировки
foreach ($available_gateways as $gateway_id => $gateway) {
$fail_count = count_failed_payments_by_gateway($user_id, $gateway_id);
if ($fail_count >= $fail_limit) {
unset($available_gateways[$gateway_id]); // Отключаем метод
}
}
return $available_gateways;
}
function count_failed_payments_by_gateway($user_id, $gateway_id) {
$args = array(
'customer_id' => $user_id,
'status' => 'failed',
'limit' => -1,
'return' => 'ids',
);
$orders = wc_get_orders($args);
$count = 0;
foreach ($orders as $order_id) {
$order = wc_get_order($order_id);
if ($order->get_payment_method() === $gateway_id) {
$count++;
}
}
return $count;
}
Шаг 2. Добавляем уведомление для пользователя
Если способ оплаты отключен, полезно вывести уведомление для пользователя в checkout:
add_action('woocommerce_checkout_before_customer_details', 'notify_payment_gateway_disabled');
function notify_payment_gateway_disabled() {
$user_id = get_current_user_id();
if (!$user_id) return;
$fail_limit = 3;
$available_gateways = WC()->payment_gateways()->get_available_payment_gateways();
// Проверяем все способы оплаты
foreach (WC()->payment_gateways()->payment_gateways() as $gateway_id => $gateway) {
if (!isset($available_gateways[$gateway_id])) {
$fail_count = count_failed_payments_by_gateway($user_id, $gateway_id);
if ($fail_count >= $fail_limit) {
wc_print_notice(sprintf('Способ оплаты "%s" временно недоступен из-за нескольких неудачных попыток.', esc_html($gateway->get_title())), 'error');
}
}
}
}
Проверка результата после внедрения
- Авторизуйтесь под пользователем с несколькими неудачными заказами в WooCommerce.
- Перейдите в корзину и на страницу оформления заказа.
- Убедитесь, что способы оплаты, по которым было более трех неудачных попыток, отсутствуют в списке.
- Проверьте, что появилось уведомление о временной недоступности способа оплаты.
- Для пользователя без неудачных оплат все способы отображаются как обычно.
Частые ошибки и как их исправить
- Не учитывается количество попыток, потому что статус заказа неправильный. Проверьте, что для неудачных оплат действительно выставляется статус
failedили используйте несколько статусов в запросе (через массив). - Функция
wc_get_ordersвозвращает пустой результат. Убедитесь, что передаете корректные параметры, и пользователь авторизован. - Способы оплаты не отключаются. Проверьте, что фильтр
'woocommerce_available_payment_gateways'применяется, и ваш код подключен правильно (например, в functions.php или плагине). - Уведомления не показываются. Проверьте, что хук
'woocommerce_checkout_before_customer_details'не переопределяется в теме или других плагинах.
Практические советы по безопасности и производительности
- Кэшируйте результаты подсчета неудачных оплат по пользователю на несколько минут, чтобы избежать нагрузки при каждом заходе на checkout.
- Не отключайте способы оплаты для гостей — отключение только для авторизованных пользователей позволяет избежать ошибок.
- Храните порог отключения в настройках сайта, чтобы можно было быстро менять логику без правки кода.
- В логах платежного шлюза отслеживайте причины неудач, это поможет точнее настраивать ограничения.
Таблица сравнения вариантов реализации
| Метод | Плюсы | Минусы |
|---|---|---|
Код через фильтр woocommerce_available_payment_gateways | Гибко, без сторонних плагинов, можно быстро менять логику | Требует навыков PHP, может влиять на производительность без кэширования |
| Сторонние плагины для управления способами оплаты | Простой интерфейс, множество функций, поддержка | Платные решения, лишний код, нагрузка на сайт |
| Отказ от автоматического отключения, ручное управление | Простота реализации | Требует постоянного контроля, риск ошибки |