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
Orderspuede llegar como array, objeto, cadena vacía onull).
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
| Propiedad | Valor |
|---|---|
artifactId | falabella-client |
groupId | com.hawkersco |
version | 1.0.25-SNAPSHOT |
| Java | 25 |
| Spring Boot | 4.0.6 (spring-boot-starter-parent) |
| Tipo de artefacto | JAR (librería, no ejecutable) |
| Módulos | Proyecto ú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
| Dependencia | Propósito |
|---|---|
spring-boot-starter | Núcleo de Spring Boot y auto-configuración. |
spring-web | RestClient, HttpServiceProxyFactory y anotaciones @HttpExchange. |
org.projectlombok:lombok | Generación de getters/setters/constructores en los DTO. |
com.fasterxml.jackson.core:jackson-annotations | Presente en el classpath, pero no usada para (de)serializar las respuestas: el proyecto usa Gson. |
com.google.code.gson:gson | Serializació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 Java | HTTP | Ruta | Parámetros | Descripción |
|---|---|---|---|---|
getOrdersString(...) | GET | / | Action (ej. GetOrders), Status, Limit, Offset, Version | Lista 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
| Sistema | Protocolo | Dirección | Detalle |
|---|---|---|---|
| Marketplace Falabella Seller Center — API de pedidos | HTTPS, JSON, firma HMAC-SHA256 en query string | Saliente | Ú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):
| Clave | Descripción | Ejemplo de valor |
|---|---|---|
falabella.url | URL base de la API de Falabella Seller Center. | ${FALABELLA_API_URL} |
falabella.user | Identificador de usuario/API (UserID) usado en cada petición. | ${FALABELLA_USER_ID} |
falabella.key | Clave 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 propiedadesfalabella.url,falabella.user,falabella.keyde 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:
- Instalarla en el repositorio Maven local (
./mvnw clean install) o consumir la versión publicada en Artifact Registry. - Añadirla como dependencia en un microservicio consumidor que defina las propiedades
falabella.*de la sección 7. - Verificar el correcto arranque comprobando que el bean
FalabellaClientse 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:
- Checkout —
checkout scm. - Publish to Artifact Registry —
mvn 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
FalabellaClientConfiglanza una excepción propia es si falla la generación de la firma HMAC-SHA256, envolviéndola en unaIOExceptioncon el mensaje"Error generando firma para Falabella". OrdersJsonAdapterlanzaJsonParseExceptionexplícitamente cuando el campoOrdersllega 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
@ControllerAdviceni códigos de error propios, al no exponer API REST propia; los errores HTTP de Falabella se propagan tal cual en elResponseEntity<String>devuelto porFalabellaClient. - 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 DTOOrdersResponseyOrderItemsResponse, ningún método de la interfaz los devuelve directamente — la deserialización con Gson (incluyendo el@JsonAdapterdeOrdersJsonAdapter) debe realizarla el propio consumidor sobre elStringrecibido.- Las clases
LenientBigDecimalTypeAdapteryLenientLongTypeAdapter(paqueteutil) no están registradas ni utilizadas en ningún punto del código de este proyecto (no hay ninguna instancia deGsonBuilderque las registre). El Javadoc deLenientLongTypeAdapterincluso referencia una claseMeliCoOrderResponseque 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ámetroSignature) 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 modificapercentEncode. - El campo
OrdersResponse.Order.extraAttributeses unStringque 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 comoStringporque 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 paraOrdersJsonAdapter, pese a ser la parte más compleja y con más ramas de decisión del proyecto.