Node.js

Webhooks

Webhooks são a forma correta de saber o resultado de uma cobrança — nunca faça polling. O SDK verifica a assinatura e devolve um evento tipado por event.type.

Webhooks são a forma correta de saber o resultado de uma cobrança — nunca faça polling. O SDK verifica a assinatura e devolve um evento tipado por event.type.

Verifique a assinatura

Sempre verifique a assinatura com o corpo cru da requisição (o Buffer/string exato que chegou), antes de fazer parse do JSON. Se você já parseou o corpo, a verificação falha.

import express from 'express';
import { Selectwin, SignatureVerificationError } from '@selectwin/sdk';

const sw = new Selectwin(process.env.SELECTWIN_API_KEY!);

// express.raw preserva o corpo cru — obrigatório para verificar o HMAC
app.post('/webhooks/selectwin', express.raw({ type: 'application/json' }), (req, res) => {
  let event;
  try {
    event = sw.webhooks.constructEvent(
      req.body,                                  // Buffer cru — não re-serialize
      req.headers['x-selectwin-signature'],      // header de assinatura
      process.env.SELECTWIN_WEBHOOK_SECRET!,     // whsec_… (da criação do endpoint)
    );
  } catch (e) {
    if (e instanceof SignatureVerificationError) return res.status(400).send('assinatura inválida');
    throw e;
  }

  // responda 2xx rápido; processe de forma assíncrona se for demorado
  res.sendStatus(200);
});

constructEvent lança SignatureVerificationError quando o secret está ausente, o header falta, a assinatura não confere ou o corpo não é JSON válido.

Eventos tipados

O retorno é uma união discriminada: dar switch em event.type estreita o tipo de event.payload.object.

switch (event.type) {
  case 'transaction.approved': {
    const tx = event.payload.object; // tipado como transação
    // dê baixa no pedido
    break;
  }
  case 'transaction.failed':
    // notifique o cliente
    break;
  default:
    // ignore o que você não trata
}

O objeto do recurso vem sempre em event.payload.object. Para trabalhar com o catálogo de tipos, o SDK exporta WEBHOOK_EVENT_TYPES (tupla de todos os tipos) e isWebhookEventType(x).

Proteção contra replay (opcional)

Além do HMAC do corpo, a Selectwin envia um header com timestamp assinado (X-Selectwin-Signature-v1: t=…,v1=…). Para rejeitar entregas antigas (replay), passe esse header e uma tolerância em segundos:

const event = sw.webhooks.constructEvent(req.body, sig, secret, {
  signatureV1: req.headers['x-selectwin-signature-v1'] as string,
  tolerance: 300, // rejeita entregas com mais de 5 min
});

Com signatureV1 presente, constructEvent também valida o timestamp e lança SignatureVerificationError se estiver fora da tolerância.

Próximos passos

How is this guide?

On this page