Автоматическое обновление статуса заказа в WooCommerce через REST API после callback платёжной системы

Проблема: заказ в WooCommerce не обновляется после callback платёжной системы

При интеграции сторонних платёжных систем часто возникает задача: после успешного завершения оплаты платёжная система отправляет callback (уведомление) на ваш сайт. Нужно автоматически обновить статус соответствующего заказа в WooCommerce, чтобы избежать ручного вмешательства и ошибок.

Однако, многие сталкиваются с тем, что статус не меняется, заказ остаётся в статусе "Ожидает оплаты" или "В обработке". Это приводит к путанице и дополнительной работе.

Диагностика проблемы: почему статус заказа не меняется

  • Неправильный endpoint — callback не достигает нужного обработчика в WordPress.
  • Отсутствие или неправильная аутентификация — запросы к REST API отклоняются.
  • Ошибки в коде обновления заказа — неверный ID заказа, отсутствие вызова нужных методов WooCommerce.
  • Кэширование — старые данные возвращаются из кэша, и изменения не видны.
  • Отсутствие проверки nonce или прав — WordPress блокирует запрос.

Пошаговое решение: как реализовать обновление заказа через REST API

1. Создайте кастомный endpoint для приёма callback

Добавьте в functions.php или в плагин следующий код, который регистрирует REST API маршрут для callback:

add_action('rest_api_init', function () {
    register_rest_route('custom/v1', '/payment-callback', [
        'methods' => 'POST',
        'callback' => 'handle_payment_callback',
        'permission_callback' => '__return_true', // временно, лучше добавить проверку
    ]);
});

function handle_payment_callback(WP_REST_Request $request) {
    $params = $request->get_json_params();
    if (empty($params['order_id']) || empty($params['payment_status'])) {
        return new WP_REST_Response(['error' => 'Invalid parameters'], 400);
    }

    $order_id = intval($params['order_id']);
    $payment_status = sanitize_text_field($params['payment_status']);

    $order = wc_get_order($order_id);
    if (!$order) {
        return new WP_REST_Response(['error' => 'Order not found'], 404);
    }

    // Обновляем статус заказа в зависимости от статуса оплаты
    switch (strtolower($payment_status)) {
        case 'paid':
            $order->update_status('processing', 'Оплата подтверждена через callback');
            break;
        case 'failed':
            $order->update_status('failed', 'Оплата не прошла');
            break;
        default:
            return new WP_REST_Response(['error' => 'Unknown payment status'], 400);
    }

    return new WP_REST_Response(['success' => true], 200);
}

2. Настройте платёжную систему для вызова вашего callback URL

URL будет выглядеть так:

https://yourdomain.com/wp-json/custom/v1/payment-callback

Проверьте, что платёжная система отправляет POST запрос с JSON телом, например:

{
  "order_id": 1234,
  "payment_status": "paid"
}

3. Добавьте базовую защиту и аутентификацию

Для безопасности не стоит разрешать открытый вызов. Например, используйте параметр секретного ключа:

function handle_payment_callback(WP_REST_Request $request) {
    $secret = $request->get_header('X-Callback-Secret');
    if ($secret !== 'ваш_секретный_ключ') {
        return new WP_REST_Response(['error' => 'Unauthorized'], 401);
    }
    // остальной код...

Как проверить, что решение работает

  • Отправьте тестовый POST запрос через Postman или curl на ваш endpoint с корректными параметрами.
  • Убедитесь, что в админке WooCommerce статус заказа изменился.
  • Проверьте логи сервера и WordPress на наличие ошибок.
curl -X POST https://yourdomain.com/wp-json/custom/v1/payment-callback \
-H 'Content-Type: application/json' \
-H 'X-Callback-Secret: ваш_секретный_ключ' \
-d '{"order_id":1234,"payment_status":"paid"}'

Частые ошибки и способы исправления

  • Ошибка 404 при вызове callback — проверьте, что пермалинки включены, и маршрут зарегистрирован.
  • Ошибка 401 Unauthorized — неверный или отсутствующий секретный ключ, настройте заголовки запроса.
  • Статус заказа не меняется — проверьте, что ID заказа правильный и что $order не null.
  • Callback не срабатывает из-за кэширования — отключите кэширование для REST API или используйте хуки очистки кэша.

Практические советы по безопасности и производительности

  • Используйте HTTPS для callback URL, чтобы защитить данные.
  • Добавьте IP-фильтрацию, если платёжная система имеет фиксированные IP адреса.
  • Ограничьте количество запросов с помощью rate limiting, чтобы избежать DDoS.
  • Логируйте события callback в отдельный файл, чтобы быстро отследить проблемы.
  • Обрабатывайте callback асинхронно, если обновление заказа требует дополнительных действий, чтобы не блокировать ответ.

Сравнение способов реализации

МетодПлюсыМинусы
Кастомный REST API endpointГибкость, можно реализовать логику под себяТребуется код, безопасность на ответственности разработчика
Плагины интеграции платёжных системГотовые решения, поддержкаМожет не подходить под специфические задачи, ограниченная кастомизация
Использование webhooks платёжной системы напрямую с WooCommerceПростота, часто встроеноМеньший контроль, зависит от возможностей плагина или темы

Шаблоны для WP Плагины для WP