Диагностика проблемы: почему статус заказа не меняется автоматически
В WooCommerce при успешной оплате заказ обычно получает статус processing или completed, в зависимости от типа товара и настроек платежного шлюза. Иногда бывает необходимо изменить статус заказа программно — например, для заказов с виртуальными товарами или при использовании нестандартных платежных систем. Если статус не меняется автоматически, это может привести к задержкам в обработке или неправильной логике магазина.
Основные причины проблемы:
- Плагин платежной системы не вызывает стандартные хуки WooCommerce после оплаты.
- Статус заказа по умолчанию не соответствует логике магазина (например, виртуальные товары должны сразу становиться
completed). - Кастомные бизнес-процессы требуют дополнительной логики изменения статуса.
Пошаговое решение: программное изменение статуса заказа после оплаты
1. Используем хук woocommerce_payment_complete
Этот хук вызывается после успешной оплаты заказа. В обработчике можно изменить статус заказа на нужный.
add_action('woocommerce_payment_complete', 'custom_change_order_status_after_payment', 10, 1);
function custom_change_order_status_after_payment($order_id) {
if (!$order_id) return;
$order = wc_get_order($order_id);
if (!$order) return;
// Пример: установить статус completed для всех заказов с виртуальными товарами
$items = $order->get_items();
$all_virtual = true;
foreach ($items as $item) {
$product = $item->get_product();
if (!$product->is_virtual()) {
$all_virtual = false;
break;
}
}
if ($all_virtual) {
$order->update_status('completed', 'Статус изменен автоматически для виртуального товара');
}
}2. Альтернатива: изменение статуса при смене оплаты
Если платёжная система не вызывает woocommerce_payment_complete, можно использовать хук woocommerce_order_status_changed и проверять переход статуса:
add_action('woocommerce_order_status_changed', 'custom_order_status_changed_handler', 10, 4);
function custom_order_status_changed_handler($order_id, $old_status, $new_status, $order) {
if ($new_status === 'processing') {
// Например, сразу переводим в completed для цифровых товаров
$items = $order->get_items();
$all_virtual = true;
foreach ($items as $item) {
$product = $item->get_product();
if (!$product->is_virtual()) {
$all_virtual = false;
break;
}
}
if ($all_virtual) {
$order->update_status('completed', 'Автоматический переход в completed');
}
}
}Проверка результата после внедрения
- Создайте тестовый заказ с виртуальным товаром.
- Пройдите оплату через тестовый шлюз (например, Sandbox PayPal).
- Проверьте в админке WooCommerce, что заказ автоматически получил статус
completed. - Посмотрите в логе заказов комментарии — там должен появиться ваш текст из
update_status.
Частые ошибки и их исправление
- Хук не срабатывает: убедитесь, что платежный шлюз вызывает стандартные хуки WooCommerce. Для нестандартных провайдеров пишите отдельную интеграцию.
- Неверный ID заказа в обработчике: всегда проверяйте, что
$order_idи объект$orderкорректны. - Статус не меняется из-за ограничений WooCommerce: нельзя перейти на статус, не предусмотренный в настройках. Проверьте, что статус
completedдобавлен и разрешён.
Практические советы по безопасности и производительности
- Не используйте длительные операции в хуках изменения статуса, чтобы не замедлять оформление заказа.
- Проверяйте права доступа и корректность данных заказа, чтобы избежать ошибок и попыток взлома.
- Для сложных логик изменения статуса лучше выносить код в отдельный плагин, чтобы не терять настройки при обновлении темы.
Сравнение вариантов реализации изменения статуса заказа
| Вариант | Плюсы | Минусы |
|---|---|---|
Хук woocommerce_payment_complete | Стандартный, срабатывает после оплаты, простой код | Не сработает с нестандартными шлюзами |
Хук woocommerce_order_status_changed | Обрабатывает изменение статуса, подходит для кастомных сценариев | Может сработать несколько раз, требует дополнительной логики |
| Пользовательская интеграция платежного шлюза | Полный контроль, точная логика | Сложнее в реализации и поддержке |