Диагностика задачи: почему нужно автоматизировать возврат и обновление статуса заказа
Часто в WooCommerce требуется не только вручную менять статус заказа на «Возвращён» или «Возврат средств», но и автоматически запускать возврат денег через платежные шлюзы при изменении статуса. Это избавляет от ручных ошибок и экономит время поддержки. Однако стандартный WooCommerce не содержит автоматического возврата средств при смене статуса заказа. Для решения этой задачи нужен кастомный код с использованием хука woocommerce_order_status_changed.
Пошаговое решение: как автоматически обновить статус возврата и вернуть деньги
1. Добавляем новый статус заказа (если его нет)
Для удобства создадим статус refunded_manual, который будет обозначать возврат, инициированный вручную или автоматически:
add_action('init', function() {
register_post_status('wc-refunded_manual', [
'label' => 'Возвращён',
'public' => true,
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
'label_count' => _n_noop('Возвращён <span class="count">(%s)</span>', 'Возвращён <span class="count">(%s)</span>'),
]);
});
add_filter('wc_order_statuses', function($order_statuses) {
$order_statuses['wc-refunded_manual'] = 'Возвращён';
return $order_statuses;
});2. Используем хук для автоматизации возврата
Добавим обработчик события смены статуса. При переходе в статус refunded_manual запустим возврат денег через встроенный метод WC_Order_Refund::create() или через API платежного шлюза, если он поддерживает.
add_action('woocommerce_order_status_changed', function($order_id, $old_status, $new_status) {
if ($new_status !== 'refunded_manual') {
return;
}
$order = wc_get_order($order_id);
if (!$order) {
return;
}
// Проверяем, есть ли уже возврат
if (count($order->get_refunds()) > 0) {
return; // Возврат уже создан
}
// Создаем возврат
try {
$refund = wc_create_refund([
'amount' => $order->get_total(),
'reason' => 'Автоматический возврат при смене статуса',
'order_id' => $order_id,
'refund_payment' => true, // возвращать деньги через шлюз
]);
} catch (Exception $e) {
error_log('Ошибка возврата для заказа ' . $order_id . ': ' . $e->getMessage());
}
}, 10, 3);Проверка результата после внедрения
1. Создайте тестовый заказ с реальным или тестовым платежом.
2. В админке поменяйте статус заказа на Возвращён (refunded_manual).
3. Проверьте в WooCommerce, что возврат создан и средства перечислены (в тестовом режиме платежного шлюза).
4. В журнале ошибок PHP убедитесь, что нет ошибок возврата.
5. Проверьте, что статус заказа корректно отображается и в пользовательской части сайта.
Частые ошибки и как исправить
- Ошибка «refund_payment» не возвращает деньги: Проверьте, поддерживает ли ваш платежный шлюз функцию возврата через API. Не все шлюзы позволяют автоматический возврат.
- Возврат создаётся несколько раз: Добавьте проверку
count($order->get_refunds())перед созданием возврата. - Новый статус не отображается в админке: Убедитесь, что вы зарегистрировали статус через
register_post_statusи добавили вwc_order_statuses. - Ошибки при создании возврата: Логируйте исключения в
error_logи проверяйте параметры возврата.
Практические советы по безопасности и производительности
- Используйте nonce и проверки прав при вызове ручных функций возврата вне админки.
- Логируйте все операции возврата для возможности аудита и отладки.
- Не запускайте возврат автоматически при каждом обновлении статуса, а только при целевом статусе, чтобы избежать избыточных операций.
- Для больших магазинов с частыми возвратами рассмотрите реализацию очередей или CRON-задач для асинхронного выполнения возвратов.
Сравнение вариантов реализации автоматического возврата
| Вариант | Код | Плагин | Компромисс |
|---|---|---|---|
| Кастомный код на хуках | Да (пример выше) | Нет | Требует знаний, гибкий, нет дополнительных нагрузок |
| Плагин возврата | Нет | Да (например WooCommerce Refund and Exchange) | Простая установка, но ограниченная кастомизация и возможные накладные расходы |
| Ручной возврат | Нет | Нет | Просто, но требует ручного труда, риск ошибок |