# Webhook URL

## Descripción general

Esta función entrega los datos de una factura pagada al servidor del comercio. Existe para que la tienda del comercio procese el pago automáticamente y entregue el producto o servicio a tu cliente.

El Webhook URL se configura individualmente para cada proyecto y apunta a los scripts de gestión de pagos dentro de la tienda del comercio. La dirección debe usar HTTPS y un nombre de dominio: no se aceptan direcciones IP, y el certificado se verifica en cada entrega.

Cada vez que el estado de una factura cambia a Pagada, el servicio envía a esta URL una solicitud POST con el siguiente formato:

```json
{
   "wallet":{
      "id":"47aa71e2-07a0-482e-9172-7114d7376ba0",
      "name":"usdt-tron",
      "blockchain":"tron",
      "cryptocurrency":"usdt",
      "address":"TKbstUwMzLrfTAGL4erYb7gc7ghmHQ9zG7"
   },
   "project":{
      "id":"9deea1e2-0c08-41a3-bdc2-a34eada3892d",
      "name":"My project",
      "commissionPayer":"seller",
      "commissionRate":1
   },
   "invoice":{
      "id":"a4c9e2ee-9a03-43e5-a1a1-00caf679d16a",
      "uid":"AFhygKX21ecd",
      "createDatetime":"2024-02-26 13:29:24",
      "timeToPayDatetime":"2024-02-27 01:29:24",
      "commissionFiatUSD":0.05,
      "amountFiatUSD":5.02,
      "amountFiat":5,
      "calcAmountFiat":5.02,
      "currencyFiat":"USD",
      "description":null,
      "serviceData":null,
      "status":"paid"
   },
   "payment":{
      "id":"f986ad8d-2298-473d-982a-efbc817b975d",
      "amount":5.02,
      "hash":"74763b65e43bcc9492a6ce9a7f26fbfdbd7635aecd3454420b5e9534cba50ee6",
      "transactionDatetime":"2024-02-26 13:32:57"
   }
}
```

La notificación se envía en cada transición a Pagada (Paid) —tanto cuando el servicio encontró el pago automáticamente como cuando el comercio asoció el pago a la factura manualmente.

## Parámetros de la solicitud

| Parámetro                     | Descripción                                                                                                                                                                                                                                                                                      |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `wallet.id`                   | ID de la billetera en formato UUID                                                                                                                                                                                                                                                               |
| `wallet.name`                 | Nombre de la billetera                                                                                                                                                                                                                                                                           |
| `wallet.blockchain`           | Blockchain de la billetera cripto                                                                                                                                                                                                                                                                |
| `wallet.cryptocurrency`       | Criptomoneda de la billetera                                                                                                                                                                                                                                                                     |
| `wallet.address`              | Dirección de la billetera cripto                                                                                                                                                                                                                                                                 |
| `project.id`                  | ID del proyecto en formato UUID                                                                                                                                                                                                                                                                  |
| `project.name`                | Nombre del proyecto                                                                                                                                                                                                                                                                              |
| `project.commissionPayer`     | Quién paga la comisión del servicio                                                                                                                                                                                                                                                              |
| `project.commissionRate`      | Tarifa en %                                                                                                                                                                                                                                                                                      |
| `invoice.id`                  | ID de la factura en formato UUID                                                                                                                                                                                                                                                                 |
| `invoice.uid`                 | ID de la factura (para el cliente)                                                                                                                                                                                                                                                               |
| `invoice.createDatetime`      | Fecha y hora de creación de la factura (UTC)                                                                                                                                                                                                                                                     |
| `invoice.timeToPayDatetime`   | Fecha y hora hasta la que la factura es válida para el cliente (UTC). La búsqueda de pagos continúa 1 hora más después de esa marca —para tener en cuenta las redes lentas. Así que puede llegar una notificación de una factura que ya se mostraba como vencida                                  |
| `invoice.commissionFiatUSD`   | Importe de la comisión del servicio. Se calcula a partir del importe `invoice.amountFiatUSD`                                                                                                                                                                                                     |
| `invoice.amountFiatUSD`       | Importe en USD. Al crear la factura se calcula a partir de `invoice.amountFiat` al tipo de cambio actual. **En el momento del pago se sobrescribe con el importe realmente recibido**, convertido a USD al tipo de cambio de ese momento. La comisión en `invoice.commissionFiatUSD` también se recalcula a partir de él |
| `invoice.amountFiat`          | El importe original de la factura en moneda fiat. No cambia                                                                                                                                                                                                                                      |
| `invoice.calcAmountFiat`      | El importe calculado en la moneda `invoice.currencyFiat` al tipo de cambio de la cripto en el momento del pago. Puede diferir de `invoice.amountFiat` porque el cliente pudo pagar la factura un tiempo después de su creación y no de inmediato. En ese tiempo, el tipo de cambio de la cripto frente a `invoice.currencyFiat` pudo moverse en cualquier dirección |
| `invoice.currencyFiat`        | Moneda fiat                                                                                                                                                                                                                                                                                      |
| `invoice.description`         | La descripción establecida al crear la factura                                                                                                                                                                                                                                                   |
| `invoice.serviceData`         | Los datos de servicio establecidos al crear la factura                                                                                                                                                                                                                                           |
| `invoice.status`              | Estado de la factura                                                                                                                                                                                                                                                                             |
| `payment.id`                  | ID del pago en formato UUID                                                                                                                                                                                                                                                                      |
| `payment.amount`              | Importe del pago en criptomoneda                                                                                                                                                                                                                                                                 |
| `payment.hash`                | Hash de la transacción on-chain                                                                                                                                                                                                                                                                  |
| `payment.transactionDatetime` | Fecha y hora de la transacción on-chain (UTC)                                                                                                                                                                                                                                                    |

## Firma de la notificación

Cada solicitud se firma con el secreto del webhook. La firma viaja en los encabezados `X-Timestamp` y `X-Signature` y permite asegurarse de que la notificación proviene del servicio y no de un tercero que conoció la dirección de tu gestor.

Verifica la firma antes de procesar el pedido. La mecánica y los ejemplos listos están en [Verificación de la firma del webhook](./signature-verification.md).

## Recomendaciones de gestión

**No rechaces una notificación porque el plazo de pago haya pasado.** Una comprobación del tipo «la factura está vencida, así que el pago no es válido» parece lógica, pero corta una parte de los pagos reales: en redes lentas una transacción puede confirmarse después del plazo, y el comercio puede asociar manualmente un pago a una factura vencida. La propia notificación confirma el pago.

**Verifica el importe contra el campo original** `invoice.amountFiat`. Es el importe de la factura tal como se emitió, y no cambia. El campo `amountFiatUSD` refleja el importe realmente recibido y puede diferir del emitido —tanto por el movimiento del tipo de cambio como por la asociación manual de pagos.

**Analiza los importes como números.** Los ceros finales se descartan: un importe de 10.00 llega como 10; formatéalo en tu lado para mostrarlo. Los importes por debajo de 0.0001 llegan en notación exponencial, por ejemplo 1.0e-6 —el análisis JSON estándar devuelve el número correcto; solo el análisis manual de cadenas falla.

**Gestiona las notificaciones de forma idempotente.** La misma notificación puede llegar de nuevo —por ejemplo, si tu script procesó el pago con éxito pero devolvió un código distinto de 2xx. Antes de entregar el pedido, comprueba si este `invoice.id` ya se ha procesado.

**Escapa los valores al mostrarlos.** Los campos `invoice.description` e `invoice.serviceData` vuelven exactamente como los envió el comercio. Si los muestras en HTML, escápalos en tu lado.

## Calendario de entrega

El servidor en el Webhook URL debe responder con un código HTTP 2xx. Cualquier otro código, un timeout o una conexión interrumpida cuenta como entrega fallida.

No se siguen las redirecciones: una respuesta 301 o 302 es una entrega fallida, no un salto a la nueva dirección. Configura la dirección final del gestor.

La conexión dispone de 5 segundos, la solicitud completa de 10. Si el gestor no entra en ese tiempo, la entrega cuenta como fallida.

Tras una entrega fallida, el servicio reintenta según el siguiente calendario:

* 5 minutos después de la última entrega fallida
* Al cabo de 15 minutos
* Al cabo de 30 minutos
* Al cabo de 1 hora
* Al cabo de 3 horas
* Al cabo de 6 horas
* Al cabo de 12 horas
* Al cabo de 24 horas

Después de eso, los intentos de entrega se detienen.

## Desactivación del Webhook URL

A veces el script del webhook de una tienda procesa el pago correctamente pero devuelve un código HTTP distinto de 2xx. Esto provoca reintentos frecuentes desde nuestro servidor según el calendario de arriba, con carga adicional tanto para nuestro servidor como para el tuyo.

Para prevenir estos casos, tenemos un mecanismo que desactiva el Webhook URL en un proyecto. Para evitarlo, sigue estos pasos:

1. Cambia el código de tu gestor de webhooks para que devuelva un código 2xx, normalmente 200, cuando el pago se procese con éxito. Pruébalo con cualquier emulador, por ejemplo Postman.
2. Contacta con el soporte técnico para corregir la configuración.
3. Vuelve a activar el Webhook URL en la configuración del proyecto y guarda el proyecto.
