# 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 %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.pagou.com.br/integracao-com-a-api/autenticacao-de-webhooks.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
