# Autenticação de Webhooks

Todos os webhooks enviados pela API do **Pagou**, incluindo eventos de boletos (ex.: <mark style="color:orange;">`charge.created`</mark>, <mark style="color:orange;">`charge.paid`</mark>) e Pix (ex.: <mark style="color:orange;">`qrcode.completed`</mark>, <mark style="color:orange;">`qrcode.refunded`</mark>), incluem os headers `X-Pagou-Signature` e `X-Pagou-Timestamp` para verificar a autenticidade e integridade das notificações. Esta seção detalha como validar esses headers, incluindo o processo de verificação da assinatura HMAC-SHA256 e do timestamp, exemplos de código em Python e JavaScript, e boas práticas para segurança.

### Visão Geral Técnica

Os webhooks da API do **Pagou** são enviados como requisições HTTP <mark style="color:green;">`POST`</mark> com corpo JSON para o `notification_url` configurado (ex.: <https://your-webhook.com/notifications>). Cada webhook inclui dois headers de autenticação:

* `X-Pagou-Signature`: Assinatura HMAC-SHA256 do conteúdo `timestamp + payload` (onde payload é a string JSON bruta do corpo da requisição). A assinatura é gerada com a chave de API do cliente.
* `X-Pagou-Timestamp`: Timestamp em segundos desde o epoch (ex.: 1754332106 para 2025-08-04 18:28:26).

### Validação dos Headers

Para garantir que o webhook é confiável, valide os headers X-Pagou-Signature e X-Pagou-Timestamp:

1. **Obter a chave de API**
2. **Validar** `X-Pagou-Signature`:
   * Extraia o `<hex>` do header `X-Pagou-Signature`.
   * Concatene o valor de `X-Pagou-Timestamp` com o payload JSON bruto (ex.: `1754329142` + `{"name":"charge.created",...}).`
   * Calcule o HMAC-SHA256 do resultado usando a chave de API.
   * Compare o hash calculado com o `<hex>` do header usando uma comparação resistente a ataques de tempo (ex.: `crypto.timingSafeEqual` em JavaScript, `hmac.compare_digest` em Python).
3. **Rejeitar se inválido**:
   * Retorne `401 Unauthorized` se a assinatura ou timestamp forem inválidos.
   * Registre tentativas inválidas para monitoramento.

**Nota**: A validação dos headers é altamente recomendada para segurança, mas os webhooks são enviados mesmo que a validação não seja implementada.

### Exemplos de Código

{% tabs %}
{% tab title="JavaScript" %}

```javascript
const crypto = require('crypto');

function verifySignature(payload, timestamp, signature, secret) {
    const receivedDigest = signature;
    const message = timestamp + payload;
    const hmac = crypto.createHmac('sha256', secret);
    hmac.update(message);
    const computedDigest = hmac.digest('hex');
    
    try {
        const receivedBuffer = Buffer.from(receivedDigest, 'hex');
        const computedBuffer = Buffer.from(computedDigest, 'hex');
        
        if (receivedBuffer.length !== computedBuffer.length) {
            return false;
        }
        
        return crypto.timingSafeEqual(receivedBuffer, computedBuffer);
    } catch (e) {
        return false;
    }
}

// Example usage:
const payload = '{"name":"charge.created","data":{"id":"7a86b3b7-779e-4e9f-af7d-bf2e512ddae1","transaction_id":"0","client_code":"7a86b3b7-779e-4e9f-af7d-bf2e512ddae1","payload":{"transaction_id":"123","bank_emissor":"bradesco","bank_number":"137","bank_agency":"0001","bank_account":"12345678","bar_code":"123456789098765434321","line":"1234323465654758868986","bank_assignor":"Celcoin"}}}';
const timestamp = '1754329886'; // From X-Pagou-Timestamp header
const signature = 'ff502eeda47ceb3a6c0dc32a34d9503f32224f6fd8c9ad30a25c0f7cf0ca358c'; // From X-Pagou-Signature header
const apiKey = '07ab896a-d830-418b-8c55-47874dc6760e'; // API Key

const isValid = verifySignature(payload, timestamp, signature, apiKey);
console.log('Signature valid:', isValid);
```

### Boas Práticas Técnicas

* **Segurança**: Sempre valide `X-Pagou-Signature` e `X-Pagou-Timestamp` para garantir a origem e integridade do webhook.
* **Comparação Segura**: Use funções como `crypto.timingSafeEqual` (JavaScript) ou `hmac.compare_digest` (Python) para evitar ataques de tempo.
* **Prevenção de Replay Attacks**: Rejeite webhooks com `X-Pagou-Timestamp` fora de ±5 minutos do horário atual.
* **Monitoramento**: Registre `X-Pagou-Timestamp`, `X-Pagou-Signature`, e resultados da validação em logs para auditoria.
* **HTTPS**: Use um certificado SSL válido para o `notification_url`.
  {% endtab %}

{% tab title="Python" %}

```python
import hmac
import hashlib

def verify_signature(payload, timestamp, signature, secret):
    message = timestamp + payload
    computed_digest = hmac.new(
        key=secret.encode('utf-8'),
        msg=message.encode('utf-8'),
        digestmod=hashlib.sha256
    ).hexdigest()
    
    return hmac.compare_digest(computed_digest, signature)

# Example usage:
payload = '{"name":"charge.created","data":{"id":"7a86b3b7-779e-4e9f-af7d-bf2e512ddae1","transaction_id":"0","client_code":"7a86b3b7-779e-4e9f-af7d-bf2e512ddae1","payload":{"transaction_id":"123","bank_emissor":"bradesco","bank_number":"137","bank_agency":"0001","bank_account":"12345678","bar_code":"123456789098765434321","line":"1234323465654758868986","bank_assignor":"Celcoin"}}}'
timestamp = '1754329886'  # From X-Pagou-Timestamp header
signature = 'ff502eeda47ceb3a6c0dc32a34d9503f32224f6fd8c9ad30a25c0f7cf0ca358c'  # From X-Pagou-Signature header
api_key = '07ab896a-d830-418b-8c55-47874dc6760e'  # API Key

is_valid = verify_signature(payload, timestamp, signature, api_key)
print('Signature valid:', is_valid)
```

### Boas Práticas Técnicas

* **Segurança**: Sempre valide `X-Pagou-Signature` e `X-Pagou-Timestamp` para garantir a origem e integridade do webhook.
* **Comparação Segura**: Use funções como `crypto.timingSafeEqual` (JavaScript) ou `hmac.compare_digest` (Python) para evitar ataques de tempo.
* **Prevenção de Replay Attacks**: Rejeite webhooks com `X-Pagou-Timestamp` fora de ±5 minutos do horário atual.
* **Monitoramento**: Registre X-Pagou-Timestamp, X-Pagou-Signature, e resultados da validação em logs para auditoria.
* **HTTPS**: Use um certificado SSL válido para o notification\_url.
* **Testes**: Valide webhooks no ambiente sandbox (<https://sandbox.api.pagou.com.br/v1>) usando ferramentas como ngrok.
  {% endtab %}
  {% endtabs %}
