Simuladores IPF

La plataforma IPF se sitúa entre los sistemas bancarios y los CSM para proporcionar instant servicios de pago.

Como ayuda para las pruebas manuales y exploratorias, así como para fines de aprendizaje y demostración, están disponibles simuladores tanto para sistemas bancarios como para CSMs.

Descripción general

birds eye view
Figura 1. una implementación de IPF interactúa con el banco y CSM simuladores

Banco y CSM los simuladores proporcionan puntos finales de reemplazo para esos sistemas. En la figura anterior, podemos ver cómo un simulador bancario proporciona tanto iniciadores como respondedores.

Los iniciadores típicos pueden incluir los siguientes puntos finales:

  • payment initiation(el Canal)

  • cancelación de pago, devolución de pago, resolución de investigación

Los iniciadores de pago también ofrecen funciones básicas real-time request counters, y apoyar adicional implementation-specific status counters.

Además, el simulador ofrece automático request load generation. Esto puede producirse de manera continua o puede limitarse en el tiempo y/o en la cantidad total de solicitudes.

Los respondedores imitarán el comportamiento esperado de los sistemas bancarios y dependerán estrictamente de la implementación del banco.

CSM Los simuladores también proporcionan iniciadores para pagos entrantes, así como respondedores para pagos salientes y otros mensajes: cancelaciones, devoluciones, investigaciones, etc.

Los respondedores también son conocidos como manejadores de solicitudes y su response latency can be configured. Cada respondedor es identificado por un handler Id único para este propósito, y el list of available responderstambién se puede obtener.

Simulador Genérico IPF NG API

Descripción general

Todos los simuladores IPF implementan el Simulador Genérico IPF. API para apoyar un conjunto común de funcionalidades. Este documento define los elementos comunes de la simulación API. Además, separe más especializado APIs se definirá para casos de uso específicos.

Información de la versión

Versión: 1. 0. 0

Etiquetas

  • Solicitud: Genere y envíe solicitudes individuales/cargadas

  • Configuración: Configure el simulador

  • Estadísticas: Consulte el estado del simulador

  • ResumenDeTransaccionesEnviadas: Consulte las transacciones del simulador

Recursos

Solicitud

Genere y envíe solicitudes individuales/cargadas

Envía un mensaje en bruto que simplemente necesita ser reenviado
PUT /sendRawRequest
Descripción

Normalmente esto representa XML mensaje que queremos transmitir. En este caso, el Simulador IPF no genera ni enriquece la solicitud porque la solicitud en sí es un mensaje completamente contenido.

Parámetros
Tipo Nombre Descripción Esquema

Cuerpo

fullRequest
required

Describe la solicitud que debe enviarse al sistema en prueba.

cadena

Encabezado

Metadatos
optional

Metadatos adicionales que podrían utilizarse para proporcionar más detalles sobre la solicitud.

cadena

Respuestas
Código HTTP Descripción Esquema

200

Se envió con éxito una única solicitud al sistema en prueba.

400

Normalmente el resultado de una solicitud malformada.

No Content

Consume
  • text/plain

Produce
  • application/json

Ejemplo HTTP solicitud
Ruta de solicitud
/sendRawRequest
Cuerpo de la solicitud
"<Document></Document>"
Encabezado de solicitud
"string"
Ejemplo HTTP respuesta
Respuesta 200
{
  "outcome": "ACSP",
  "additionalInfo": { }
}
Envía un único mensaje de solicitud al sistema en prueba
PUT /sendRequest
Descripción

Envía una única carga de mensaje de solicitud al sistema en prueba, tal como se describe en los Detalles de Solicitud.

Parámetros
Tipo Nombre Descripción Esquema

Cuerpo

detallesDeSolicitud
required

Describe la solicitud que debe enviarse al sistema en prueba. Esto se convierte en un formato especializado.

Respuestas
Código HTTP Descripción Esquema

200

Se envió con éxito una única solicitud al sistema en prueba.

400

Normalmente el resultado de un RequestDetails mal formado json carga útil.

No Content

Consume
  • application/json

Ejemplo HTTP solicitud
Ruta de solicitud
/sendRequest
Cuerpo de la solicitud
{
  "transactionId": "fb495cf0d88a11ea87d00242ac130003",
  "amount": {
    "amount": 100,
    "currency": "EUR"
  },
  "originatorName": "John Maynard Keynes",
  "originatorAccount": {
    "iban": "GB29NWBK60161331926819",
    "bic": "DEUTDEFF",
    "accountId": "7928629",
    "ukBankAccount": "object",
    "proxy": "object"
  },
  "beneficiaryName": "Benedetto Cotrugli",
  "beneficiaryAccount": {
    "iban": "GB29NWBK60161331926819",
    "bic": "DEUTDEFF",
    "accountId": "7928629",
    "ukBankAccount": "object",
    "proxy": "object"
  },
  "remittanceInfo": "Remittance information",
  "additionalInfo": {
    "Cdtr. PstlAdr. PstCd": "12820",
    "CdtTrfTxInf[0]. Cdtr. Nm": "Benedetto Cotrugli"
  }
}
Descripción

El campo additionalInfo permite que los datos de la solicitud se enriquezcan con customised valor a través de la implementación de SpelRequestInitiationEnricher.

Ejemplo HTTP respuesta
Respuesta 200
{
  "outcome": "ACSP",
  "additionalInfo": { }
}
Envía un mensaje de Solicitud de Retiro
PUT /bankRecall
Descripción

Permite que se envíe una única carga útil de mensaje de solicitud de recuperación al sistema.

Parámetros
Tipo Nombre Descripción Esquema

Cuerpo

solicitudDeRetiro
required

Detalles de la solicitud de retiro

Respuestas
Código HTTP Descripción Esquema

200

Procesado con éxito.

400

Error General.

No Content

Consume
  • application/json

Ejemplo HTTP solicitud
Ruta de solicitud
/bankRecall
Cuerpo de la solicitud
{
  "transactionId": "81cbf33cd88b11ea87d00242ac130003",
  "cancellationId": "string",
  "cdtrNm": "string"
}
Ejemplo HTTP respuesta
Respuesta 200
{
  "outcome": "ACSP",
  "additionalInfo": { }
}
Envía un mensaje de Solicitud de Devolución
PUT /bankReturn
Descripción

Permite que se envíe una única carga útil de mensaje de solicitud de devolución al sistema.

Parámetros
Tipo Nombre Descripción Esquema

Cuerpo

solicitud De Devolución
required

Detalles de la Solicitud de Devolución

Respuestas
Código HTTP Descripción Esquema

200

Procesado con éxito.

400

Error General.

No Content

Consume
  • application/json

Ejemplo HTTP solicitud
Ruta de solicitud
/bankReturn
Cuerpo de la solicitud
{
  "transactionId": "81cbf33cd88b11ea87d00242ac130003",
  "cdtrNm": "string",
  "amount": 0
}
Ejemplo HTTP respuesta
Respuesta 200
{
  "outcome": "ACSP",
  "additionalInfo": { }
}
Envía un mensaje de Solicitud de Resolución de Investigación
PUT /bankRoi
Descripción

Permite que se envíe una única carga útil de mensaje de solicitud de ROI al sistema.

Parámetros
Tipo Nombre Descripción Esquema

Cuerpo

roiRequest
required

Detalles de la solicitud de ROI

Respuestas
Código HTTP Descripción Esquema

200

Procesado con éxito.

400

Error General.

No Content

Consume
  • application/json

Ejemplo HTTP solicitud
Ruta de solicitud
/bankRoi
Cuerpo de la solicitud
{
  "transactionId": "81cbf33cd88b11ea87d00242ac130003",
  "orgtrNm": "string",
  "rsnCd": "string",
  "rsnPrtry": "string",
  "addtlInf": [ "string" ]
}
Ejemplo HTTP respuesta
Respuesta 200
{
  "outcome": "ACSP",
  "additionalInfo": { }
}
Recupera la carga de solicitudes en curso simulada en el sistema
GET /requestLoad
Descripción

Lee la configuración actual para bulk/ generación de carga de solicitud continua.

Respuestas
Código HTTP Descripción Esquema

200

Las solicitudes por segundo

400

Normalmente el resultado de una RequestLoadConfiguration malformada.json carga útil.

No Content

Ejemplo HTTP solicitud
Ruta de solicitud
/requestLoad
Ejemplo HTTP respuesta
Respuesta 200
{
  "requestsPerSecond": 15,
  "requestsLeft": 350,
  "cutOffTime": "2020-10-23T17:30:00. 000+0000"
}
Establece la carga de solicitud en curso simulada en el sistema bajo prueba
POST /requestLoad
Descripción

Genera transacciones financieras a la tasa dada, de manera continua o en un lote limitado. Se puede utilizar el tamaño y/o la duración para el modo por lotes, omítase para el modo continuo. Establezca la tasa en cero para detenerse.

Parámetros
Tipo Nombre Descripción Esquema

Cuerpo

cuerpo
required

Los ajustes de carga de solicitud deseados

Respuestas
Código HTTP Descripción Esquema

200

Las solicitudes actualizadas por segundo

400

Error general.

No Content

Ejemplo HTTP solicitud
Ruta de solicitud
/requestLoad
Cuerpo de la solicitud
{
  "requestsPerSecond": 15,
  "size": 500,
  "duration": "PT5M"
}
Ejemplo HTTP respuesta
Respuesta 200
{
  "requestsPerSecond": 15,
  "requestsLeft": 350,
  "cutOffTime": "2020-10-23T17:30:00. 000+0000"
}

Configuración

Configure el simulador

Lea todas las configuraciones de los respondedores
GET /responseConfiguration
Descripción

Proporciona configuraciones de respuesta para todos los respondedores. Es útil tener la lista completa de controladores disponibles.

Respuestas
Código HTTP Descripción Esquema

200

La lista de configuraciones de respuesta del simulador

Ejemplo HTTP solicitud
Ruta de solicitud
/responseConfiguration
Ejemplo HTTP respuesta
Respuesta 200
{
  "three-items": [ {
    "handlerId": "accounts",
    "latency": 100
  }, {
    "handlerId": "fraud",
    "latency": 150
  }, {
    "handlerId": "sanctions",
    "latency": 0
  } ]
}
Vea cómo un respondedor específico responde a las solicitudes
GET /responseConfiguration/{handlerId}
Descripción

Proporciona detalles sobre la tasa de rechazo / aciertos, la tasa de mensajes a los que no debe responder y que, por lo tanto, causan un tiempo de espera, así como la latencia que debe aplicarse antes de responder.

Parámetros
Tipo Nombre Descripción Esquema

Ruta

handlerId
required

El identificador del controlador de solicitudes para obtener la configuración. Esto es definido por la implementación.

cadena

Respuestas
Código HTTP Descripción Esquema

200

La configuración de respuesta del respondedor.

404

No se pudo encontrar el controlador de solicitudes con el handlerId proporcionado.

No Content

Ejemplo HTTP solicitud
Ruta de solicitud
/responseConfiguration/string
Ejemplo HTTP respuesta
Respuesta 200
{
  "handlerId": "channel",
  "latency": 100
}
Cambie cómo un respondedor responde a las solicitudes
PUT /responseConfiguration/{handlerId}
Descripción

Establece los detalles de la tasa de rechazo / aciertos, la tasa de mensajes a los que no debe responder y, por lo tanto, causa un tiempo de espera, así como la latencia que debe aplicarse antes de responder.

Parámetros
Tipo Nombre Descripción Esquema

Ruta

handlerId
required

El identificador del controlador de solicitudes a configurar. Esto es definido por la implementación.

cadena

Cuerpo

nueva Configuración
required

La nueva configuración a utilizar incluye el ID del controlador.

Respuestas
Código HTTP Descripción Esquema

200

La configuración de respuesta del simulador fue recibida con éxito.

No Content

400

Normalmente el resultado de una ResponseConfiguration mal formada.json carga útil.

No Content

404

No se pudo encontrar el controlador de solicitudes con el handlerId proporcionado.

No Content

Ejemplo HTTP solicitud
Ruta de solicitud
/responseConfiguration/string
Cuerpo de la solicitud
{
  "handlerId": "channel",
  "latency": 100
}

Estadísticas

Consulte el estado del simulador.

OBTENER /estadísticas
Respuestas
Código HTTP Descripción Esquema

200

Proporciona información estadística sobre el procesamiento de transacciones y sus resultados.

Ejemplo HTTP solicitud
Ruta de solicitud
/statistics
Ejemplo HTTP respuesta
Respuesta 200
{
  "pending": 3,
  "totalSent": 6433,
  "successful": 6421,
  "totalReceived": 0,
  "timedOut": 5,
  "failed": 12,
  "recentLatency": 155,
  "statusCounters": [ {
    "status": "Accepted",
    "count": 6410
  }, {
    "status": "Rejected",
    "count": 11
  } ]
}

Resumen De Transacción Enviada

Consulte las transacciones para el simulador

OBTENER /transacciones
Respuestas
Código HTTP Descripción Esquema

200

Proporciona información detallada sobre transacciones.

Ejemplo HTTP solicitud
Ruta de solicitud
/transactions
Ejemplo HTTP respuesta
Respuesta 200
{
  "totalSent": 1000,
  "averageTransactionTimeMs": 64,
  "startEventTime": "2020-10-23T16:30:50. 000+0000",
  "lastEventTime": "2020-10-23T17:30:50. 000+0000",
  "transactions": [ {
    "id": "TestFlow|nQqyDbhqWrwJysoDVJrRVPTOfPhicTKgkDE",
    "status": "Completed",
    "startTime": "020-10-23T17:30:00Z",
    "completedTime": "2020-10-23T17:30:05. 000+0000",
    "timeTakeMs": 5000
  }, {
    "id": "TestFlow|nQqyDbhqWrwJysoDVJrRVPTOfPhicTKgkAD",
    "startTime": "020-10-23T17:30:00Z",
    "status": "Processing"
  } ]
}

Definiciones

Cuenta

Una representación de una cuenta

Nombre Descripción Esquema

iban
optional

Un IBAN que identifica la cuenta
Ejemplo:`"GB29NWBK60161331926819"`

cadena

bic
optional

Un BIC que identifica la cuenta
Ejemplo:`"DEUTDEFF"`

cadena

accountId
optional

Un identificador genérico para la cuenta
Ejemplo:`"7928629"`

cadena

cuentaBancariaUk
optional

Una representación de una cuenta bancaria del Reino Unido
Ejemplo:`"object"`

proxy
optional

Una representación de la identificación de cuentas proxy
Ejemplo:`"object"`

cuentaBancariaUk

Nombre Descripción Esquema

código de clasificación
required

Identificador de sucursal
Ejemplo:`"21-21-21"`

cadena

número De Cuenta
required

Identificador de cuenta
Ejemplo:`"12345678"`

cadena

proxy

Nombre Descripción Esquema

tipo
optional

Una indicación del tipo de este id de proxy
Ejemplo:`"PAYPAL_ID, EMAIL, PHONE - or any string that the CSM might identify as a proxy identifier type"`

cadena

id
optional

Id de proxy
Ejemplo:`"some.email.address@iconsolutions.com-or any string that conforms to the CSMs proxy id expectations"`

cadena

Código De Moneda

El código de moneda ISO 4217

Tipo: enum (GBP, USD, EUR, CHF, CAD, AUD, NZD, HKD, JPY, CNY)

CantidadFinanciera

Una representación de un monto financiero con la moneda involucrada

Nombre Descripción Esquema

cantidad
optional

La cantidad de dinero en la denominación más baja que no necesita fracciones, por ejemplo, peniques para GBP y centavos para USD.
Ejemplo:`100`

entero (int64)

moneda
optional

MagicValue

Valor mágico para el simulador utilizado para producir la respuesta.

Nombre Descripción Esquema

descripción
optional

Describa el valor mágico y su impacto.
Ejemplo:`"it rejects the payment for this given value"`

cadena

ruta
optional

La ruta en la solicitud para obtener el valor.
Ejemplo:`"request. CreditAccountIdentifier"`

cadena

valor
optional

El valor en la solicitud que se considerará valor mágico.
Ejemplo:`"PT2222666699988888"`

cadena

MagicValues

Una lista de todos los magic values en el simulador.

Type: <MagicValue> matriz

RecallRequestInitiator

Carga útil de solicitud de recall

Nombre Descripción Esquema

transactionId
optional

Un identificador único para la transacción financiera generada
Ejemplo:`"81cbf33cd88b11ea87d00242ac130003"`

cadena

cancellationId
optional

Un valor generado aleatoriamente utilizado para fines de prueba y para hacer coincidir los identificadores alternativos.
Ejemplo:`"string"`

cadena

cdtrNm
optional

Nombre del acreedor
Ejemplo:`"string"`

cadena

DetallesDeSolicitud

Una descripción de una solicitud para enviar al sistema en prueba.

Nombre Descripción Esquema

transactionId
optional

Un identificador único para la transacción financiera generada
Ejemplo:`"fb495cf0d88a11ea87d00242ac130003"`

cadena

cantidad
optional

Cantidad a transferir
Ejemplo:CantidadFinanciera

originatorName
optional

Nombre de la persona que envía fondos
Ejemplo:`"John Maynard Keynes"`

cadena

cuentaOriginadora
optional

Cuenta del deudor
Ejemplo:Cuenta

nombreDelBeneficiario
optional

Nombre de la persona que recibe los fondos
Ejemplo:`"Benedetto Cotrugli"`

cadena

cuentaBeneficiario
optional

Cuenta del acreedor
Ejemplo:Cuenta

información De Remesas
optional

Información de remesas
Ejemplo:`"Remittance information"`

cadena

información Adicional
optional

Reservado para características extendidas de simuladores individuales
Ejemplo:`{ }`

objeto

RequestLoadConfiguration

Una solicitud para generar transacciones financieras a la tasa dada, de manera continua o en un lote limitado. El tamaño y/o la duración pueden utilizarse para el modo por lotes, omítase para el modo continuo. Establezca la tasa en cero para detener.

Nombre Descripción Esquema

solicitudesPorSegundo
required

El número de mensajes de solicitud que se deben enviar cada segundo. Utilice 0 para desactivar el tráfico de carga.
Valor mínimo:`0`
Ejemplo:`15`

entero

tamaño
optional

El número máximo de solicitudes a producir. Ilimitado si no se establece, debe ser positivo en caso contrario.
Valor mínimo:`1`
Ejemplo:`500`

entero (int64)

duración
optional

El tiempo máximo para producir solicitudes es. Formato de duración ISO-8601 PnDTnHnMn.nS, considerando que los días son exactamente 24 horas. Ilimitado si no se establece, debe ser positivo en caso contrario.
Ejemplo:`"PT5M"`

cadena (iso8601)

RequestLoadResponse

Una solicitud para generar transacciones financieras a la tasa dada, de manera continua o en un lote limitado. El tamaño y/o la duración pueden utilizarse para el modo por lotes, omítase para el modo continuo. Establezca la tasa en cero para detener.

Nombre Descripción Esquema

solicitudesPorSegundo
required

La tasa actual de mensajes de solicitud a enviar por segundo. Cero significa que no se está generando tráfico.
Valor mínimo:`0`
Ejemplo:`15`

entero

requestsLeft
optional

El número de solicitudes a producir antes de detenerse. No se establece para solicitudes ilimitadas.
Valor mínimo:`1`
Ejemplo:`350`

entero (int64)

horaCorte
optional

El instant cuando el simulador dejará de producir solicitudes. No está configurado para un tiempo ilimitado.
Ejemplo:`"2020-10-23T17:30:00. 000+0000"`

cadena (fecha-hora)

ResultadoDeLaSolicitud

Si esta solicitud fue aceptada o rechazada

Nombre Descripción Esquema

resultado
required

ACSP para aceptado, RJCT para rechazado
Ejemplo:`"ACSP"`

enum (ACSP, RJCT)

información Adicional
optional

información adicional específica de la implementación
Ejemplo:`{ }`

objeto

Resolución Del Solicitante De Investigación

Resolución de la carga útil de la solicitud de investigación

Nombre Descripción Esquema

transactionId
optional

Un identificador único para la transacción financiera generada
Ejemplo:`"81cbf33cd88b11ea87d00242ac130003"`

cadena

orgtrNm
optional

Nombre de la organización
Ejemplo:`"string"`

cadena

rsnCd
optional

código de razón
Ejemplo:`"string"`

cadena

rsnPrtry
optional

razón prtry
Ejemplo:`"string"`

cadena

addtlInf
optional

Ejemplo:`[ "string" ]`

< string > array

Configuración De Respuesta

Configuración de cómo el simulador maneja las respuestas.

Nombre Descripción Esquema

handlerId
optional

El identificador del controlador
Ejemplo:`"channel"`

cadena

latencia
optional

Cuánto tiempo esperar antes de responder. Definido en milisegundos.
Ejemplo:`100`

entero

ConfiguracionesDeRespuesta

Una lista de todas las configuraciones de respuesta en el simulador.

Type: <ResponseConfiguration> matriz

ReturnRequestInitiator

Carga útil de solicitud de devolución

Nombre Descripción Esquema

transactionId
optional

Un identificador único para la transacción financiera generada
Ejemplo:`"81cbf33cd88b11ea87d00242ac130003"`

cadena

cdtrNm
optional

Nombre del acreedor
Ejemplo:`"string"`

cadena

cantidad
optional

Monto original de liquidación bancaria
Ejemplo:`0`

entero (int64)

Detalles De Transacción Enviada

Detalles de todas las transacciones enviadas

Nombre Descripción Esquema

id
optional

Ejemplo:`"TestFlow|nQqyDbhqWrwJysoDVJrRVPTOfPhicTKgkAD"`

cadena

estado
optional

Ejemplo:`"Accepted"`

cadena

horaDeInicio
optional

El instant cuando el simulador emitió la solicitud.
Ejemplo:`"2020-10-23T17:30:00. 000+0000"`

cadena (fecha-hora)

tiempoCompletado
optional

El instant cuando el simulador recibió la respuesta completada.
Ejemplo:`"2020-10-23T17:30:50. 000+0000"`

cadena (fecha-hora)

timeTakeMs
optional

tiempo requerido para que las transacciones se completen (completedTime-startTime).
Ejemplo:`64333`

entero

Resumen De Transacción Enviada

Detalles sobre transacciones

Nombre Descripción Esquema

totalSent
optional

Número total de transacciones recibidas a través de pagos salientes.
Ejemplo:`1000`

entero

tiempo Promedio Transacción Ms
optional

Tiempo promedio requerido para completar las transacciones.
Ejemplo:`64`

entero

horaInicioEvento
optional

El instant cuando el simulador envió su primera solicitud.
Ejemplo:`"2020-10-23T16:30:50. 000+0000"`

cadena (fecha-hora)

hora DelÚltimo Evento
optional

El instant cuando el simulador recibió su última respuesta.
Ejemplo:`"2020-10-23T17:30:50. 000+0000"`

cadena (fecha-hora)

transacciones
optional

Contadores específicos de implementación, incrementados al inspeccionar el mensaje y derivar un estado.
Ejemplo: [ { "id": "TestFlow| nQqyDbhqWrwJysoDVJrRVPTOfPhicTKgkDE", "estado": "Completado", "startTime": "020-10-23T17:30:00Z", "completedTime": "2020-10-23T17:30:05. 000+0000", "timeTakeMs": 5000 }, { "id": "TestFlow| nQqyDbhqWrwJysoDVJrRVPTOfPhicTKgkAD", "startTime": "020-10-23T17:30:00Z", "estado": "Procesando" } ]

Estadísticas

Información estadística sobre el procesamiento de transacciones y sus resultados.

Nombre Descripción Esquema

pendiente
optional

Número total de transacciones iniciadas pero sin un resultado determinado.
Ejemplo:`3`

entero

totalSent
optional

Número total de transacciones recibidas a través de pagos salientes.
Ejemplo:`6433`

entero

exitoso
optional

Número total de transacciones recibidas a través de pagos salientes, excluyendo las que failed por razones no relacionadas con el negocio.
Ejemplo:`6421`

entero

totalRecibido
optional

Número total de transacciones recibidas a través de pagos entrantes.
Ejemplo:`0`

entero

tiempoAgotado
optional

Número total de transacciones para las cuales no se recibió una respuesta oportuna.
Ejemplo:`5`

entero

failed
optional

Número total de transacciones que failed.
Ejemplo:`12`

entero

latenciaReciente
optional

Latencia promedio reciente observada para que las respuestas lleguen a las solicitudes en ms.
Ejemplo:`155`

entero

contadoresDeEstado
optional

Contadores específicos de implementación, incrementados al inspeccionar el mensaje y derivar un estado.
Ejemplo: [ { "estado": "Aceptado", "count": 6410 }, { "estado": "Rechazado", "count": 11 } ]

<StatusCounter> matriz

StatusCounter

Contadores adicionales para uso en estadísticas. Estos son definidos por la implementación.

Nombre Descripción Esquema

estado
optional

Ejemplo:`"Accepted"`

cadena

contar
optional

Ejemplo:`42`

entero

Explorando el Simulador API

El simulador api puede ser explorado y triggered usando swagger-ui. Se sirve mediante el simulador bajo la ruta /apidocs.

swagger ui

Puede activar el simulador utilizando el swagger ui Try it out botones.

Implementación de un Simulador

Como se indicó anteriormente, podemos implementar tres tipos de simuladores: . Simuladores bancarios. CSM simuladores. Simuladores de respuesta (es decir, controladores de solicitudes)

El marco del simulador viene como un Spring Boot starter, con una API módulo.

Para implementar un simulador, usted debe:

Dependencias del proyecto

Utilice lo siguiente maven configuración:

<dependencies>
    <dependency>
       <groupId>com.iconsolutions.test</groupId>
        <artifactId>ipf-simulator-ng-api</artifactId>
        <version>${simulator.version}</version>
    </dependency>
    <dependency>
       <groupId>com.iconsolutions.test</groupId>
        <artifactId>ipf-simulator-ng-core</artifactId>
        <version>${simulator.version}</version>
    </dependency>
</dependencies>

Aplicación del Simulador

Una aplicación de simulador es simplemente una Spring Boot aplicación que auto-configurará el marco del simulador gracias a la dependencia declared before.

@SpringBootApplication
class ExampleSimulatorApplication {
    public static void main(final String[] args) {
        final var simulator = new SpringApplication(ExampleSimulatorApplication.class);
        simulator.setWebApplicationType(NONE);
        simulator.run(args);
    }
}

Message definition s

El iniciador de la solicitud de pago generará un mensaje de solicitud,enrich lo con el payload of the initiation commandy finalmente envíelo al sistema de destino utilizando el apropiado transport. Para que esto ocurra, el simulador necesita saber cómo generar un template, cómo aplicar el comando de inicio a este y dónde enviarlo.

Tales características se definen utilizando el MessageDefinition característica del Test Framework de Icon.

    @SuppressWarnings("unused")
    enum TestBusinessDomainMessageType implements MessageType {

        MY_REQUEST,
        PAIN001_RAW_REQUEST,

        PACS008_RAW_REQUEST;

        public String getName() {
            return name();
        }

        public Set<String> getAliases() {
            return Set.of();
        }
    }

    @Bean
    MessageDefinition<MyRequest> requestMessageDefinition(final WireMockServer wireMockServer) {
        return new DefaultMessageDefinition.Builder<MyRequest>()
                .withType(MY_REQUEST)  (1)
                .withGenerator(myRequestGenerator()) (2)
                .withDocumentTypeClass(MyRequest.class) (3)
                .withDestination(wireMockServer.url("/endpoint")) (4)
                .withToStringMapper(this::messageAsJson)
                .build();
    }

    private String messageAsJson(Object document) {
        try {
            return objectMapper.writeValueAsString(document);
        } catch (JsonProcessingException e) {
            throw new IconRuntimeException("Could not serialize " + document, e);
        }
    }

    @Bean
    RequestInitiationGenerator<MyRequest> myRequestGenerator() {
        return properties -> new MyRequest();
    }
1 Tipo simbólico
2 Genere una solicitud, tal vez complete con valores aleatorios
3 Java tipo de la solicitud
4 Representación específica del transporte del destino
Algunos transportes pueden no requerir que se especifique un destino en el message definition

Para aplicar el comando de iniciación de pago a la solicitud generada, también necesitamos definir un enricher:

    @Bean
    RequestInitiationEnricher<MyRequest> myRequestEnricher() {
        return (myRequest, parameters) -> {
            Optional.ofNullable(parameters.getTransactionId())
                    .ifPresent(myRequest::setTxnId);

            Optional.ofNullable(parameters.getAmount())
                    .map(RequestAmount::getAmount)
                    .ifPresent(myRequest::setAmount);

            return myRequest;
        };
    }

La solicitud enriquecida será enviada ahora al destino configurado arriba, con el transporte correspondiente.MY_REQUEST como un simbólico message type.

    @Bean
    SpelRequestInitiationEnricher<MyRequest, MyRequest> mySpelRequestEnricher() {

        var CUSTOMISED_TRANSACTION_ID = "myCustomisedTransactionId";
        var legacyFields = List.of(CUSTOMISED_TRANSACTION_ID);
        var spelParserConfiguration = new SpelParserConfiguration(
                true,
                true,
                10
        );

        return new SpelRequestInitiationEnricher<>(
                legacyFields,  (1)
                spelParserConfiguration
        ) {

            @Override
            protected void enrichFromInitiateRequestParameters(MyRequest myRequest,
                                                               InitiateRequestParameters parameters
            ) { (2)
                Optional.ofNullable(parameters.getTransactionId())
                        .ifPresent(myRequest::setTxnId);

                Optional.ofNullable(parameters.getAmount())
                        .map(RequestAmount::getAmount)
                        .ifPresent(myRequest::setAmount);
            }

            @Override
            protected MyRequest getObjectToEnrichFromAdditionalInfo(MyRequest request) {
                (3)
                return request;
            }

            @Override
            protected void enrichUsingLegacyFields(MyRequest request,
                                                   Map.Entry<String, Object> entry
            ) { (4)
                if (CUSTOMISED_TRANSACTION_ID.equals(entry.getKey())) {
                    request.setTxnId(entry.getValue().toString());
                }
            }

        };
    }

El SpelRequestInitiationEnricher proporciona un método enrichFromAdditionalInfo para enriquecer la solicitud de additionalInfo field. La clase hija puede anular el método obsoleto enrichUsingLegacyFields para enriquecer los campos heredados en customized De esta manera, esto debe evitarse ya que no será compatible en un futuro cercano.

1 (Obsoleto) Opcional: especifique los campos heredados de additionalInfo para enriquecer la solicitud.
2 Especifique cómo enriquecer la solicitud a partir de initiateRequestParameters
3 Especifique el objeto objetivo para enriquecer a partir de additionalInfo
4 (Obsoleto) Opcional: sobrescriba este método para especificar cómo utilizar los campos heredados de additionalInfo para enriquecer la solicitud.

Solicitud de Envoltura en Crudo

El envoltorio de solicitud en bruto se utiliza para casos en los que deseamos que el simulador simplemente transmita el mensaje al destino. en lugar de generar y enriquecer el mensaje. Para enviar el mensaje en bruto /sendRawRequest API se utiliza donde el raw request (mensaje completo) debe ser proporcionado. Se puede utilizar un encabezado Metadata opcional para los casos en los que esto API se utiliza para soporte para enviar diferentes mensajes en bruto a diferentes destinos.

Al igual que para enviar una única solicitud con el enriquecedor, necesitamos definir un message definition y lo más importante raw request wrapper. Para esto comenzaremos desde la implementación raw request wrapper implementando com.iconsolutions.simulator.core.interface. Raw Request Wrapper servicio.

    @Bean
    RawRequestWrapper<MyRawPain001Request> rawPain001RequestWrapper() {
        return new RawRequestWrapper<MyRawPain001Request>() {
            @Override
            public MyRawPain001Request map(InitiateWithRawRequest initiateWithRawRequest) { (1)
                return MyRawPain001Request.builder()
                        .rawXml(initiateWithRawRequest.getRawRequest())
                        .build();
            }

            @Override
            public boolean supports(InitiateWithRawRequest initiateWithRawRequest) { (2)
                return "this is pain001 message".equalsIgnoreCase(initiateWithRawRequest.getMetadata());
            }
        };
    }

En ese ejemplo:

1 Estamos transformando InitiateWithRawRequest que sostiene rawRequest y encabezado metadata en nuestro custom Java tipo. Esto se debe simplemente a que nos gustaría crear un separado message definition para esta solicitud de datos en bruto en particular.
2 Verifica el encabezado de metadatos para determinar si este contenedor puede manejar este mensaje. Este metadato es importante en casos donde nos gustaría manejar diferentes solicitudes en bruto.

Después de envolver la solicitud en bruto a nuestro custom Java tipo que necesitamos definir message definition para eso tipo.

Un ejemplo de definir message definition es:

    @Bean
    MessageDefinition<MyRawPain001Request> rawPain001RequestMessageDefinition(final WireMockServer wireMockServer) {
        return new DefaultMessageDefinition.Builder<MyRawPain001Request>()
                .withType(PAIN001_RAW_REQUEST)  (1)
                .withDocumentTypeClass(MyRawPain001Request.class) (2)
                .withDestination(wireMockServer.url("/pain001")) (3)
                .withToStringMapper(MyRawPain001Request::getRawXml) (4)
                .build();
    }
1 Tipo simbólico
2 Nuestro custom Java escriba simplemente para que podamos definir diferentes destinos y/o manejar de manera diferente esta solicitud en bruto particular
3 Destino al que se debe enviar el mensaje. Esto también puede ser gestionado únicamente por los asociados.message transport.
4 Dado que esto representa una solicitud en bruto, podríamos utilizar una cadena.mapper así y utilícelo más tarde en message transport as is.

Message transport

Para llevar el mensaje a su destino, necesitamos definir un MessageTransport.

Esto define una relación entre un simbólico message type y los medios para dirigirlo a su destino, denominado un Transporter.

En este ejemplo estamos configurando un Akka-basado HTTP transporter.

    @Bean
    MessageTransport channelMessageTransport() {
        final ActorSystem actorSystem = ActorSystem.create("test-implementation");
        /* This transporter is asynchronous and does not add messages to the message bucket,
         * therefore it is not suitable for use with JBehave feature tests */
        final var transporter = new AkkaHttpMessageTransporter<>(
                Http.get(actorSystem),
                actorSystem
        );

        return MessageTransportImpl.MessageTransportImplBuilder.aMessageTransportImpl()
                .withSendingSupplier(transporter)
                .withSupportedMessageTypes(Set.of(
                        MY_REQUEST,
                        PAIN001_RAW_REQUEST,
                        PACS008_RAW_REQUEST))
                .build();
    }

Al observar la implementación, podemos ver cómo estamos aprovechando el message definitions:

final class AkkaHttpMessageTransporter<T> implements TransporterWithAckSupport<HttpResponse> {

    @Override
    public CompletionStage<HttpResponse> sendMessageWithAck(MessageDefinition messageDefinition, Message message, String destination) {

        HttpRequest request = httpRequestFor(messageDefinition, message, destination);
        LOGGER.debug("Sending request {}", request);

        return akkaHttp.singleRequest(request)
                // Consume response entity
                .thenCompose(httpResponse -> httpResponse
                        .toStrict(TOSTRICT_TIMEOUT_MILLIS, classicActorSystemProvider)
                        .thenApply(HttpResponse.class::cast));
    }

    private HttpRequest httpRequestFor(
            MessageDefinition<T> messageDefinition, Message<T> message, String destination) {

        return HttpRequest.create(uriFor(destination, messageDefinition))
                .withMethod(httpMethodFor(messageDefinition))
                .withHeaders(headersFor(message))
                .withEntity(HttpEntities.create(
                        ContentTypes.APPLICATION_JSON,
                        messageDefinition.asString(message.getDocument())
                ));
    }

    private String uriFor(String destination, MessageDefinition<T> messageDefinition) {
        return StringUtils.defaultIfBlank(destination, messageDefinition.getDestination()); (1)
    }
    //..
}
1 Recupere la URL objetivo de la relevante message definition

Manejador de solicitudes

Los controladores de solicitudes están ahí para responder a algunas solicitudes. Por ejemplo, cuando nuestro sistema envía una solicitud al endpoint de CUENTAS del banco, queremos simular lo que el banco envía de vuelta a nuestro sistema. Algunos simuladores solo pueden tener un manejador de solicitudes, ya que estos simuladores no generan ninguna solicitud.

Cada controlador de solicitudes debe implementar com.iconsolutions.simulator.api. Interfaz Request Handler. Un ejemplo de manejador de solicitudes ficticias:

final class ExampleSimulatorHandler implements RequestHandler {

    ExampleSimulatorHandler(final WireMockServer wireMockServer) {
        this.wireMockServer = wireMockServer;
        this.latency = 0;

        this.wireMockServer.stubFor(post(urlEqualTo("/endpoint"))
                .withRequestBody(containing("this-is-a-magic-txnId-and-will-cause-a-rejection"))
                .willReturn(aResponse()
                        .withStatus(418)
                        .withBody("FAILED")));

        this.wireMockServer.stubFor(post(urlEqualTo("/endpoint"))
                .withRequestBody(containing("this-is-a-magic-txnId-and-will-be-accepted"))
                .willReturn(aResponse()
                        .withStatus(201)
                        .withBody("SUCCESS")));
    }

}

Gestiona todas las solicitudes que llegan a la ruta "/endpoint" de WireMock. En lugar de WireMock, un manejador real probablemente escucharía en algún Kafka tema o JMS cola, etc.

A continuación, deberá registrarlo con Spring.

@SpringBootApplication
class ExampleSimulatorApplication {

    @Bean
    RequestHandler testSimulatorHandler(final WireMockServer wireMockServer) {
        return new ExampleSimulatorHandler(wireMockServer);
    }

}

Después de eso, este controlador de solicitudes ficticio simplemente devolverá una respuesta ficticia si usted invoca la ruta /endpoint con la carga útil esperada.

Configuración

Toda la configuración externalizada sigue el Spring Boot convenciones.

En resumen, SpringApplication carga propiedades de application.properties archivos en las siguientes ubicaciones y los añade al Entorno de Spring:

  1. A /config subdirectorio del directorio actual

  2. El directorio actual

  3. Un classpath /config paquete

  4. La raíz del classpath

La lista está ordenada por precedencia (las propiedades definidas en ubicaciones más altas en la lista anulan las definidas en ubicaciones más bajas).

También puede utilizar YAML Archivos ('.yml') como una alternativa a '.properties'.

Esta es una lista de las claves de configuración disponibles:

Tabla 1. Servidor HTTP
Clave Predeterminado Descripción

simulador.http.host

0. 0. 0. 0

Interfaz para exponer el Simulador API on

simulador.http.port

55555

Puerto TCP para exponer el Simulador API on

Magic values

El _Manejador de Solicitudes_API expone un método para recuperar una lista de Magic Values para la implementación específica del simulador.

Esta funcionalidad es opcional, y la implementación predeterminada está devolviendo una lista vacía.

La lista de simulador magic values es puramente para fines de documentación. No se supone que proporcionen ninguna funcionalidad más que informativa.

Al observar la implementación, podemos ver cómo definimos magic values:

    @Override
    public List<MagicValue> getMagicValues() {
        return List.of(new MagicValue(
                "Rejects requests with this txnId",
                "txnId",
                "this-is-a-magic-txnId-and-will-cause-a-rejection"));
    }

Métricas

Las métricas deben habilitarse explícitamente, para ello hay varias cosas que debe hacer.

  1. Agregue una dependencia en ipf-simulator-ng-metrics

  2. Configure cinnamon prometheus en su application.conf

  3. Incluya la canela java agente al ejecutar su simulador:`-javaagent:/path/to/cinnamon-agent.jar`

Dependencia de métricas

<dependency>
   <groupId>com.iconsolutions.test</groupId>
    <artifactId>ipf-simulator-ng-metrics</artifactId>
    <version>${project.version}</version>
</dependency>

Configure Cinnamon Prometheus

cinnamon.prometheus {
  exporters += http-server
  use-default-registry = on
}

Las métricas se exponen en un prometheus formato amigable en localhost:9001, a menos que se configure de manera diferente en su application.conf.

cinnamon.prometheus {
  ..
  port = 9999
}

Hay varias métricas proporcionadas de forma predeterminada, y puede agregar las suyas propias con bastante facilidad.

Métricas fuera de la caja

Métrica Descripción

solicitudes_de_aplicación_enviadas

Un recuento de las solicitudes enviadas al sistema objetivo (pueden ser exitosas, pendientes o failed)

solicitudes_de_aplicación_exitosas

Un conteo de solicitudes que recibieron una respuesta del sistema objetivo (con éxito o no)

solicitudes_de_aplicación_fallidas

Un recuento de solicitudes que failed a ser enviado al sistema de destino (Generalmente un fallo de transporte)

solicitudes_de_aplicación_pendientes

Un recuento de solicitudes que aún no han recibido una respuesta del sistema objetivo.

duraciones_de_respuesta_de_la_aplicación

Un resumen del tiempo que tarda el sistema objetivo en responder a las solicitudes.

Custom Métricas

Las métricas son proporcionadas por una instancia de com.lightbend.cinnamon.akka. CinnamonMetrics. Puede declarar un bean dependencia de este tipo y haga lo que desee.

Un ejemplo donde podemos querer contar todas las solicitudes.events(requests and responses in this case)

    @Bean
    RequestEventHandler customMetrics(final CinnamonMetrics cinnamonMetrics) {
        final var customCounter = cinnamonMetrics.createCounter(new Descriptor.Builder()
                .withName("this is a demonstration of a custom metric")
                .withKey("my_custom_counter_metric")
                .build());

        return requestEvent -> customCounter.increment();
    }

Todas las métricas estarán precedidas por application_, por lo que la salida de esto se vería como

# HELP application_my_custom_counter_metric this is a demonstration of a custom metric
# TYPE application_my_custom_counter_metric gauge
application_my_custom_counter_metric{application=".. ExampleSimulatorApplication", host="..",} 60. 0