Pular para o conteúdo
sinapsepay

Webhooks assinados: como ter certeza de que o aviso veio da SinapsePay

Por que conferir a assinatura de cada webhook, como a assinatura HMAC-SHA256 funciona e como validar em Node.js e Python em poucas linhas.

Equipe SinapsePay · · 2 min de leitura

Um webhook é um aviso: “a cobrança 1042 foi paga”. Se o seu sistema libera o pedido a partir desse aviso, ele precisa ter certeza de quem mandou. Qualquer pessoa que descubra a sua URL pode mandar um JSON parecido.

A assinatura resolve isso

Cada aviso da SinapsePay leva o cabeçalho:

X-SinapsePay-Assinatura: t=1791251108,v1=87e8f770150cad1a...
  • t é o momento do envio (segundos desde 1970).
  • v1 é um HMAC-SHA256 de t + "." + corpo, calculado com um segredo (whsec_…) que só você e a SinapsePay conhecem.

Sem o segredo, ninguém consegue gerar um v1 válido. E como o t entra na conta, um aviso antigo copiado não serve para ser reenviado depois.

Validando em poucas linhas

import { createHmac, timingSafeEqual } from 'node:crypto'

function avisoValido(corpoCru, cabecalho, segredo) {
  const { t, v1 } = Object.fromEntries(cabecalho.split(',').map((p) => p.split('=')))
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false // aviso velho demais
  const esperado = createHmac('sha256', segredo).update(`${t}.${corpoCru}`).digest('hex')
  return v1?.length === esperado.length && timingSafeEqual(Buffer.from(v1), Buffer.from(esperado))
}

Três cuidados que fazem diferença:

  1. Use o corpo cru, exatamente como chegou. Converter para objeto e de volta para texto muda espaços e ordem, e a assinatura não bate.
  2. Compare em tempo constante (timingSafeEqual, hmac.compare_digest), para não vazar informação pelo tempo da comparação.
  3. Ignore repetidos. O mesmo aviso pode chegar mais de uma vez (a SinapsePay tenta de novo se você não responder 2xx). O cabeçalho X-SinapsePay-Entrega é o mesmo em todas as tentativas: guarde e ignore os que já processou.

E se o meu sistema estiver fora do ar?

A SinapsePay tenta de novo em 30 segundos, 2 minutos, 10 minutos, 30 minutos, 1, 3, 6 e 12 horas. O histórico de entregas fica no painel, e você sempre pode consultar a cobrança pela API.

O passo a passo completo, com Python, está em Avisos ao seu sistema.

Comece a cobrar ainda hoje

Crie a conta, conecte o banco da sua empresa e teste tudo no Simulador antes de ir para produção.