# Webhooks e Notificações

A Easypay utiliza webhooks (também chamados notificações) para informar a sua aplicação sobre eventos que ocorrem na sua conta Easypay. Este é um serviço servidor-para-servidor que envia notificações quase em tempo real sobre alterações no estado de pagamentos.

## O que são Webhooks?

Webhooks são chamadas **POST API** (codificadas em JSON) que permitem à sua aplicação saber que um evento ocorreu. Eles permitem que o seu sistema reaja automaticamente a eventos de pagamento sem precisar de fazer polling constante da API.

## Por que Usar Webhooks?

Webhooks são particularmente úteis para eventos assíncronos como:

- Quando um cliente paga uma referência Multibanco
- Um pagamento recorrente tem sucesso/falha
- Um pagamento de subscrição tem sucesso/falha
- Um pagamento de venda única de checkout tem sucesso/falha
- A autorização é concedida ou recusada
- A captura é concluída


Com webhooks, o seu sistema pode automatizar ações personalizadas em resposta às transições que ocorrem num fluxo de pagamento.

## Tipos de Notificação Suportados

A Easypay suporta 3 tipos de notificação:

### 1. Notificação Genérica

Uma notificação informando sobre todas as transições de estado de um recurso de pagamento.

**Caso de Uso**: Monitorização abrangente de todos os eventos de pagamento

**Exemplo de Payload**:


```json
{
  "id": "5eca7446-14e9-47bb-aabb-5ee237159b8b",
  "key": "dcf9ab3fd95ca3d5607853f36d46f161c8715858",
  "type": "capture",
  "status": "success",
  "messages": ["Your request was successfully captured"],
  "date": "2022-08-10 14:56:54"
}
```

### 2. Notificação de Autorização

Uma notificação informando sobre um pagamento transitando para o estado de autorização. Disponível para pagamentos únicos e recorrentes.

**Caso de Uso**: Monitorização específica de eventos de autorização

**Exemplo de Payload**:


```json
{
  "id": "1bbc14c3-8ca8-492c-887d-1ca86400e4fa",
  "value": 1,
  "currency": "EUR",
  "key": "the merchant key",
  "expiration_time": "2022-01-01 10:20",
  "customer": {
    "id": "22ea3cc9-424b-489a-91b7-8955f643dc93",
    "name": "Customer Example",
    "email": "customer@example.com",
    "phone": "911234567",
    "phone_indicative": "+351"
  },
  "method": "mb",
  "account": {
    "id": "4c67e74b-a256-4e0a-965d-97bf5d01bd50"
  },
  "authorisation": {
    "id": "4c67e74b-a256-4e0a-965d-97bf5d01bd50"
  }
}
```

### 3. Notificação de Transação

Uma notificação informando sobre um pagamento transitando para o estado de captura. Disponível para pagamentos únicos e recorrentes.

**Caso de Uso**: Monitorização específica de capturas de pagamento com sucesso

**Exemplo de Payload**:


```json
{
  "id": "87615356-0a88-42bd-8abb-aab3e90128de",
  "value": "40",
  "currency": "EUR",
  "key": "the merchant key",
  "expiration_time": "2023-08-07 20:00",
  "method": "MBW",
  "customer": {
    "id": "2eb64a7f-90a7-4dc6-959b-1d9aba44910c",
    "phone": "910410419"
  },
  "account": {
    "id": "0b8de6e7-89c8-4d76-93e8-019bc058f27d"
  },
  "transaction": {
    "id": "eb23923b-3529-4b71-b54e-1e707a8d55c4",
    "key": "transaction_key_of_this_capture",
    "type": "capture",
    "date": "2022-08-10T12:45:50Z",
    "values": {
      "requested": "40",
      "paid": "40",
      "fixed_fee": "0",
      "variable_fee": "0",
      "tax": "0",
      "transfer": "0"
    }
  }
}
```

**Nota**: Se se subscrever tanto a notificações Genéricas como de Autorização, receberá duas notificações para o mesmo evento com diferentes contratos de mensagem.

## Fluxo de Notificação Recomendado

![Fluxo recomendado](https://easypay-cdn-delivery.s3.eu-central-1.amazonaws.com/docs/checkout/notification_recommended_flow.png)

1. **Easypay envia notificação** para o seu endpoint configurado
2. **O seu sistema recebe a notificação** e extrai o ID de pagamento
3. **O seu sistema consulta a API da Easypay** para verificar a notificação (recomendado por razões de segurança)
4. **O seu sistema processa** o pagamento de acordo com a resposta da API


## Configurar Webhooks

### Via Backoffice

1. Faça login no backoffice da Easypay
2. Navegue para `Developers > Configuration API 2.0`
3. Selecione a conta de pagamento para a qual pretende receber notificações
4. Selecione `Notifications`
5. Configure os seus endpoints:
  - **Generic - URL**: Para notificações genéricas
  - **Authorisation - URL**: Para notificações de autorização
  - **Payment - URL**: Para notificações de captura/transação


## Implementar um Endpoint de Webhook

### Requisitos Básicos

O seu endpoint de webhook deve:

- Aceitar pedidos POST
- Aceitar payloads JSON
- Responder com código de estado HTTP 200
- Processar pedidos dentro de 20 segundos
- Ser acessível por HTTPS (recomendado)


### Exemplo de Implementação

Node

```javascript
const express = require('express');
const axios = require('axios');

const app = express();
app.use(express.json());

app.post('/webhooks/easypay/generic', async (req, res) => {
  const notification = req.body;

  // 1. Acknowledge receipt immediately
  res.status(200).send('OK');

  // 2. Verify the notification by querying the API
  try {
    const response = await axios.get(
      `https://api.prod.easypay.pt/2.0/single/${notification.id}`,
      {
        headers: {
          'AccountId': process.env.EASYPAY_ACCOUNT_ID,
          'ApiKey': process.env.EASYPAY_API_KEY
        }
      }
    );

    // 3. Process the verified payment
    if (response.data.status === 'success') {
      await processSuccessfulPayment(response.data);
    } else {
      await handleFailedPayment(response.data);
    }

  } catch (error) {
    console.error('Error verifying notification:', error);
    // Implement retry logic or alert system
  }
});

async function processSuccessfulPayment(payment) {
  // Your business logic here
  console.log('Processing successful payment:', payment.id);
  // Update database, send confirmation email, etc.
}

async function handleFailedPayment(payment) {
  // Your error handling logic
  console.log('Handling failed payment:', payment.id);
}

app.listen(3000);
```

Python

```python
from flask import Flask, request, jsonify
import requests
import os

app = Flask(__name__)

@app.route('/webhooks/easypay/generic', methods=['POST'])
def generic_notification():
    notification = request.json

    # 1. Acknowledge receipt immediately
    response = jsonify({'status': 'received'})
    response.status_code = 200

    # 2. Verify the notification by querying the API
    try:
        verify_response = requests.get(
            f"https://api.prod.easypay.pt/2.0/single/{notification['id']}",
            headers={
                'AccountId': os.getenv('EASYPAY_ACCOUNT_ID'),
                'ApiKey': os.getenv('EASYPAY_API_KEY')
            }
        )

        payment = verify_response.json()

        # 3. Process the verified payment
        if payment['status'] == 'success':
            process_successful_payment(payment)
        else:
            handle_failed_payment(payment)

    except Exception as e:
        print(f"Error verifying notification: {e}")
        # Implement retry logic or alert system

    return response

def process_successful_payment(payment):
    # Your business logic here
    print(f"Processing successful payment: {payment['id']}")
    # Update database, send confirmation email, etc.

def handle_failed_payment(payment):
    # Your error handling logic
    print(f"Handling failed payment: {payment['id']}")

if __name__ == '__main__':
    app.run(port=3000)
```

## Campos de Notificação Genérica por Tipo de Pagamento

Os campos `id` e `key` em notificações genéricas mudam de acordo com o tipo de pagamento e operação:

| Tipo de Pagamento | id | key |
|  --- | --- | --- |
| **Single Authorisation** | ID de pagamento único | `key` do pedido de criação |
| **Single Capture** | ID de pagamento único | `transaction_key` do pedido de captura |
| **Single Sale** | ID de pagamento único | `transaction_key` do objeto `capture` no pedido de criação |
| **Frequent Create** | ID de pagamento recorrente | `key` do pedido de criação |
| **Frequent Authorization** | ID de pagamento recorrente | `transaction_key` do pedido de autorização |
| **Frequent Capture** | ID da operação de captura | `transaction_key` do pedido de captura |
| **Refund** | ID de reembolso | `transaction_key` do pedido de reembolso |
| **Void** | ID de anulação | `transaction_key` do pedido de anulação |
| **Subscription Create** | ID de subscrição | `key` do pedido de criação |
| **Subscription Capture** | ID de subscrição | `transaction_key` do objeto `capture` |
| **Chargeback Single** | ID único | `transaction_key` do pedido de criação |
| **Chargeback Frequent** | ID da operação de captura | `transaction_key` do pedido de captura |
| **Out Payment** | ID de pagamento de saída | `key` do pedido de criação |


## Boas Práticas de Segurança

1. **Sempre Verificar Notificações**: Consulte a API da Easypay para confirmar a autenticidade do webhook
2. **Use HTTPS**: Certifique-se de que o seu endpoint de webhook usa HTTPS
3. **Valide Payload**: Verifique a estrutura do payload antes de processar
4. **Processamento Idempotente**: Trate duplicatas de notificações graciosamente
5. **IP Whitelisting**: Opcionalmente, restrinja o acesso aos intervalos IP da Easypay
6. **Registar Tudo**: Mantenha registos detalhados para resolução de problemas
7. **Monitorizar Falhas**: Alertar sobre falhas no processamento de webhooks


## Testar Webhooks

### Desenvolvimento Local com ngrok


```bash
# 1. Start your local server
npm start  # or python app.py

# 2. Expose local server with ngrok
ngrok http 3000

# 3. Use the ngrok URL in your Easypay backoffice
# Example: https://abc123.ngrok.io/webhooks/easypay/generic
```

### Testes Manuais

Crie pagamentos de teste e monitorize a entrega de webhook:


```bash
# Create a test payment
curl -X POST 'https://api.test.easypay.pt/2.0/single' \
  -H 'AccountId: 2b0f63e2-9fb5-4e52-aca0-b4bf0339bbe6' \
  -H 'ApiKey: eae4aa59-8e5b-4ec2-887d-b02768481a92' \
  -H 'Content-Type: application/json' \
  -d '{
    "type": "sale",
    "value": 10.00,
    "method": "cc"
  }'
```

## Monitorizar Webhooks

Pode monitorizar a entrega de webhook através do backoffice da Easypay:

1. Faça login no backoffice da Easypay
2. Navegue para `Developers > Notifications API 2.0`
3. Selecione a sua conta de pagamento
4. Veja o estado da entrega de webhook, tentativas de retentativa e códigos de resposta


## Processar Falhas

Se o seu endpoint de webhook estiver inacessível ou devolver um erro, a Easypay irá:

- Fazer retentativas do webhook múltiplas vezes
- Usar backoff exponencial entre retentativas
- Eventualmente marcar o webhook como falhado


## Próximos Passos

- [Tipos de Pagamento](/docs/guides/payment-types) - Compreenda diferentes fluxos de pagamento
- [Autorizações e Capturas](/docs/guides/authorizations-captures) - Saiba sobre eventos de auth/capture
- [Referência da API](/openapi) - Esquemas de payload de webhook
- [Tratamento de Erros](/docs/error-handling) - Trate erros de webhook graciosamente