Notificação
Os webhooks permitem que você receba notificações em tempo real sobre eventos em sua conta.
Visão Geral
Quando um evento ocorre, a plataforma envia uma requisição HTTP POST para o seu endpoint de webhook. Todos os tipos de evento são entregues na mesma URL configurada.
Configurando Webhooks
- Informe os endpoints de webhook: sandbox e produção
- Implemente um handler para receber eventos de webhook
Segurança
Toda requisição de webhook é assinada. Valide a assinatura antes de processar o evento para garantir que a notificação veio da plataforma e não foi adulterada.
Headers
Cada requisição inclui os seguintes headers:
| Header | Descrição |
|---|---|
X-Webhook-Signature | Assinatura HMAC-SHA256 do corpo, no formato sha256=<hex> |
X-Event-ID | Identificador único do evento |
X-Event-Type | Tipo do evento (ex: payment.completed) |
X-Delivery-Attempt | Número de reenvios já realizados (0 na primeira entrega) |
Como a assinatura é calculada
A assinatura é o HMAC-SHA256 do corpo bruto da requisição — os bytes exatos recebidos — codificado em hexadecimal, usando a chave secreta do seu webhook. O valor é enviado no header prefixado por sha256=.
Calcule a assinatura sobre o corpo bruto. Não deserialize e re-serialize o JSON antes de validar: a re-serialização altera os bytes (ordem de campos, espaçamento) e invalida a assinatura.
Validando em Go
package webhooks
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"io"
"net/http"
"strings"
)
// ValidateSignature verifica o header X-Webhook-Signature contra o corpo bruto da requisição.
// secret é a chave secreta do seu webhook; body são os bytes exatos recebidos.
func ValidateSignature(secret string, body []byte, signatureHeader string) bool {
// O header vem no formato "sha256=<hex>".
want, ok := strings.CutPrefix(signatureHeader, "sha256=")
if !ok {
return false
}
mac := hmac.New(sha256.New, []byte(secret))
mac.Write(body)
got := hex.EncodeToString(mac.Sum(nil))
// Comparação em tempo constante para evitar ataques de temporização.
return hmac.Equal([]byte(want), []byte(got))
}
// Exemplo de handler HTTP.
func HandleWebhook(secret string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// Leia o corpo bruto ANTES de qualquer decodificação de JSON.
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "não foi possível ler o corpo", http.StatusBadRequest)
return
}
if !ValidateSignature(secret, body, r.Header.Get("X-Webhook-Signature")) {
http.Error(w, "assinatura inválida", http.StatusUnauthorized)
return
}
// Assinatura válida — processe o evento a partir do corpo (body).
// Responda 2xx para confirmar o recebimento.
w.WriteHeader(http.StatusOK)
}
}
Tipos de Evento
| Evento | Descrição |
|---|---|
payment.completed | Um pagamento foi concluído com sucesso |
terminal.activated | Um terminal foi ativado com sucesso |