Skip to main content

Falabella Client

1. Descripción general

falabella-client es una librería cliente (JAR) que actúa como fachada HTTP declarativa (@HttpExchange) sobre la API de Falabella Seller Center, según la description de su pom.xml: "Falabella Client".

El proyecto no es un servicio desplegable ni contiene lógica de negocio propia: es una dependencia interna publicada en el registro de artefactos Maven de Hawkers, consumida por los microservicios del ecosistema que necesitan integrar pedidos con el marketplace de Falabella. Encapsula:

  • Firma de cada petición saliente con HMAC-SHA256, calculada sobre los parámetros de consulta ordenados alfabéticamente y codificados según RFC 3986, tal como exige el protocolo de autenticación de la API de Falabella (estilo Amazon MWS/Lazada Open Platform).
  • Inyección automática de los parámetros de autenticación (UserID, Format=JSON, Timestamp, Signature) en cada llamada, de forma transparente para el consumidor.
  • Operaciones declarativas para consultar pedidos (GetOrders) y los ítems de un pedido (GetOrderItems).
  • Deserialización JSON tolerante con Gson, capaz de normalizar las peculiaridades de la API de Falabella (el campo Orders puede llegar como array, objeto, cadena vacía o null).

Dentro del ecosistema de microservicios de Hawkers, falabella-client cumple el mismo rol que otros clientes de marketplace (eci-client, auro-client, dynamics-client): aislar a los microservicios de negocio de los detalles de transporte, firma y serialización específicos de la API externa de Falabella.

2. Información técnica

PropiedadValor
artifactIdfalabella-client
groupIdcom.hawkersco
version1.0.25-SNAPSHOT
Java25
Spring Boot4.0.6 (spring-boot-starter-parent)
Tipo de artefactoJAR (librería, no ejecutable)
MódulosProyecto único (no multi-módulo)

3. Arquitectura y diseño

Estructura de paquetes bajo com.hawkersco.falabellaclient:

com.hawkersco.falabellaclient
├── FalabellaClientApplication.java # @SpringBootApplication (arranque para pruebas locales)
├── client/
│ └── FalabellaClient.java # @HttpExchange — GetOrders y GetOrderItems
├── config/
│ ├── FalabellaAutoConfiguration.java # @AutoConfiguration — bean FalabellaClient
│ └── FalabellaClientConfig.java # ClientHttpRequestInterceptor — firma HMAC-SHA256 + parámetros de auth
├── pojo/
│ ├── OrdersResponse.java # DTO anidado de la respuesta de GetOrders (Head/Body/Order/Address...)
│ ├── OrdersJsonAdapter.java # JsonDeserializer a medida para el campo "Orders" (array/objeto/""/null)
│ └── OrderItemsResponse.java # DTO de la respuesta de GetOrderItems
└── util/
├── LenientBigDecimalTypeAdapter.java # TypeAdapter Gson: BigDecimal tolerante a separador de miles
└── LenientLongTypeAdapter.java # TypeAdapter Gson: Long tolerante a valores decimales

FalabellaAutoConfiguration se registra como auto-configuración Spring Boot en META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports, de modo que cualquier microservicio que añada falabella-client como dependencia obtiene el bean FalabellaClient automáticamente, condicionado (@ConditionalOnProperty) a que existan las propiedades falabella.url, falabella.user y falabella.key.

Flujo de firma y llamada (FalabellaClientConfig)

sequenceDiagram
participant Consumidor as Microservicio consumidor
participant FalabellaClient
participant Interceptor as FalabellaClientConfig
participant Falabella as API Falabella Seller Center

Consumidor->>FalabellaClient: getOrdersString(Action, Status, Limit, Offset, Version)
FalabellaClient->>Interceptor: intercepta petición saliente
Interceptor->>Interceptor: parsea query params existentes
Interceptor->>Interceptor: ordena params alfabéticamente (TreeMap)
Interceptor->>Interceptor: añade UserID, Format=JSON, Timestamp (ISO instant UTC)
Interceptor->>Interceptor: firma con HMAC-SHA256 (falabella.key) → Signature
Interceptor->>Falabella: GET / ?Action=...&Signature=...&Timestamp=...&UserID=...
Falabella-->>FalabellaClient: JSON (ResponseEntity<String>)
FalabellaClient-->>Consumidor: raw JSON string

4. Dependencias principales

DependenciaPropósito
spring-boot-starterNúcleo de Spring Boot y auto-configuración.
spring-webRestClient, HttpServiceProxyFactory y anotaciones @HttpExchange.
org.projectlombok:lombokGeneración de getters/setters/constructores en los DTO.
com.fasterxml.jackson.core:jackson-annotationsPresente en el classpath, pero no usada para (de)serializar las respuestas: el proyecto usa Gson.
com.google.code.gson:gsonSerialización/deserialización JSON de las respuestas (@SerializedName, @JsonAdapter, TypeAdapter a medida).
com.google.cloud.artifactregistry:artifactregistry-maven-wagon (extensión de build)Publicación del JAR en Google Artifact Registry (distributionManagement).

No se listan dependencias de test más allá de spring-boot-starter-test (scope test), usada únicamente por el test de contexto FalabellaClientApplicationTests.

5. API / Endpoints

No aplica como API REST propia. falabella-client no expone endpoints; es una librería consumida como dependencia. FalabellaClientApplication (@SpringBootApplication) existe únicamente como contexto de arranque para desarrollo/pruebas locales.

En su lugar, la interfaz FalabellaClient declara las operaciones disponibles contra la API externa de Falabella Seller Center (ambas apuntan a la ruta raíz /, con la acción indicada vía parámetro Action, siguiendo el estilo de API basada en acciones):

Método JavaHTTPRutaParámetrosDescripción
getOrdersString(...)GET/Action (ej. GetOrders), Status, Limit, Offset, VersionLista paginada de pedidos filtrada por estado. Devuelve JSON crudo (String). Límite documentado en el código: 100 (Limit tope de Falabella).
getOrderItems(...)GET/Action (ej. GetOrderItems), OrderId, VersionÍtems de un pedido concreto. Devuelve JSON crudo (String).

Ambos métodos devuelven ResponseEntity<String> (JSON en crudo); la deserialización a OrdersResponse / OrderItemsResponse mediante Gson es responsabilidad del consumidor, no de FalabellaClient.

Ejemplo simplificado de estructura de respuesta de GetOrders (modelada por OrdersResponse):

{
"SuccessResponse": {
"Head": {
"RequestId": "...",
"RequestAction": "GetOrders",
"ResponseType": "Orders",
"Timestamp": "2025-12-17T10:45:19.424171Z",
"TotalCount": "42"
},
"Body": {
"Orders": {
"Order": [
{
"OrderId": "123456",
"CustomerFirstName": "...",
"GrandTotal": 94850.00,
"Statuses": [ { "Status": "pending" } ],
"Warehouse": { "FacilityId": "...", "SellerWarehouseId": "..." }
}
]
}
}
}
}

6. Integraciones externas

SistemaProtocoloDirecciónDetalle
Marketplace Falabella Seller Center — API de pedidosHTTPS, JSON, firma HMAC-SHA256 en query stringSalienteÚnico sistema externo integrado: consulta de pedidos (GetOrders) y de sus ítems (GetOrderItems).

No hay otras integraciones (colas, SFTP, Dynamics 365, etc.) en este proyecto.

7. Configuración

El fichero src/main/resources/application.properties está excluido de control de versiones (.gitignore); las propiedades deben ser definidas por el microservicio consumidor (o crearse localmente siguiendo el CLAUDE.md del proyecto):

ClaveDescripciónEjemplo de valor
falabella.urlURL base de la API de Falabella Seller Center.${FALABELLA_API_URL}
falabella.userIdentificador de usuario/API (UserID) usado en cada petición.${FALABELLA_USER_ID}
falabella.keyClave secreta usada para firmar las peticiones (HMAC-SHA256).********

Si falta alguna de las tres propiedades, el bean FalabellaClient no se registra (@ConditionalOnProperty), sin error de arranque explícito.

8. Persistencia

No aplica. El proyecto no gestiona base de datos ni realiza persistencia propia; todos los DTO son objetos de transporte para las llamadas HTTP a la API de Falabella.

9. Procesos programados y mensajería

No aplica. No existen @Scheduled, @KafkaListener ni @RabbitListener en el código. La ejecución de las consultas de pedidos e ítems es responsabilidad del microservicio consumidor, que decide cuándo invocarlas.

10. Ejecución en local

Requisitos previos:

  • JDK 25.
  • Maven Wrapper (./mvnw, incluido en el repositorio).
  • Fichero src/main/resources/application.properties (gitignored) con las propiedades falabella.url, falabella.user, falabella.key de la sección 7.

Comandos:

# Build sin tests (equivalente al comportamiento de CI)
./mvnw -B -DskipTests clean install

# Ejecutar todos los tests
./mvnw test

# Ejecutar una clase de test concreta
./mvnw test -Dtest=FalabellaClientApplicationTests

# Ejecutar un método de test concreto
./mvnw test -Dtest=FalabellaClientApplicationTests#contextLoads

Al ser una librería, no se "levanta" como servicio independiente ni expone actuator/health. El único test existente (FalabellaClientApplicationTests#contextLoads) verifica que el contexto de Spring arranca correctamente. Para probarla en local es necesario:

  1. Instalarla en el repositorio Maven local (./mvnw clean install) o consumir la versión publicada en Artifact Registry.
  2. Añadirla como dependencia en un microservicio consumidor que defina las propiedades falabella.* de la sección 7.
  3. Verificar el correcto arranque comprobando que el bean FalabellaClient se inyecta sin error en el microservicio consumidor.

11. Despliegue

El proyecto se publica como artefacto Maven en Google Artifact Registry (artifactregistry://europe-west3-maven.pkg.dev/pi-saldum/pi-repo-maven), no se despliega como contenedor ni servicio.

El Jenkinsfile define un pipeline de dos etapas:

  1. Checkoutcheckout scm.
  2. Publish to Artifact Registrymvn deploy -DskipTests.

Job de Jenkins del proyecto: https://jenkins-pi.hawkersco.net/job/falabella-client/

12. Manejo de errores y logging

  • El único punto donde FalabellaClientConfig lanza una excepción propia es si falla la generación de la firma HMAC-SHA256, envolviéndola en una IOException con el mensaje "Error generando firma para Falabella".
  • OrdersJsonAdapter lanza JsonParseException explícitamente cuando el campo Orders llega con un formato no soportado (una cadena no vacía distinta de las esperadas, o un tipo JSON inesperado), en lugar de fallar silenciosamente o devolver una lista vacía.
  • No hay un @ControllerAdvice ni códigos de error propios, al no exponer API REST propia; los errores HTTP de Falabella se propagan tal cual en el ResponseEntity<String> devuelto por FalabellaClient.
  • No se implementa lógica de reintento ni circuit breaker: es responsabilidad del microservicio consumidor.
  • No hay configuración de logging específica en el proyecto; hereda la configuración de logs del consumidor.

13. Notas y consideraciones

  • FalabellaClient únicamente devuelve JSON en crudo (ResponseEntity<String>); pese a existir los DTO OrdersResponse y OrderItemsResponse, ningún método de la interfaz los devuelve directamente — la deserialización con Gson (incluyendo el @JsonAdapter de OrdersJsonAdapter) debe realizarla el propio consumidor sobre el String recibido.
  • Las clases LenientBigDecimalTypeAdapter y LenientLongTypeAdapter (paquete util) no están registradas ni utilizadas en ningún punto del código de este proyecto (no hay ninguna instancia de GsonBuilder que las registre). El Javadoc de LenientLongTypeAdapter incluso referencia una clase MeliCoOrderResponse que no existe en este repositorio, lo que sugiere que ambos adapters son código reutilizado/copiado de otro cliente del ecosistema (probablemente un cliente de MercadoLibre) y han quedado como código muerto aquí. Pendiente de verificar si se usan desde el lado del consumidor.
  • La firma HMAC-SHA256 se calcula dos veces sobre la query string ordenada: una vez dentro de generateSignature (sin el parámetro Signature) y de nuevo al reconstruir la URL final con todos los parámetros incluida la firma; es un patrón correcto pero sensible a cambios accidentales en el orden/codificación si se modifica percentEncode.
  • El campo OrdersResponse.Order.extraAttributes es un String que contiene JSON embebido sin deserializar (comentado explícitamente en el código: "es un JSON embebido en String"); el consumidor debe parsearlo por separado si necesita esos datos.
  • Varios campos que semánticamente son numéricos o booleanos (InvoiceRequired, TotalCount, ItemsCount) se modelan como String porque la API de Falabella los devuelve como cadenas (ej. "InvoiceRequired": "false"), comportamiento documentado con comentarios en el propio código.
  • No existen tests más allá del test de contexto (contextLoads); no hay tests unitarios para la lógica de firma HMAC ni para OrdersJsonAdapter, pese a ser la parte más compleja y con más ramas de decisión del proyecto.