Saltar al contenido
Payment Emulator LabDocumentaciónEntrar a la consola
En esta página

Funcionamiento interno

Escenarios deterministas de pago

JSON es el canon. El emparejado de escenarios es determinista y admite proveedor,operación, límites de importe y metadatos exactos. JavaScript arbitrario estáprohibido.

3 min de lectura

Índice / Index · English

Traducción de docs/en/runtime/scenarios.md, que es el original. Si discrepan, manda el inglés.

JSON es el canon. El emparejado de escenarios es determinista y admite proveedor, operación, límites de importe y metadatos exactos. JavaScript arbitrario está prohibido.

Los escenarios propios viven sólo como ficheros canónicos en scenarios/<proveedor>/*.json. npm run scenario:compile valida el DSL seguro y genera apps/api/src/modules/scenarios/default-scenarios.ts como representación de ejecución. npm run build, npm run typecheck y npm test corren el compilador antes, lo que impide que el JSON y el comportamiento se desvíen en silencio.

Los escenarios a medida se persisten con POST /scenarios y { "key": "equipo/rechazo-importe-alto", "definition": { ... } }. La respuesta devuelve una referencia de estilo inmutable, como equipo/rechazo-importe-alto@1. Las sesiones a medida tienen que usar la referencia con @versión explícita, para que una versión posterior no cambie en silencio una prueba que ya existía.

El DSL admite a propósito un conjunto pequeño de reglas deterministas. Las claves de acción desconocidas se rechazan; no hay JavaScript, ni eval, ni ejecución de funciones. Compilar o cachear en Redis es una optimización posterior de rendimiento, no la fuente de la verdad.

#then.after — un pago que se mueve solo

json
{
  "provider": "mercadopago",
  "version": 1,
  "when": { "operation": "payment.create" },
  "then": {
    "outcome": "requires_action",
    "after": { "seconds": 5, "outcome": "captured" },
    "webhook": { "enabled": true }
  }
}

Un ticket pagado en el mostrador de una tienda, una transferencia que compensa por la noche, una cartera que redirige y vuelve. En todos ellos el pago cambia mientras la integración no hace nada, y a la integración se lo cuenta un webhook — que es el caso que más fácilmente se implementa mal y el más difícil de reproducir contra un proveedor real, porque no hay petición que puedas mandar para que alguien entre en una tienda.

Regla Por qué
Sólo sobre un pago que acaba en requires_action Es el único estado en que espera a alguien que no es la integración. En los demás quien actúa es la integración, y un temporizador moviéndolo sería el emulador actuando en su nombre
outcome es captured o failed Un pago que espera puede completarse o caducar. Devolver o disputar con un temporizador sería el emulador haciendo una operación que es de la integración
seconds entre 1 y 3600 Un escenario es algo que una prueba espera; uno que dispara mañana es una fila que nadie verá moverse
El dinero siempre es external No entró nadie, y un ticket pagado en una tienda es efectivo llegando del mundo. Debitar un saldo sería inventarse un pagador

El worker lo barre con un reloj. El plano de control puede correr el barrido a demanda — POST /applications/{id}/payments/run-timed-transitions, con un asOf opcional — que es lo que permite a una prueba observar un ticket de cinco minutos sin esperar cinco minutos. La misma razón por la que run-settlement existe a su lado.

Vienen tres: mercadopago/ticket-paid-later, mercadopago/ticket-expired y stripe/bank-transfer-clears.

#Carencia actual del DSL

then.httpStatus y then.fault.once siguen existiendo en la forma TypeScript de un escenario, pero GatewayService no los consume. No uses ninguno de los dos en un escenario nuevo hasta que haya comportamiento y pruebas. Para un fallo HTTP, usa then.fault: { "type": "http_error", "status": 429 }; ése es el camino implementado.

Payment Emulator Lab · RonuSoftwareMIT