Webhooks en WooCommerce: cómo crearlos y verificar su firma

Los webhooks en WooCommerce son notificaciones HTTP que tu tienda envía automáticamente a una URL externa cuando ocurre un evento concreto, como la creación de un pedido. En lugar de estar consultando constantemente la base de datos, recibes la información en el momento exacto en que se produce.

Qué son exactamente los webhooks y por qué importan

Un webhook es simplemente una llamada POST que WooCommerce hace a la URL que tú configures. El payload suele llegar en JSON e incluye toda la información del recurso afectado. Su gran ventaja es que eliminan la necesidad de polling, reduciendo la carga en tu servidor y permitiendo integraciones en tiempo real con ERP, gestores de logística o CRMs.

Cómo crear un webhook para el evento «pedido creado»

Existen dos formas principales: desde el panel de administración o mediante código. La más rápida es hacerlo desde WooCommerce → Ajustes → Avanzado → Webhooks.

Pulsa en «Añadir webhook», dale un nombre descriptivo y elige como Estado «Activo». En Entrega a escribe la URL completa de tu receptor. El campo más importante es Acción del evento: selecciona order.created.

Guarda. WooCommerce generará automáticamente una clave secreta que usarás después para verificar la firma. Si prefieres hacerlo por código, puedes usar el siguiente snippet:

<?php
add_action('woocommerce_init', function() {
    $webhook = new WC_Webhook();
    $webhook->set_name('Pedido creado - Mi ERP');
    $webhook->set_topic('order.created');
    $webhook->set_delivery_url('https://midominio.com/webhook/pedidos');
    $webhook->set_secret('tu_clave_secreta_muy_larga_y_aleatoria');
    $webhook->set_status('active');
    $webhook->save();
});
?>

Verificar la firma HMAC en el receptor (ejemplo en PHP)

La seguridad es crítica. WooCommerce firma cada petición con HMAC-SHA256 usando tu clave secreta. Si no verificas esta firma, cualquiera podría enviarte peticiones falsas.

Este es un ejemplo completo y funcional de un endpoint en PHP puro:

<?php
header('Content-Type: application/json');

$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WC_WEBHOOK_SIGNATURE'] ?? '';
$secret = 'tu_clave_secreta_muy_larga_y_aleatoria';

$calculated_signature = base64_encode(hash_hmac('sha256', $payload, $secret, true));

if (!hash_equals($calculated_signature, $signature)) {
    http_response_code(401);
    echo json_encode(['error' => 'Firma inválida']);
    exit;
}

$data = json_decode($payload, true);

// Procesar el pedido
if (isset($data['id'])) {
    $order_id = (int) $data['id'];
    // Aquí tu lógica: enviar a ERP, actualizar stock externo, etc.
    error_log('Pedido recibido: ' . $order_id);
}

http_response_code(200);
echo json_encode(['status' => 'ok']);

El uso de hash_equals es importante para evitar ataques de timing. Nunca uses el operador ==.

Reintentos automáticos de WooCommerce

WooCommerce reintenta la entrega de webhooks fallidos hasta 5 veces con un backoff exponencial. Los intervalos aproximados son: 1 minuto, 5 minutos, 15 minutos, 1 hora y 5 horas.

Para que un reintento se active, tu endpoint debe devolver un código HTTP diferente a 2xx (normalmente 500 o 503). Si devuelves 200 aunque ocurra un error interno, WooCommerce considerará que todo fue bien y no volverá a intentarlo.

Errores típicos que te volverán loco

  • URL bloqueada por firewall o Cloudflare: Asegúrate de permitir las IPs de tu servidor WooCommerce o añade una regla específica.
  • Firma incorrecta: El error más común. Revisa que estás usando exactamente la clave secreta y que el payload no ha sido modificado (ni siquiera un salto de línea).
  • Timeout: Si tu receptor tarda más de 20 segundos, WooCommerce aborta la conexión y considera que falló.
  • JSON mal formado: Si devuelves HTML en lugar de JSON cuando hay error, el log de WooCommerce se vuelve confuso.
  • No guardar el log: Activa el registro de webhooks en WooCommerce → Estado → Logs y filtra por webhooks.

Cuándo usar la REST API en lugar de webhooks

Los webhooks son ideales cuando quieres reaccionar inmediatamente a eventos. Sin embargo, hay casos en los que la REST API es más adecuada:

  • Cuando necesitas consultar datos históricos o filtrar pedidos con criterios complejos.
  • Procesos batch nocturnos (exportaciones masivas, conciliaciones).
  • Cuando el sistema receptor no puede exponer una URL pública segura.
  • Integraciones que requieren autenticación OAuth o permisos granulares.

En la práctica, muchos desarrolladores combinan ambas estrategias: usan webhooks para notificaciones en tiempo real y la REST API para obtener información adicional o corregir datos.

Buenas prácticas que deberías seguir siempre

  1. Guarda siempre el ID del webhook en tu base de datos para poder desactivarlo si es necesario.
  2. Procesa los webhooks de forma asíncrona. No hagas todo el trabajo dentro del endpoint; encola la tarea.
  3. Idempotencia. Tu código debe poder recibir dos veces el mismo pedido sin duplicar información.
  4. Usa un secreto largo y aleatorio (mínimo 32 caracteres).
  5. Monitorea los logs de fallos diariamente las primeras semanas.

Implementar webhooks correctamente te ahorrará decenas de miles de peticiones innecesarias al día y te dará una integración mucho más robusta. Una vez que lo tienes funcionando, rara vez vuelves a tocarlo.

Scroll al inicio