Simuladores IPF

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

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 CSM.

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 estar limitado 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.

CSMLos 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 único handler Id 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. Separe aún 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

  • SentTransactionSummary: Consulte las transacciones del simulador

  • MagicValues: Recupera informes de valores mágicos

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, como se describe en el RequestDetails.

Parámetros
Tipo Nombre Descripción Esquema

Cuerpo

requestDetails
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 malformado RequestDetails carga útil json.

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 addtionalInfo el campo 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 Recordatorio
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

recallRequest
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

returnRequest
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 la generación de carga de solicitudes masivas/continuas.

Respuestas
Código HTTP Descripción Esquema

200

Las solicitudes por segundo

400

Normalmente el resultado de un malformado RequestLoadConfiguration json payload.

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 proporcionado handlerId.

No Contenido

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

newConfiguration
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 un malformado ResponseConfiguration json payload.

No Content

404

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

No Contenido

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.

ELIMINAR /estadísticas
Descripción

Estadísticas claras

Respuestas
Código HTTP Descripción Esquema

200

OK

No Content

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
  } ]
}

SentTransactionSummary

Consulte las transacciones para el simulador.

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

200

Proporciona información detallada sobre transacciones.

MagicValues

Recupera un informe de valor mágico para un controlador de solicitudes específico.

Recupera un informe de valor mágico para un controlador de solicitudes específico
GET /magicValues/{handlerId}
Parámetros
Tipo Nombre Descripción Esquema

Ruta

handlerId
required

El identificador del controlador de solicitudes para obtener los valores mágicos. Esto está definido por la implementación.

cadena

Respuestas
Código HTTP Descripción Esquema

200

La lista de valores mágicos del simulador

Ejemplo HTTP solicitud
Ruta de solicitud
/magicValues/string
Ejemplo HTTP respuesta
Respuesta 200
[ {
  "description" : "it will reject the payment for accounts",
  "path" : "request.CreditAccountIdentifier",
  "value" : "PT2222666699988888"
}, {
  "description" : "it will reject the payment for fraud",
  "path" : "request.AccountIdentifier",
  "value" : "PT2222444411166666"
}, {
  "description" : "it will reject the payment for sanctions",
  "path" : "request.AccountIdentifier",
  "value" : "PT1111444455566666"
} ]
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

ukBankAccount
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"`

ukBankAccount

Nombre Descripción Esquema

código de clasificación
required

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

cadena

accountNumber
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

CurrencyCode

El código de moneda ISO 4217

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

FinancialAmount

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 requiere fracciones, por ejemplo, peniques para GBP y centavos para USD.
Ejemplo:`100`

entero (int64)

moneda
optional

Ejemplo:CurrencyCode

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 cuál es el 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 valores mágicos 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

assgneBic
optional

Asigne BIC
Ejemplo:`"ICONGBA0"`

cadena

assgnrBic
optional

Asigne BIC
Ejemplo:`"ICONGBA1"`

cadena

additionalTransportHeaders
optional

Encabezados de transporte opcionales para incluir con la solicitud. Estos encabezados se fusionarán y tendrán prioridad sobre cualquier encabezado generado por el global.TransportHeaderGenerator configuración.
Ejemplo:`{ "ipf_version_selection": "LATEST" }`

objeto

RequestDetails

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:FinancialAmount

originatorName
optional

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

cadena

originatorAccount
optional

Cuenta del deudor
Ejemplo:Cuenta

beneficiaryName
optional

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

cadena

beneficiaryAccount
optional

Cuenta del acreedor
Ejemplo:Cuenta

remittanceInfo
optional

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

cadena

additionalInfo
optional

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

objeto

additionalTransportHeaders
optional

Encabezados de transporte opcionales para incluir con la solicitud. Estos encabezados se fusionarán con y tendrán prioridad sobre cualquier encabezado generado por el global.TransportHeaderGenerator configuración.
Ejemplo:`{ "ipf_version_selection": "LATEST" }`

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 detenerse.

Nombre Descripción Esquema

requestsPerSecond
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 en formato de duración ISO-8601.PnDTnHnMn.nS con días considerados exactamente de 24 horas. Ilimitado si no se establece, debe ser positivo de lo contrario.
Ejemplo:`"PT5M"`

cadena (iso8601)

transportHeaderDistributions
optional

Distribuciones para los encabezados de transporte generados. Las claves son los nombres de los encabezados, los valores son objetos.mapping valores de encabezado a la distribución porcentual deseada (que debe sumar 100 para cada encabezado). Estas distribuciones anularán cualquier distribución global para el mismo nombre de encabezado en el TransportHeaderGenerator configuración.
Ejemplo:`{ "ipf_version_selection": { "LATEST": 80, "STABLE": 20} }`

objeto

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

requestsPerSecond
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)

cutOffTime
optional

El instante en el que el simulador dejará de producir solicitudes. No está configurado para un tiempo ilimitado.
Ejemplo:`"2020-10-23T17:30:00.000+0000"`

cadena (fecha-hora)

RequestOutcome

Si esta solicitud fue aceptada o rechazada

Nombre Descripción Esquema

resultado
required

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

enum (ACSP, RJCT)

additionalInfo
optional

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

objeto

ResolutionOfInvestigationRequestInitiator

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

additionalTransportHeaders
optional

Encabezados de transporte opcionales para incluir con la solicitud. Estos encabezados se fusionarán y tendrán prioridad sobre cualquier encabezado generado por el global.TransportHeaderGenerator configuración.
Ejemplo:`{ "ipf_version_selection": "LATEST" }`

objeto

ResponseConfiguration

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

ResponseConfigurations

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)

additionalInfo
optional

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

objeto

additionalTransportHeaders
optional

Encabezados de transporte opcionales para incluir con la solicitud. Estos encabezados se fusionarán con y tendrán prioridad sobre cualquier encabezado generado por el global.TransportHeaderGenerator configuración.
Ejemplo:`{ "ipf_version_selection": "LATEST" }`

objeto

SentTransactionDetails

Detalles de todas las transacciones enviadas

Nombre Descripción Esquema

id
optional

Ejemplo:`"TestFlow|nQqyDbhqWrwJysoDVJrRVPTOfPhicTKgkAD"`

cadena

estado
optional

Ejemplo:`"Accepted"`

cadena

startTime
optional

El instante en que el simulador emitió la solicitud.
Ejemplo:`"2020-10-23T17:30:00.000+0000"`

cadena (fecha-hora)

completedTime
optional

El instante en que 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

SentTransactionSummary

Detalles sobre transacciones

Nombre Descripción Esquema

totalSent
optional

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

entero

accumulativeTimeMs
optional

Tiempo acumulativo requerido para completar las transacciones.
Ejemplo:`64333`

número

averageTransactionTimeMs
optional

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

entero

startEventTime
optional

El instante en que el simulador envió su primera solicitud.
Ejemplo:`"2020-10-23T16:30:50.000+0000"`

cadena (fecha-hora)

lastEventTime
optional

El instante en que 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 aquellas que fallaron por razones no relacionadas con el negocio.
Ejemplo:`6421`

entero

totalReceived
optional

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

entero

timedOut
optional

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

entero

fallido
optional

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

entero

recentLatency
optional

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

entero

statusCounters
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

La API del simulador puede ser explorada y triggered usando swagger-ui. Se sirve por el simulador bajo la ruta /apidocs.

swagger ui

Puede activar el simulador utilizando la interfaz de usuario de Swagger.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 deberá:

Dependencias del proyecto

Utilice la siguiente configuración de maven:

<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);
    }
}

Definiciones de mensajes

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 la definición del mensaje.

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 tipo de mensaje simbólico.

    @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());
                }
            }

        };
    }

The 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 de legado 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 de initiateRequestParameters
3 Especifique el objeto objetivo para enriquecer desde additionalInfo
4 (Obsoleto) Opcional: sobrescriba este método para especificar cómo utilizar campos heredados de additionalInfo para enriquecer la solicitud

Solicitud de Envase 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.service. Raw Request Wrapper interfaz.

    @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 una definición de mensaje separada para esta solicitud en bruto particular.
2 Verifica el encabezado de metadatos para determinar si este envoltorio 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 necesitamos definir la definición del mensaje para eso tipo.

Un ejemplo de definir la definición del mensaje 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 solo para que podamos definir diferentes destinos y/o manejar de manera diferente esta solicitud en bruto particular
3 Destino al que debe enviarse el mensaje. Esto también puede ser gestionado únicamente por el transporte de mensajes asociado.
4 Dado que esto representa una solicitud en bruto, podríamos utilizar una cadena.mapper así y utilícelo más tarde en el transporte de mensajes tal como está.

Transporte de mensajes

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

Esto define una relación entre un tipo de mensaje simbólico y los medios para enrutarlo a su destino, llamado un Transporter.

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

@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)
    }

    private Iterable<HttpHeader> headersFor(Message<T> message) {
        return message.getMetadata().getHeaders().entrySet().stream() (2)
                .map(entry -> HttpHeader.parse(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());
    }

    // ...
}
1 Recupere la URL objetivo de la definición de mensaje relevante.
2 Incluya los encabezados de mensaje generados como HTTP encabezados de solicitud. Sin este paso, proporcionado additionalTransportHeaders or Generación de Encabezado de Transporte will simply be ignored.

Generación de Encabezado de Transporte

El simulador incluye un generador de encabezados de transporte impulsado por configuración que puede agregar automáticamente encabezados a las solicitudes salientes basándose en distribuciones ponderadas.

Configuración

La generación del encabezado de transporte se configura a través de Spring Boot propiedades con el prefijo ipf.simulator.generate-transport-headers.

Clave Predeterminado Descripción

ipf.simulator.generate-transport-headers.enabled

false

Si la generación de encabezados está habilitada.

ipf.simulator.generate-transport-headers.headers

Un mapa de nombres de encabezados a sus distribuciones de valores ponderados.

Ejemplo de configuración en application.conf:

ipf.simulator.generate-transport-headers {
  enabled = true
  headers {
    ipf_version_selection {
      LATEST = 80
      OLDEST = 20
    }
    ipf_schema_version {
      1 = 50
      2 = 50
    }
  }
}

En este ejemplo, el 80% de las solicitudes tendrán ipf_version_selection: LATEST y el 20% tendrá ipf_version_selection: OLDEST mientras ipf_schema_version tendrá una división equitativa del 50–50 entre 1 y 2.

Fusión y Sobrescritura de Encabezados

Los encabezados generados por la configuración global pueden ser combinados o reemplazados por los encabezados proporcionados en cada uno. API solicitudes.

  • Solicitudes Únicas: Al utilizar puntos finales como /sendRequest, usted puede proporcionar additionalTransportHeaders en el cuerpo de la solicitud (consulte RequestDetails). Estos encabezados se fusionarán con los encabezados generados. Si existe un nombre de encabezado en ambos, el valor de additionalTransportHeaders tiene prioridad.

  • Solicitudes de Carga: Al iniciar una carga a través de /requestLoad, usted puede especificar transportHeaderDistributions(vea RequestLoadConfiguration). Para cada encabezado especificado en este campo, se utilizará la distribución proporcionada para generar valores, anulando cualquier distribución global para el mismo nombre de encabezado. Los encabezados resultantes se fusionan luego con los encabezados generados a partir de otras distribuciones globales que no fueron anuladas.

Encabezados pasados a través del HTTP la solicitud (ya sea como valores individuales o como distribuciones) siempre anula los proporcionados por el global TransportHeaderGenerator configuración.

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. Request Handler interfaz. 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 WireMock "/endpoint" ruta. En lugar de WireMock un controlador 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 la configuración de application.conf archivos en las siguientes ubicaciones y los añade al Spring Entorno:

  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('.yml') o archivos de propiedades ('.properties') como una alternativa a HOCON('.conf').

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.puerto

55555

Puerto TCP para exponer el Simulador API on

Tabla 2. Generación de Encabezado de Transporte
Clave Predeterminado Descripción

ipf.simulator.generate-transport-headers.enabled

falso

Si la generación de encabezados está habilitada

ipf.simulator.generate-transport-headers.headers

Mapa de nombres de encabezados a sus distribuciones de valores ponderados

Magic values

El _Manejador de Solicitudes_API expone un método para recuperar una lista de Valores Mágicos 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 valores mágicos del simulador es únicamente 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 valores mágicos:

    @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 el agente de Java de canela 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>

Configurar Cinnamon Prometheus

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

Las métricas se exponen en un formato compatible con Prometheus 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 fallidas)

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 no se pudieron enviar 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.

Métricas Personalizadas

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 todos los eventos de solicitud (solicitudes y respuestas en este caso)

    @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_, así 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