Pagos Online
Concepto clave: Sesion vs Pago
Es fundamental entender que en la External API existen dos conceptos distintos: la sesion y el pago. Aunque estan relacionados, representan cosas diferentes y tienen ciclos de vida independientes.
La sesion (sessionId)
La sesion es lo que tu sistema crea al llamar a POST /payment/session. Representa la intencion de cobro: el importe, la divisa, las URLs de retorno, la descripcion, etc. Cuando la creas, recibes un sessionId y una paymentUrl para redirigir al cliente.
Cuando el cliente completa el pago con exito, la sesion pasa a estado completed y se cierra.
La sesion no se modifica una vez completada. Su trabajo ha terminado: sirvio para que el cliente pagara.
El pago (paymentReference)
El pago es la transaccion real que se crea cuando el cliente completa satisfactoriamente el formulario de pago. Es el objeto que el procesador de pagos reconoce y sobre el que se pueden hacer operaciones.
El paymentReference (referencia del pago autorizado) aparece dentro de la sesion una vez completada, en el campo paymentReference y tambien en el array de attempts.
El pago es lo que importa para operaciones posteriores. Reembolsos, capturas, cancelaciones y extensiones se hacen sobre el paymentReference, no sobre el sessionId.
Relacion visual
Sesion (sessionId: "SHOP01-EXT-1719500000")
|
|-- Cliente completa el pago (status: "authorised") <-- ESTE ES EL PAGO
|
Estado de la sesion: "completed"
paymentReference: "KVGQSN3K2SKFNVNS" <-- referencia del pago realEn resumen
| Concepto | Que es | Se crea cuando | Se usa para |
|---|---|---|---|
Sesion (sessionId) | Intencion de cobro | Tu sistema llama a POST .../payment/session | Redirigir al cliente, consultar estado |
Pago (paymentReference) | Transaccion autorizada | El cliente completa el pago con exito | Reembolsos, capturas, cancelaciones, conciliacion |
Regla practica: Usa
sessionIdpara consultar el estado y obtener elpaymentReference. UsapaymentReferencepara modificar el pago (refund, capture, cancel, extend).
---
Flujo completo de un pago online
Antes de entrar en los endpoints, es importante entender el flujo completo. Un pago online implica tres participantes y tres redireccionamientos:
Tu sistema Avirato Payments Cliente
| | |
| 1. POST /payment/session |
| (con urlOk y urlKo) | |
|------------------------->| |
| | |
| 2. Recibe paymentUrl | |
|<-------------------------| |
| | |
| 3. Redirige al cliente a la paymentUrl |
|------------------------->+---------------------------->
| | |
| 4. El cliente ve la pagina |
| de pago y paga |
| |<--------------------------+
| | |
| 5. Avirato Payments redirige |
| a urlOk (exito) o urlKo (fallo) |
| +--------------------------->
| | |
| 6. El cliente llega a tu urlOk o urlKo |
|<-------------------------+---------------------------+
| | |
| 7. Tu sistema consulta | |
| GET /payment/session/{id} |
|------------------------->| |
|<-------------------------| |Paso a paso
- Tu sistema crea la sesion llamando a
POST /payment/sessioncon el importe, la divisa, y dos URLs de retorno:urlOkyurlKo - Recibes un
sessionIdy unapaymentUrl. LapaymentUrles un enlace a la pagina de pago segura de Avirato Payments - Redirige al cliente a la
paymentUrl. Puedes hacer un redirect HTTP 302 o abrir en una nueva pestana, segun tu caso de uso - El cliente ve la pagina de pago. Ahi introduce su tarjeta, completa 3D Secure si es necesario, y confirma el pago. Tu sistema no interviene en este paso
- Avirato Payments redirige automaticamente al cliente a una de las dos URLs que proporcionaste:
urlOksi el pago se completo con exitourlKosi el pago fallo, fue cancelado por el cliente, o expiro- El cliente llega a tu pagina. En la
urlOkpuedes mostrar un mensaje de confirmacion. En laurlKopuedes informar del problema y, si tiene sentido, crear una nueva sesion de pago para ofrecer otro intento - Tu sistema confirma el pago usando las herramientas que te proporcionamos: los datos cifrados que llegan en el parametro
datade laurlOk(descifrables con tu client secret), el webhook que recibiras automaticamente unos segundos despues, y opcionalmente la consultaGET /payment/session/{id}para verificacion adicional
Entorno Test: El flujo es identico. La unica diferencia es que en el paso 4, la pagina de pago es un formulario simulado (no conecta con ningun procesador real). El cliente introduce tarjetas ficticias y el resultado se determina segun el nombre del titular (ver Tarjetas de prueba).
La importancia de urlOk y urlKo
Estas dos URLs son el puente de vuelta entre nuestra pagina de pago y tu sistema. Son obligatorias y determinan la experiencia del cliente despues de pagar:
urlOk: Donde aterrizara el cliente cuando el pago sea exitoso. Debe ser una pagina de tu sistema que muestre una confirmacion (ej: "Gracias, tu pago se ha completado"). La URL recibira un parametrodatacon informacion cifrada del pago (descifrable con tu client secret)urlKo: Donde aterrizara el cliente si algo falla (tarjeta rechazada, timeout, cancelacion). Debe ser una pagina que informe del problema. Si quieres ofrecer otro intento, crea una nueva sesion de pago desde tu backend y redirige al cliente a la nuevapaymentUrl
Recomendacion practica: Usa el campo
customReferenceal crear la sesion para incluir tu referencia interna (ej: numero de pedido, ID de operacion). Este valor se incluye en los datos cifrados del redirect y en los webhooks, lo que te permite asociar automaticamente el resultado con la operacion original en tu sistema.
No confies solo en la URL de retorno: verifica el estado con
GET /payment/session/{sessionId}y, sobre todo, con los webhooks. En Live el estado definitivo de un pago puede evolucionar despues del redirect o de una consulta anterior (por ejemplo, un chargeback notificado por el procesador). Trata los webhooks como la referencia de negocio para cambios tardios y vuelve a consultar la API si necesitas el estado persistido (verWebhooks).
---
Crear sesion de pago
Crea una sesion de pago y obtiene una URL donde redirigir al cliente para completar el pago.
Live: POST https://aviratopayments.com/external/v1/payment/session
Test: POST https://aviratopayments.com/external/v1/test/payment/sessionParametros del body
| Campo | Tipo | Requerido | Descripcion |
|---|---|---|---|
webcode | string | Si | Identificador de tu negocio |
amount.value | integer | Si | Importe en centimos (ej: 10000 = 100.00 EUR) |
amount.currency | string | Si | Codigo ISO 4217 de 3 letras en mayusculas. Valores aceptados: EUR, GBP, USD |
urlOk | string | Si | URL donde redirigir al cliente cuando el pago se completa con exito. Debe ser una URL valida de tu sistema |
urlKo | string | Si | URL donde redirigir al cliente cuando el pago falla, se cancela o expira. Debe ser una URL valida de tu sistema |
countryCode | string | No | Codigo ISO 3166-1 alpha-2 (por defecto: ES) |
shopperLocale | string | No | Idioma de la pagina de pago, formato BCP-47 (por defecto: es-ES). Max 10 caracteres |
deliverAt | string | No | Fecha del servicio en formato ISO 8601 (ej: 2026-07-15T14:00:00Z) |
description | string | No | Descripcion del pago. Max 255 caracteres |
customReference | string | No | Tu referencia interna para conciliacion. Max 100 caracteres. Se incluye en los datos cifrados del redirect |
isPreAuth | boolean | No | true para preautorizacion (no captura inmediata). Por defecto: false |
Ejemplo de peticion (Live)
curl -X POST https://aviratopayments.com/external/v1/payment/session \
-H "X-API-KEY: tu_api_key_live" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-12345-payment" \
-d '{
"webcode": "SHOP01",
"amount": {
"value": 15000,
"currency": "EUR"
},
"urlOk": "https://tu-sistema.com/pago-ok",
"urlKo": "https://tu-sistema.com/pago-error",
"countryCode": "ES",
"shopperLocale": "es-ES",
"description": "Pedido #12345 - Servicio premium",
"customReference": "ORD-2026-12345",
"isPreAuth": false
}'Ejemplo de peticion (Test)
curl -X POST https://aviratopayments.com/external/v1/test/payment/session \
-H "X-API-KEY: tu_api_key_test" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: test-order-12345-payment" \
-d '{
"webcode": "SHOP01",
"amount": {
"value": 15000,
"currency": "EUR"
},
"urlOk": "https://tu-sistema.com/pago-ok",
"urlKo": "https://tu-sistema.com/pago-error",
"description": "Pedido #12345 - Servicio premium",
"customReference": "ORD-2026-12345"
}'Respuesta exitosa (201)
{
"success": true,
"data": {
"sessionId": "SHOP01-EXT-17195000001234",
"paymentUrl": "https://aviratopayments.com/pay-external/eyJhbGciOi...",
"status": "pending",
"amount": {
"value": 15000,
"currency": "EUR"
},
"description": "Pedido #12345 - Servicio premium",
"customReference": "ORD-2026-12345",
"isPreAuth": false,
"createdAt": "2026-06-28 10:30:00"
}
}Formato de
sessionId: En Live el formato es{webcode}-EXT-{timestamp}. En Test el formato es{webcode}-EXTT-{timestamp}. Esto te permite identificar a simple vista de que entorno proviene una sesion.
paymentUrlen Test: La URL apunta a una pagina de pago simulada (no conecta con la pasarela real). El formulario acepta tarjetas ficticias y el resultado se determina por el nombre del titular. Ver Tarjetas de prueba.
Que hacer con la respuesta
- Guarda el
sessionIden tu sistema, asociado a la operacion (pedido, servicio, etc.). Lo necesitaras para consultar el estado y obtener elpaymentReferencecuando se complete - Redirige al cliente a
paymentUrlinmediatamente. Ahi vera la pagina de pago segura con los metodos de pago disponibles - Prepara tus paginas de retorno (
urlOkyurlKo). El cliente llegara a una de ellas despues de pagar
Tiempo limite para pagar
Una vez que el cliente abre la paymentUrl, dispone de 5 minutos (300 segundos) para completar el pago. Pasado ese tiempo, la pagina de pago expira automaticamente y el cliente es redirigido a urlKo.
La sesion en si no tiene un tiempo de expiracion fijo desde el servidor: lo que expira es la pagina de pago en el navegador del cliente. Si el cliente no abre la paymentUrl, la sesion permanece en estado pending indefinidamente.
La pagina de pago muestra un reloj con la cuenta atras visible para el cliente, asi que no necesitas informarle por tu parte.
Ciclo de vida de la sesion
La sesion (no el pago) pasa por estos estados:
pending --> (cliente completa pago) --> completed --> El pago existe, usa paymentReference
--> (cliente cancela) --> cancelled
--> (error en el pago) --> failed
--> (tiempo expirado) --> expired| Estado | Descripcion |
|---|---|
pending | Sesion creada, esperando que el cliente pague. Puede haber intentos fallidos en curso |
completed | Un intento de pago fue autorizado. La sesion se cierra y el paymentReference esta disponible |
failed | Todos los intentos han fallado sin que ninguno sea autorizado |
expired | La sesion ha expirado sin completarse |
cancelled | Cancelada antes de completarse |
Importante: Una sesion
completedno cambiara de estado. A partir de ese momento, lo relevante es el pago (paymentReference), que es el que puedes reembolsar, capturar, etc.
Si el pago falla
Si el pago falla (tarjeta rechazada, 3DS cancelado, timeout), el cliente es redirigido a tu urlKo. Para ofrecer otro intento, crea una nueva sesion y redirige al cliente a la nueva paymentUrl.
---
Redirect post-pago: lo que ocurre cuando el cliente termina
Una vez que el cliente completa el formulario de pago (o lo abandona/falla), Avirato Payments le redirige automaticamente a la URL correspondiente:
- Pago exitoso -> El cliente es redirigido a tu
urlOk - Pago fallido, cancelado o expirado -> El cliente es redirigido a tu
urlKo
La redireccion es automatica: el cliente ve brevemente un mensaje "Redirigiendo..." y aterriza en tu pagina sin necesidad de hacer clic en ningun boton.
El parametro data en urlOk
Cuando el cliente llega a tu urlOk, la URL incluye un parametro data con un JWT que contiene informacion cifrada del pago:
https://tu-sistema.com/pago-ok?data=eyJhbGciOiJIUzI1NiIs...Para leer esta informacion:
- Extrae el parametro
datade la URL - Decodifica el JWT usando tu client secret como clave (ver Autenticacion - Client Secret)
- El payload descifrado contiene los datos del pago: referencia, importe, estado, etc.
urlKono incluye el parametrodata, ya que no hay pago exitoso del que informar. EnurlKomuestra un mensaje apropiado al cliente.
Entorno Test: El parametro
dataenurlOkfunciona exactamente igual que en Live. Se cifra con el client secret del entorno Test, y lo descifras con ese mismo secret. El contenido tiene la misma estructura.
Validacion de los datos del redirect
Cuando recibas al cliente en urlOk con el parametro data, valida la informacion cifrada contra los datos en abierto:
- Decodifica el JWT con tu client secret
- Compara los datos del payload (importe, referencia, estado) con lo que esperas segun tu logica de negocio
- Si los datos no coinciden, trata la operacion como sospechosa
Esto protege contra manipulaciones: un usuario podria cambiar la URL manualmente, pero no puede falsificar el JWT sin tu client secret.
Que pasa si el cliente cierra el navegador
Si el cliente completa el pago pero cierra el navegador antes de ser redirigido, el pago se ha completado igualmente.
En este caso, el cliente nunca llega a tu urlOk. Para cubrir este escenario:
- Recibiras un webhook unos segundos despues de que el pago se complete (ver Webhooks)
- Como alternativa, puedes hacer polling periodico con
GET /payment/session/{sessionId}para detectar sesiones que pasaron acompletedsin que el cliente volviera
Recomendacion: No dependas exclusivamente de la redireccion a
urlOkpara confirmar pagos. Usa los webhooks como fuente principal de confirmacion y la redireccion como mejora de experiencia de usuario.
---
Tarjetas de prueba (entorno Test)
En el entorno Test, la pagina de pago es un formulario simulado. No se conecta con ningun procesador real. El resultado del pago se determina por el nombre del titular de la tarjeta (holderName):
Pago exitoso
Usa cualquier nombre que no sea uno de los valores especiales de la tabla siguiente. Ejemplo: Juan Garcia, Test User, Maria Lopez.
Simular fallos
| Nombre del titular (case-insensitive) | Resultado | Motivo |
|---|---|---|
DECLINED | Pago rechazado | Generic decline |
CARD_EXPIRED | Pago rechazado | Expired card |
INVALID_CARD | Pago rechazado | Invalid card number |
NOT_ENOUGH_BALANCE | Pago rechazado | Not enough balance |
CVC_DECLINED | Pago rechazado | CVC declined |
FRAUD | Pago rechazado | Fraud detected |
ERROR | Error del procesador | Acquirer error |
Datos de la tarjeta
El formulario simulado valida el formato de la tarjeta de forma realista:
- Numero: Debe tener 13-19 digitos y pasar la validacion Luhn. Ejemplo:
4111 1111 1111 1111(Visa) - Mes de expiracion: Formato
MM(01-12), no puede estar expirada - Ano de expiracion: Formato
YY(2 digitos), no puede estar expirado - CVC: 3 digitos (Visa/Mastercard) o 4 digitos (Amex)
- Nombre del titular: Minimo 3 caracteres
Tip: Para probar un flujo exitoso rapido, usa
4111 1111 1111 1111, expiracion12/30, CVC737, nombreTest User.
---
Preautorizaciones
Si necesitas reservar un importe sin capturarlo inmediatamente (ej: deposito de garantia), usa isPreAuth: true.
Con una preautorizacion puedes despues:
- Capturar el importe total o parcial:
POST /payment/capture - Cancelar la preautorizacion:
POST /payment/cancel - Extender el plazo antes de que expire:
POST /payment/extend
Ver Modificaciones para mas detalle.
---
Divisas aceptadas
Actualmente la External API acepta las siguientes divisas:
| Codigo | Divisa |
|---|---|
EUR | Euro |
GBP | Libra esterlina |
USD | Dolar estadounidense |
Si envias un codigo de divisa no soportado, recibiras un error 400 Bad Request.
---
Errores comunes
| Codigo | HTTP | Causa |
|---|---|---|
| 12001 | 400 | Campo requerido faltante o valor invalido (incluye divisa no soportada) |
| 12002 | 400 | Fecha deliverAt en formato incorrecto (debe ser ISO 8601) |
| 12006 | 400 | Formato de countryCode invalido |
| 12009 | 400 | Pais no soportado |
| 11008 | 403 | API key sin permisos o webcode no coincide |