Verificar y manejar webhooks entrantes
Autentique eventos de panel firmados y solicitudes de recopilación de secretos compartidos sin mezclar sus formatos.
Actualizado
En esta página
Elija el método de verificación correcto
La implementación actual tiene dos formatos de entrega. Los eventos del panel firmados incluyen Socialjuice-Signature y Socialjuice-Timestamp. En su lugar, las solicitudes de formulario de recopilación utilizan X-Webhook-Secret. Mantenga la firma de su espacio en secreto solo en el servidor receptor.
Si hay un encabezado de firma presente, requiera una verificación HMAC válida. No recurra a aceptar una solicitud firmada no válida como solicitud heredada. Si admite el formato de colección, solicite su encabezado de secreto compartido exacto. Rechazar la autenticación faltante.
Verificar una solicitud firmada
Lea el cuerpo de la solicitud sin formato antes de que el middleware JSON lo cambie. La firma es HMAC SHA-256 de <timestamp>.<raw_request_body> con el secreto de firma. Socialjuice-Signature contiene t=<timestamp>,v1=<hex hmac>. Su marca de tiempo debe coincidir con Socialjuice-Timestamp.
Utilice una comparación de resumen en tiempo constante. Rechace encabezados y marcas de tiempo con formato incorrecto de más de cinco minutos en el pasado o en el futuro. Mantenga sincronizado el reloj de su servidor. Después de la verificación, analice JSON y distinga webhook.test de testimonial.created.
Ejemplo de HMAC de Node.js
Este ejemplo verifica únicamente el formato firmado. Suministre el cuerpo sin formato como Buffer antes del análisis de JSON. No autentica las solicitudes de cobro X-Webhook-Secret.
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verifySocialjuice(rawBody, headers, secret) {
if (!secret || !Buffer.isBuffer(rawBody)) return false;
const timestamp = headers.get('socialjuice-timestamp') || '';
const signature = headers.get('socialjuice-signature') || '';
const match = /^t=(\d+),v1=([a-f0-9]{64})$/.exec(signature);
if (!match || match[1] !== timestamp) return false;
const seconds = Number(timestamp);
if (!Number.isSafeInteger(seconds) ||
Math.abs(Date.now() / 1000 - seconds) > 300) return false;
const expected = createHmac('sha256', secret)
.update(timestamp + '.')
.update(rawBody)
.digest();
const received = Buffer.from(match[2], 'hex');
return expected.length === received.length &&
timingSafeEqual(expected, received);
}Verificar una solicitud de cobro
Lea X-Webhook-Secret y compárelo con el secreto de firma configurado en su servidor. Rechazar un encabezado vacío o una discrepancia. Mantenga el punto final en HTTPS y nunca registre este encabezado: su valor es el secreto mismo.
Este formato no incluye una marca de tiempo firmada ni un ID de entrega garantizado. No puede utilizar el ejemplo HMAC anterior para la protección de reproducción. Inspeccione la carrocería real, busque el testimonio uuid cuando esté disponible y elimine los duplicados dentro del espacio previsto. Las cargas útiles pueden ser planas o contener un objeto testimonial anidado.
Acepte rápidamente y evite duplicar el trabajo
Procese únicamente solicitudes autenticadas. Para eventos firmados, elimine los duplicados con Socialjuice-Delivery o la identificación del sobre. Para solicitudes de recopilación, utilice un identificador de testimonios estable cuando esté disponible y mantenga el contexto del espacio de trabajo. Almacene registros de deduplicación de forma persistente si varias instancias de servidor reciben eventos.
Devuelve una respuesta 2xx inmediatamente después de aceptar de forma segura una solicitud y pone en cola un trabajo más lento. Trate a webhook.test como una prueba de conexión, no como un testimonio real. Una prueba aprobada no prueba que el mapeo de la carga útil de su colección sea correcto.