# 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