Verifique e lide com webhooks recebidos
Autentique eventos de painel assinados e solicitações de coleta de segredos compartilhados sem misturar seus formatos.
Atualizado
Nesta página
Escolha o método de verificação correto
A implementação atual possui dois formatos de entrega. Os eventos de painel assinados incluem Socialjuice-Signature e Socialjuice-Timestamp. As solicitações de formulário de coleta usam X-Webhook-Secret. Mantenha o segredo de assinatura do seu espaço apenas no servidor receptor.
Se um cabeçalho de assinatura estiver presente, exija uma verificação HMAC válida. Não volte a aceitar uma solicitação assinada inválida como uma solicitação herdada. Se você oferece suporte ao formato de coleção, exija seu cabeçalho exato de segredo compartilhado. Rejeite a autenticação ausente.
Verifique uma solicitação assinada
Leia o corpo bruto da solicitação antes que o middleware JSON o altere. A assinatura é HMAC SHA-256 de <timestamp>.<raw_request_body> com o segredo de assinatura. Socialjuice-Signature contém t=<timestamp>,v1=<hex hmac>. Seu carimbo de data/hora deve estar de acordo com Socialjuice-Timestamp.
Use uma comparação de resumo em tempo constante. Rejeite cabeçalhos e carimbos de data/hora malformados há mais de cinco minutos no passado ou no futuro. Mantenha o relógio do seu servidor sincronizado. Após a verificação, analise JSON e distinga webhook.test de testimonial.created.
Exemplo de HMAC do Node.js.
Este exemplo verifica apenas o formato assinado. Forneça o corpo bruto como Buffer antes da análise de JSON. Ele não autentica solicitações de coleta 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);
}Verifique uma solicitação de coleta
Leia X-Webhook-Secret e compare-o com o segredo de assinatura configurado em seu servidor. Rejeite um cabeçalho vazio ou uma incompatibilidade. Mantenha o endpoint em HTTPS e nunca registre este cabeçalho: seu valor é o próprio segredo.
Este formato não inclui carimbo de data/hora assinado ou ID de entrega garantida. Não é possível usar o exemplo HMAC acima para proteção de reprodução. Inspecione o corpo real, encontre o depoimento uuid quando disponível e desduplique dentro do espaço pretendido. As cargas úteis podem ser planas ou conter um objeto de depoimento aninhado.
Aceite rapidamente e evite trabalho duplicado
Processe apenas solicitações autenticadas. Para eventos assinados, desduplicar com Socialjuice-Delivery ou o ID do envelope. Para solicitações de coleta, use um identificador de depoimento estável, quando disponível, e mantenha o contexto do espaço de trabalho. Armazene registros de desduplicação de forma persistente se diversas instâncias de servidor receberem eventos.
Retorne uma resposta 2xx imediatamente após aceitar uma solicitação com segurança e coloque um trabalho mais lento na fila. Trate webhook.test como um teste de conexão, não como um depoimento real. A aprovação no teste não prova que o mapeamento da carga útil da sua coleção está correto.