Documentation for a newer release is available. View Latest

DSL 15 - Texto de error dinámico

Comenzando

Este paso del tutorial utiliza como punto de partida la solución "shared_models_two" del proyecto.

Si en cualquier momento quieres ver la solución de este paso, la encontrarás en la solución add_dynamic_text.

Propósito

En DSL 4 - Uso de un dominio externo, introdujimos el concepto de código de razón para poder enriquecer nuestros eventos con información sobre el motivo subyacente por el que se generó el evento. En aquel momento solo usamos los campos de nombre y descripción para describir el código de razón. En esta sección iremos un paso más allá y mostraremos cómo podemos configurar dinámicamente el texto de nuestro código de razón basándonos en la información del flujo. Así, en lugar de tener solo un mensaje de error genérico usado para todos los pagos, podemos hacer que nuestro mensaje de error sea único para un pago concreto y aportar información más rica.

En nuestro caso, crearemos algunos códigos de razón para nuestra respuesta de fraude y los usaremos para empezar a proporcionar mensajes de error dinámicos. Veamos cómo hacerlo.

Uso del DSL

Placeholders

Lo primero que necesitamos es introducir un nuevo concepto, los "placeholders". Los placeholders son una forma de extraer información de cualquier dato de negocio dado (¡o de una combinación de datos de negocio!) en un formato de cadena simple que podamos usar en mensajes. El placeholder tiene dos propiedades:

  • El nombre del placeholder

  • Una lista de datos de negocio.

Puedes pensar en un placeholder como una función que recibe una lista de elementos de datos de negocio y devuelve una cadena. En el caso más sencillo, los datos de negocio pueden ser ya una cadena en sí mismos; pero en casos más complejos, por ejemplo, podrías querer extraer un campo específico del pacs.008.

Creemos un placeholder para simular que extraemos algunos datos de nuestro pacs.008. Empezamos añadiendo una nueva biblioteca de placeholders haciendo clic derecho sobre nuestro modelo y seleccionando New  v2Flo  Placeholder Library.

Esta biblioteca se comporta como las demás, así que empecemos pulsando "Add placeholder" e introduciendo:

  • un nombre: "Extract from Pacs008"

  • una descripción: "Extract a string from the pacs008"

  • un elemento de datos de negocio: "Customer Credit Transfer"

Cuando termines, debería verse así:

error 1

Ahora usemos nuestro placeholder para crear un texto dinámico para nuestro código de razón.

Texto dinámico

Añadamos un nuevo "Reason code set" a nuestra "Reason code library" existente para nuestro sistema de fraude. Añadirás dos códigos de razón: el primero usará solo una descripción estándar, mientras que el segundo también incluirá la definición de texto dinámico.

Así que empecemos añadiendo dos códigos de razón:

  • Uno con nombre "Simple Reason" y descripción "A simple reason without dynamic text"

  • Uno con nombre "Dynamic Reason" y descripción "A reason with dynamic text".

Para el motivo dinámico, añadamos un mensaje de texto dinámico. Empezamos pulsando Return (o CTRL+SPACE para mostrar las opciones disponibles y seleccionar DynamicText) en el bloque de texto. Ahora podemos escribir nuestro mensaje como cualquier entrada de texto normal. Empecemos escribiendo "This is a dynamic message. The special value is " en el cuadro. Queremos finalizar nuestro texto tomando el valor del placeholder "Extract from Pacs008" que configuramos. Para ello, simplemente pulsa CTRL+SPACE y selecciónalo del desplegable de opciones disponibles.

Cuando termines, nuestro conjunto de códigos de razón y códigos de razón deberían verse así:

error 2

Por último, necesitamos añadir nuestros nuevos códigos de razón de Fraude en nuestra definición de respuesta para la comprobación de fraude para que podamos devolver el código de razón.

error 3

Y eso es todo desde el punto de vista del DSL; pasemos ahora a la implementación.

Implementación en Java

Cambiemos ahora a IntelliJ y veamos cómo conectamos esto en nuestro código de implementación. Como de costumbre, empezaremos ejecutando una build desde una ventana de terminal en el directorio raíz de nuestro proyecto:

mvn clean install

En nuestro trabajo de DSL creamos un placeholder. Lo describimos como una función que toma algunos datos de negocio y devuelve una cadena. ¡Exactamente eso es! Cada placeholder dará lugar a un método en el "Placeholder Port" del dominio.

Veamos el código generado en /domain-root/domain/target; ahora deberíamos encontrar el puerto para definir nuestros placeholders como esto:

package com.iconsolutions.ipf.tutorial;

import com.iconsolutions.iso20022.message.definitions.payments_clearing_and_settlement.pacs008.FIToFICustomerCreditTransferV08;

public interface IpftutorialmodelPlaceholderPort {

  String executeExtractFromPacs008(FIToFICustomerCreditTransferV08 customerCreditTransfer);

}

Aquí vemos que se ha generado una función que toma nuestro FIToFICustomerCreditTransferV08 y devuelve un String. Esto es lo que tendremos que implementar y declarar en nuestra configuración como siempre. Por ahora, lo haremos implementando un mapeo muy simple y constante que devuelve la cadena "Test Mapping". Añádelo a la configuración del tutorial como abajo:

public IpftutorialmodelDomain init(ActorSystem actorSystem, IsoMappingService mappingService, SchedulerPort schedulerAdapter) {
    // All adapters should be added to the domain model
    return new IpftutorialmodelDomain.Builder(actorSystem)
            .withTutorialDomainFunctionLibraryAdapter(input -> CompletableFuture.completedStage(new DuplicateCheckResponseInput.Builder(input.getId(), AcceptOrRejectCodes.Accepted).build()))
            .withAccountingSystemActionAdapter(new SampleAccountingSystemActionAdapter())
            .withFraudSystemActionAdapter(new FraudSystemActionAdapter())
            .withDecisionLibraryAdapter(input ->
                    input.getCustomerCreditTransfer().getCdtTrfTxInf().get(0).getIntrBkSttlmAmt().getValue().compareTo(BigDecimal.TEN)>0 ?
                            RunFraudCheckDecisionOutcomes.FRAUDREQUIRED : RunFraudCheckDecisionOutcomes.SKIPFRAUD)
            .withIpftutorialflowV1AggregateFunctionAdapter(input -> new ExtractCreditorAccountForFlowIpftutorialflowV1AggregateFunctionOutput(input.getCustomerCreditTransfer().getCdtTrfTxInf().get(0).getCdtrAcct()))
            .withIpftutorialflowV2AggregateFunctionAdapter(input -> new ExtractCreditorAccountForFlowIpftutorialflowV2AggregateFunctionOutput(input.getCustomerCreditTransfer().getCdtTrfTxInf().get(0).getCdtrAcct()))
            .withInitiationFlowAggregateFunctionAdapter(parameters -> new MapPain001ToPacs008ForFlowInitiationFlowAggregateFunctionOutput(mappingService.mapPain001toPacs008(parameters.getPaymentInitiation())))
            .withSchedulerAdapter(schedulerAdapter)
            .withCSMServiceActionAdapter(new SampleCSMServiceActionAdapter())
            .withSanctionsSystemActionAdapter(new SampleSanctionsSystemActionAdapter())
            .withPlaceholderAdapter(customerCreditTransfer -> "Test Mapping")
            .build();
}

En este caso, lo único que hace nuestra implementación del placeholder es devolver un texto fijo. En una implementación real, aquí extraerías y formatearías los datos relevantes del customerCreditTransfer.

Comprobación de nuestra solución

Como siempre, comprobemos que nuestra solución funciona. Inicia la aplicación como antes (las instrucciones están disponibles en Revisión de la aplicación inicial si necesitas recordatorio).

A continuación, envía un pago:

curl -X POST localhost:8080/submit | jq

Ahora, cuando el flujo genere un error de fraude con un código de razón que incluya texto dinámico, deberías ver que el mensaje incorpora el valor que devuelve tu placeholder, en lugar de un texto genérico. Esto facilitará diagnósticos más precisos y una experiencia de usuario más clara.

Conclusiones

En esta sección:

  • Presentamos los placeholders como mecanismo para construir mensajes dinámicos.

  • Configuramos códigos de razón con texto dinámico en el DSL.

  • Implementamos el puerto de placeholders en Java y lo integramos en la configuración.

  • Verificamos que los mensajes de error pueden enriquecerse dinámicamente en tiempo de ejecución.