Saltearse al contenido

10 - Mapa de Integraciones Externas

Validated Corrections

  • Slack debe tratarse como integracion configurada pero no activa en el codigo observable del proyecto. Ni SLACK_BOT_USER_OAUTH_TOKEN ni LOG_SLACK_WEBHOOK_URL figuran en .env.example, y el log stack por defecto (LOG_STACK=single) no incluye el canal Slack.
  • Legal Check es TransUnion, no Experian. El UML del modulo (docs/DIAGRAMA_APROBAR_CUPO_UML.md) atribuye el legal check a Experian CrossCore. El codigo (app/Services/LegalCheckService.php:37 y el macro Http::transunion() en app/Providers/AppServiceProvider.php:19-30) lo manda a TransUnion con Basic Auth. Este mapa refleja la realidad de runtime.
  • El gate de aprobacion del cupo (AprobarCupoService::validarSiElClienteTieneSuCupoAprobado()) no es una cadena secuencial estricta: pide >= 5 ProcessType distintos cuyo evento mas reciente del mes en curso sea FINISH_SUCCESS. Las dependencias “criticas” listadas en la seccion 6 son una lectura del flujo intencionado en el frontend, no una garantia del backend.
  • GET /api/v1/datacredito/historial no es solo una comodidad tecnica: es un endpoint publico sensible y debe leerse con implicaciones de seguridad.
  • El webhook de Certicamara necesita una nota mas fuerte: hoy la documentacion no refleja suficientemente que el callback publico carece de una verificacion fuerte visible en el controlador.
  • DataCreditoService mantiene un requestUUID fijo y una cache que no incorpora apellido; ambos detalles son relevantes y deben figurar como riesgos tecnicos del mapa.
  • Este documento es fuerte en inventario, pero debe endurecer su lectura de riesgo operativo y de exposicion.

1. Inventario de Integraciones

#Nombre del ServicioProveedorPropositoMetodo de AutenticacionVariables de Entorno (principales)Variable URL Base
1TransUnion LegalCheckTransUnionScreening en listas legales/regulatorias, verificacion de estado del documentoHTTP Basic Auth (usuario/contrasena)TRANSUNION_API_URL, TRANSUNION_API_USERNAME, TRANSUNION_API_PASSWORDTRANSUNION_API_URL
2Experian CrossCore (Evidente)Experian (via Okta)Validacion de identidad, generacion/verificacion de OTP, cuestionario basado en conocimientoOAuth 2.0 (password grant via Okta) + headers de API keyEXPIRIAN_CROSS_CORE_AUTH_API_URL, EXPIRIAN_CROSS_CORE_API_URL, EXPIRIAN_CROSS_CORE_API_CLIENT_ID, EXPIRIAN_CROSS_CORE_API_CLIENT_SECRET, EXPIRIAN_CROSS_CORE_API_USERNAME, EXPIRIAN_CROSS_CORE_API_PASSWORDEXPIRIAN_CROSS_CORE_API_URL
3DataCredito (HDC Plus)DataCredito / Experian ColombiaReporte de historia crediticia (HDC Plus), credit scoringOAuth 2.0 (endpoint de token personalizado) + headers de API keyDATACREDITO_API_URL, DATACREDITO_CLIENT_ID, DATACREDITO_CLIENT_SECRET, DATACREDITO_USERNAME, DATACREDITO_PASSWORD, DATACREDITO_USER, DATACREDITO_USER_PASSWORDDATACREDITO_API_URL
4Certicamara (ePagare)Certicamara S.A.Creacion de pagare digital, verificacion de firmaToken de API estatico (header x-sckey-token)CERTICAMARA_CREATE_URL, CERTICAMARA_SEARCH_URL, CERTICAMARA_TOKEN, CERTICAMARA_TEMPLATE_IDCERTICAMARA_CREATE_URL / CERTICAMARA_SEARCH_URL
5Core Credito (SHIVAM)Core bancario interno (on-premise)Creacion de cliente en sistema crediticio, registro de compras, consultas de cupo crediticioHeaders personalizados (usuario/contrasena en headers HTTP)CORE_CREDITO_ENDPOINT, CORE_CREDITO_REQ_USER_ID, CORE_CREDITO_REQ_PASSWDCORE_CREDITO_ENDPOINT
6EMCALI MembresiasEMCALI (servicio publico)Validacion de contrato/membresia, chequeo de aprobacion de cuposNinguno (sin autenticacion)EMCALI_MEMBRESIAS_API_URLEMCALI_MEMBRESIAS_API_URL
7Notificaciones SlackSlackConfigurado pero inactivo — no se despachan notificaciones en el codigo observable; LOG_SLACK_WEBHOOK_URL no esta declarado en .env.example y las variables de entorno del bot token estan ausentes del archivo de ejemploBot OAuth token (declarado en config/services.php) + URL de webhook (declarado en config/logging.php)SLACK_BOT_USER_OAUTH_TOKEN, SLACK_BOT_USER_DEFAULT_CHANNEL, LOG_SLACK_WEBHOOK_URLN/A (Driver Slack de Laravel)

2. Detalles de Integraciones

2.1 TransUnion LegalCheck

Clase de servicio: App\Services\LegalCheckService

Macro de cliente HTTP: Http::transunion() (registrado en app/Providers/AppServiceProvider.php:19-30) — URL base desde services.transunion.endpoint + withBasicAuth() usando services.transunion.username/password + timeout de 300s + JSON accept.

El diagrama UML oficial de clases (docs/DIAGRAMA_APROBAR_CUPO_UML.md) describe LegalCheckService integrandose con Experian. El codigo real en LegalCheckService.php:37 invoca Http::transunion()->post('/ws/LegalcheckWSRest/legalcheck/consulta', ...). TransUnion es el proveedor real — el UML esta equivocado en este punto.

MetodoEndpointProposito
manejar(User)POST /ws/LegalcheckWSRest/legalcheck/consultaHacer screening de una persona contra listas legales/regulatorias

Datos enviados:

{
"codigoInformacion": "5766",
"tipoIdentificacion": "<mapped_doc_type>",
"numeroIdentificacion": "<dni>"
}

Datos recibidos: JSON con nombre, estadoDocumento, data (array de hallazgos en listas legales con booleanos list_id y finding).

Manejo de errores:

  • Si el request HTTP falla: lanza ValidationException con un mensaje visible al usuario.
  • Validacion de negocio: compara el nombre retornado contra el nombre del usuario usando similar_text() con un umbral minimo configurable (TRANSUNION_PORCENTAJE_NOMBRE_MINIMO, por defecto 70%).
  • Verifica que estadoDocumento sea “VIGENTE”.
  • Itera los IDs de listas restringidas (configurados en services.transunion.lista_con_restricciones) para buscar hallazgos legales.
  • Retorna DTO LegalCheckResult (patron success/error).
  • Emite eventos ValidationLog para la traza de auditoria.

Comportamiento ante fallo: Lanza ValidationException en fallos HTTP; retorna DTO de error en violaciones de reglas de negocio. Sin logica de reintento. Sin fallback.


2.2 Experian CrossCore (Evidente)

Clase de servicio: App\Services\IdentityValidationService

Macros de cliente HTTP:

  • Http::expirianCrossCoreAuth() — endpoint de auth Okta. El macro expirianCrossCoreAuth() establece un header crudo Authorization desde la variable de entorno EXPIRIAN_CROSS_CORE_AUTH (NO mediante el metodo withBasicAuth() de Laravel). Se espera que el valor del env contenga una cadena de auth pre-formateada (probablemente Basic base64(user:pass))
  • Http::expirianCrossCore() — endpoint de API, JSON accept, timeout de 300s
MetodoEndpointProposito
generateToken()POST /oauth2/aus8jhfmnuDjZO8Q11t7/v1/token (en URL base de auth)Obtener token de acceso OAuth 2.0 via password grant
validarIdentidad(User)POST /op/evidentemaster/v1/identificacion/validarValidacion inicial de identidad
generarOTP(User)POST /da/evidente/v3/otp/initializeInicializar transaccion OTP
(continua)POST /da/evidente/v3/otp/evaluationEvaluar riesgo y enviar OTP a email/telefono
verificarOTP(User, code)POST /da/evidente/v3/otp/verifyVerificar codigo OTP (hash SHA-256)
generarCuestionario(User)POST /op/evidentemaster/v1/identificacion/preguntasGenerar preguntas de autenticacion basadas en conocimiento
verificarCuestionario(User, answers)POST /op/evidentemaster/v1/identificacion/verificarVerificar respuestas del cuestionario

Flujo de autenticacion: Cada llamada de API obtiene un token OAuth fresco desde Okta (password grant con scope expco_evidente_master). El token se pasa como header access_token junto con headers client_secret y client_id.

Datos enviados: Documentos de identidad (tipo/numero), nombres, fechas de expedicion del documento, codigos OTP (hash SHA-256), respuestas del cuestionario.

Datos recibidos: Resultados de validacion (codigos resultado), IDs de transaccion OTP, preguntas/respuestas del cuestionario, flags de aprobacion, scores.

Manejo de errores:

  • Generacion de token: lanza excepciones especificas para unsupported_grant_type, invalid_grant, invalid_scope.
  • Cada metodo retorna DTOs tipados: IdentityValidationResult, GenerateOTPResult, VerifyOTPResult, GenerateQuestionnarieResult, VerifyQuestionnarieResult.
  • La generacion del cuestionario maneja codigos: 00 (inactivo), 02 (ya generado), 07 (preguntas insuficientes), 10/11/12 (limites de intento diario/mensual/anual agotados).
  • Estado cacheado en Redis/cache: {userId}.validacion (60 min), {userId}.transaccion_otp_id (30 min), {userId}.requiere_cuestionario (30 min), {userId}.cuestionario_id (30 min), {userId}.registro_cuestionario (30 min).
  • Emite eventos ValidationLog para cada paso.

Comportamiento ante fallo: Retorna DTOs de error con mensajes visibles al usuario. Sin reintento automatico. Token fresco por llamada (sin caching de token). Estado de validacion previo faltante resulta en retorno temprano con error.


2.3 DataCredito (HDC Plus)

Clase de servicio: App\Services\DataCreditoService

Macro de cliente HTTP: Http::datacredito() — URL base + JSON accept + timeout de 60s

MetodoEndpointProposito
generarToken()POST /spla/oauth2/v1/tokenGenerar token de acceso OAuth
revocarToken(token?)POST /spla/oauth2/v1/revokeTokenRevocar token de acceso
consultarHistorialCredito(...)POST /cs/credit-history/v1/hdcplusConsultar reporte completo de historia crediticia
consultarHistorialPorTipoDocumento(...)(delega al anterior)Wrapper de conveniencia con mapeo de tipo de documento

Flujo de autenticacion: Token OAuth 2.0 obtenido via headers Client_id + Client_secret y body username/password. Token cacheado por 590 segundos (justo bajo el vencimiento de 10 min). Pasado como Bearer token en llamadas subsiguientes.

Datos enviados:

{
"user": "<user>",
"password": "<user_password>",
"identifyingTrx": { "requestUUID": "...", "dateTime": "...", "originatorChannelName": "...", "originatorChannelType": "..." },
"identifyingUser": { "person": { "personId": { "personIdNumber": "...", "personIdType": 1 }, "personLastName": "..." } },
"parameters": [{ "type": "0", "nameParameter": "codigos", "valueParameter": "TOM-001" }]
}

Datos recibidos: Objeto ReportHDCplus que contiene productResult.responseCode, models[].scoreValue, y la data completa de historia crediticia.

Manejo de errores:

  • Refresh de token al recibir 401: limpia cache, genera nuevo token, reintenta el request una vez.
  • Las respuestas exitosas se cachean por 24 horas (datacredito.historial.{doc}.{type}).
  • Las respuestas fallidas limpian la entrada de cache y registran el error.
  • Entorno local: pasa por proxy a traves de https://test.miplante.com/api/v1/datacredito/historial para data mock.
  • Excepciones registradas y re-lanzadas.

Comportamiento ante fallo: Un solo reintento automatico ante 401 (expiracion de token). Sin otros reintentos. Las excepciones se propagan al caller. Cache usado para evitar llamadas redundantes dentro de 24h.

Puntos de riesgo observables en este servicio:

  • requestUUID hard-coded en DataCreditoService.php:185 — cada llamada no-local envia '3fa85f64-5717-4562-b3fc-2c963f66afa6' como identifyingTrx.requestUUID. La linea comentada arriba muestra que la intencion era Str::uuid()->toString(). Esto rompe el contrato de auditoria/correlacion que DataCredito espera y hace que la trazabilidad de requests del lado servidor sea imposible de desambiguar.
  • La clave de cache omite apellido en DataCreditoService.php:141"datacredito.historial.{$personIdNumber}.{$personIdType}" solo usa documento como clave. Si se hacen dos consultas para el mismo DNI con personLastName distinto, la segunda retorna el body cacheado de la primera. El TTL de 24h amplifica el impacto.
  • Bypass mock del entorno local en DataCreditoService.php:153-178 — cuando app()->environment('local'), el servicio no llama a DataCredito en absoluto; emite un HTTP GET a https://test.miplante.com/api/v1/datacredito/historial y reconstruye un Response falso. El mock local es por lo tanto una llamada de red a un hostname compartido con produccion, no a un fixture local.

Consumido por:

  • HDCValidationService — valida la historia crediticia durante el flujo de aprobacion del credito
  • ExtenderCupoService — lee el score crediticio para decisiones de extension de cupo

2.4 Certicamara (ePagare)

Clase de servicio: App\Services\CerticamaraService

Macro de cliente HTTP: Http::certicamara() — header x-sckey-token + JSON + timeout de 60s

MetodoEndpointProposito
crearPagare(datos)POST {CERTICAMARA_CREATE_URL} (default: https://services.eworkflow.co/core/ws/rest/create)Crear pagare digital para firmar
verificarPagare(uuid)GET {CERTICAMARA_SEARCH_URL} (default: https://services.epagare.co/.../search)Verificar estado de firma de un pagare

Datos enviados (crear): Payload basado en template con firma secuencial, datos del firmante (nombre, email, documento, movil), validacion biometrica (E_BIOMETRICS), expiracion de 15 minutos.

Datos recibidos: JSON con UUID del documento, estado, informacion del firmante.

Manejo de errores: Registra exito/error. Retorna data de respuesta como array (array vacio en respuesta null). No se lanzan excepciones ante errores de API — el caller debe verificar el contenido de la respuesta.

Comportamiento ante fallo: Sin logica de reintento. Sin fallback. Solo logging.


2.5 Core Credito (SHIVAM Banking Core)

Clase de servicio: App\Services\CoreCreditoService

Cliente HTTP: Llamadas directas Http::withHeaders(...) (sin macro) — SOAP/XML sobre HTTP, verificacion SSL deshabilitada, timeout de 60s

MetodoAccion SOAP (Req_Mthd)Proposito
crearCliente(datos)modSolicitudCrear/registrar cliente en el sistema crediticio, obtener numero VCARD
registrarCompra(datos)pstPurchaseRegistrar una transaccion de compra contra el credito del cliente
consultarCupo(datos)qryLimitConsultar cupo crediticio disponible, dias en mora, monto en mora

Protocolo: XML SOAP sobre HTTP POST a un endpoint on-premise (default: https://10.241.88.102:8443/...).

Autenticacion: Headers personalizados por request: Req_UserID, Req_PassWD, Req_PrcCode, Req_MsgCode, Req_Type, Res_MsgCode, Log_Channel.

Datos enviados: Envelopes XML SOAP con elementos en namespace IFX que contienen los datos del cliente, detalles de compra o parametros de consulta.

Datos recibidos: Respuestas XML SOAP parseadas a arrays. Campos clave: ErrorID (exito = S0000), ErrorSDesc, ApplNo (numero VCARD), CreditLimitApp, CreditLimitAvl, DaysinArrears, ArrearAmt, TrxnRefNo.

Manejo de errores:

  • Parseo XML con manejo interno de errores de libxml.
  • Normalizacion de encoding de caracteres (eliminacion de BOM, deteccion/conversion de encoding).
  • Excepciones registradas con contexto y re-lanzadas.
  • Exito determinado por ErrorID === 'S0000'.

Comportamiento ante fallo: Sin logica de reintento. Las excepciones se propagan. La verificacion SSL se deshabilita explicitamente para el endpoint IP interno.

Consumido por:

  • CreditoService — orquesta creacion de cliente, registro de compra, consultas de credito
  • ExtenderCupoService — sincroniza los cupos crediticios actualizados despues de la extension

2.6 EMCALI Membresias

Clase de servicio: App\Services\EmcaliMembresiaService

Cliente HTTP: Directo Http::timeout(30)->contentType('application/json') — sin macro, sin auth

MetodoEndpointProposito
consultarMembresia(numero_contrato)GET {EMCALI_MEMBRESIAS_API_URL} (con body JSON)Validar contrato de membresia, obtener cupos aprobados

Datos enviados: {"contrato": <numero_contrato>} como body JSON en request GET.

Datos recibidos: Datos de membresia con niveles de cupo aprobados (claves como {amount}_{installments} con valor "Si"/"No"), o mensajes de error.

Manejo de errores:

  • Configuracion de endpoint faltante: lanza EmcaliMembresiaException.
  • Errores de cliente (4xx): parseados para detectar errores de negocio (contrato requerido, contrato no encontrado) y cacheados por 1 dia.
  • Errores de servidor (5xx): registrados con contexto completo, no cacheados.
  • Excepciones: capturadas, registradas, retorna ConsultarMembresiaResult::unexpectedError().
  • Retorna DTO ConsultarMembresiaResult con contextos de error tipados (enum EmcaliServiceErrorType).

Comportamiento ante fallo: Sin logica de reintento. Las respuestas exitosas y de error de cliente se cachean por 24h. Los errores de servidor y excepciones no se cachean (permite reintento inmediato). Degradacion elegante via patron DTO.

Consumido por:

  • CreditoService::clientePresentaMora() — verifica morosidad
  • ExtenderCupoService::extender() — determina elegibilidad de extension crediticia

2.7 Notificaciones Slack (configurado, inactivo)

Configuracion: Existen dos configuraciones Slack en paralelo pero ninguna esta conectada a rutas de codigo activas en el repositorio observable:

  • config/services.php:31-35 define slack.notifications.bot_user_oauth_token y slack.notifications.channel — destinados al canal de Notification de Laravel. Las claves env SLACK_BOT_USER_OAUTH_TOKEN y SLACK_BOT_USER_DEFAULT_CHANNEL NO estan presentes en .env.example.
  • config/logging.php:90-95 define un canal de log slack con clave LOG_SLACK_WEBHOOK_URL. Esa clave env tampoco esta en .env.example, y LOG_STACK=single en el ejemplo significa que el log stack no incluye Slack.

Autenticacion: Token OAuth de Bot User (services.php) o URL de webhook entrante (logging.php). Ninguno esta configurado por defecto. Ninguna ruta de codigo actualmente despacha una notificacion Slack o publica al canal de log Slack.

Variable EnvDefinida enConectada a codigo activo?
SLACK_BOT_USER_OAUTH_TOKENconfig/services.php (no en .env.example)No
SLACK_BOT_USER_DEFAULT_CHANNELconfig/services.php (no en .env.example)No
LOG_SLACK_WEBHOOK_URLconfig/logging.php (no en .env.example)No (no esta en LOG_STACK=single)

3. Diagrama de Conexion de Servicios Externos

graph TB
    subgraph "Aplicacion MiPlante"
        LSC[LegalCheckService]
        IVS[IdentityValidationService]
        DCS[DataCreditoService]
        CS[CerticamaraService]
        CCS[CoreCreditoService]
        EMS[EmcaliMembresiaService]
        HDCVS[HDCValidationService]
        CRDS[CreditoService]
        EXTS[ExtenderCupoService]
        WH_CERT[Webhook: CerticamaraController]
        API_DC[API: DataCreditoController]
        SLACK[Notificaciones Slack]
    end

    subgraph "Servicios Externos"
        TU[TransUnion<br/>API LegalCheck]
        EXP_AUTH[Experian Okta<br/>Servidor de Auth]
        EXP_API[Experian CrossCore<br/>API Evidente]
        DC[DataCredito<br/>API HDC Plus]
        CERT[Certicamara<br/>API ePagare]
        CORE[Core Credito<br/>SHIVAM Banking]
        EMC[EMCALI<br/>API Membresias]
        SLK[API Slack]
    end

    %% Conexiones de servicios
    LSC -->|"POST /consulta<br/>Basic Auth"| TU
    IVS -->|"POST /token<br/>OAuth Password Grant"| EXP_AUTH
    IVS -->|"POST /validar, /otp/*, /preguntas, /verificar<br/>OAuth Token + API Key"| EXP_API
    DCS -->|"POST /token, /hdcplus<br/>OAuth Token + API Key"| DC
    CS -->|"POST /create, GET /search<br/>API Token"| CERT
    CCS -->|"POST SOAP XML<br/>Headers Personalizados"| CORE
    EMS -->|"GET (body JSON)<br/>Sin Auth"| EMC
    SLACK -->|"Bot OAuth Token"| SLK

    %% Delegacion interna
    HDCVS -.->|delega| DCS
    CRDS -.->|delega| CCS
    CRDS -.->|delega| EMS
    EXTS -.->|delega| EMS
    EXTS -.->|delega| DCS
    EXTS -.->|delega| CRDS

    %% Webhook entrante
    CERT -->|"POST /api/v1/webhooks/certicamara<br/>Callback de evento de firma"| WH_CERT

    %% Proxy de API
    API_DC -.->|delega| DCS

    style TU fill:#f9d71c,stroke:#333
    style EXP_AUTH fill:#f9d71c,stroke:#333
    style EXP_API fill:#f9d71c,stroke:#333
    style DC fill:#f9d71c,stroke:#333
    style CERT fill:#f9d71c,stroke:#333
    style CORE fill:#e74c3c,stroke:#333,color:#fff
    style EMC fill:#f9d71c,stroke:#333
    style SLK fill:#4a154b,stroke:#333,color:#fff

4. Endpoints de Webhook

RutaMetodoControladorLlamador ExternoPropositoAutenticacion
/api/v1/webhooks/certicamaraPOSTWebhooks\CerticamaraControllerCerticamara ePagareRecibe notificaciones de estado de firma para pagares digitalesNinguna. Ruta publica de API solamente bajo el middleware api. El controlador (app/Http/Controllers/Webhooks/CerticamaraController.php) no verifica un header de firma, HMAC, token de shared-secret, o IP de origen. La unica verificacion de autorizacion es Cliente::where('certicamara_uuid', $uuid)->first() — cualquiera que pueda adivinar u obtener un UUID valido puede manejar el pipeline de jobs.

Flujo del webhook:

  1. Certicamara envia POST con uuid y payload de evento cuando ocurre un evento de firma de pagare.
  2. El controlador busca el Cliente por certicamara_uuid.
  3. Si lo encuentra, despacha el job ValidarPagareDigital en la cola creditos con $cliente y $request->all() como payload.
  4. Retorna 200 con JSON de exito, o 404 si no se encontro el cliente.

Riesgo: El controlador del webhook trata cualquier POST con un certicamara_uuid conocido como autentico. Un callback falsificado que incluya el uuid correcto y un valor state puede disparar cambios de estado de pagare (firmado/bloqueado/expirado), que a su vez manejan ProcesarPagareDigital y GenerarCreditoDeVenta, ambos los cuales mutan estado de Venta y OrdenCompra y llaman a SHIVAM. Se debe agregar mitigacion antes de que esta superficie sea considerada segura.

Endpoints de Proxy de API:

RutaMetodoControladorProposito
GET /api/v1/datacredito/historialGETApi\DataCreditoControllerProxy publico de DataCredito. Usado por la rama mock de entorno local de DataCreditoService::consultarHistorialCredito(), pero la ruta misma es publicamente alcanzable en cualquier host que la sirva. Sensibilidad: retorna la historia crediticia completa HDC Plus incluyendo el score. Debe tratarse como un endpoint privilegiado y restringirse.

5. Resumen de Metodos de Autenticacion

IntegracionMetodo de AuthCiclo de Vida del TokenHeaders/Mecanismo
TransUnionHTTP Basic AuthPersistente (credenciales de config)Authorization: Basic base64(user:pass) via withBasicAuth()
Experian CrossCore AuthHeader Authorization crudo (pre-formateado desde env)Por request, sin timeout explicito (usa default de Guzzle/Laravel)Authorization: {EXPIRIAN_CROSS_CORE_AUTH} a Okta (se espera que el valor env contenga la cadena de auth completa, ej. Basic base64(user:pass))
Experian CrossCore APIOAuth 2.0 Bearer + API KeysToken fresco por llamada (sin caching)access_token, client_secret, client_id como headers personalizados
DataCreditoOAuth 2.0 Bearer + API KeysToken cacheado 590s (~10 min)Authorization: Bearer {token} + headers Client_id, Client_secret, ProductId, serverIpAddress
CerticamaraToken de API EstaticoPersistente (config)Header x-sckey-token: {CERTICAMARA_TOKEN}
Core CreditoAuth por Header PersonalizadoPor request (credenciales de config)Req_UserID, Req_PassWD en headers HTTP
EMCALINingunaN/ARequest HTTP sin autenticacion
SlackBot OAuth TokenPersistente (config)Driver estandar de notificacion Slack de Laravel

6. Manejo de Fallos y Comportamiento de Fallback

IntegracionLogica de ReintentoEstrategia de CachingComportamiento de FallbackTimeout
TransUnionNingunoNingunoSe lanza ValidationException; bloquea el flujo de aprobacion crediticia300s
Experian CrossCoreNinguno (el token fresco por llamada evita problemas de token vencido)Estado de validacion cacheado 30-60 min en cache de la appDTO de error retornado; el usuario ve mensaje; puede reintentar manualmente300s (llamadas API) / default (llamadas de auth)
DataCreditoUn reintento ante 401 (refresh de token)Token cacheado 590s; respuestas exitosas cacheadas 24hExcepcion propagada; validacion HDC retorna false; ExtenderCupo retorna sin-extension60s
CerticamaraNingunoNingunoArray vacio retornado; el caller debe manejarlo60s
Core CreditoNingunoNingunoString de mensaje de error retornado desde CreditoService; bloquea creacion de cliente o compra60s
EMCALINinguno (pero errores de servidor no cacheados, permitiendo recall inmediato)Exito y errores de cliente cacheados 24h; errores de servidor NO cacheadosConsultarMembresiaResult::unexpectedError() retornado; en clientePresentaMora() la excepcion se captura y retorna false30s
SlackN/A — ninguna ruta de codigo despacha Slack hoyN/ASin ruta de codigo observable. Las variables env requeridas estan ausentes de .env.example; LOG_STACK=single excluye el canal de log Slack.Default (si alguna vez se invoca)

Dependencias de la Ruta Critica

El flujo de aprobacion crediticia no es un pipeline secuencial estricto. El frontend en ModalValidate.vue lleva al usuario por las fases en orden, pero el gate del backend (AprobarCupoService::validarSiElClienteTieneSuCupoAprobado() en app/Services/AprobarCupoService.php:17-38) solo requiere que al menos 5 valores distintos de ProcessType tengan su evento mas reciente del mes calendario actual como FINISH_SUCCESS. El orden no importa; solo importa “el ultimo intento por process_type este mes fue exitoso”.

Las integraciones consumidas por el flujo:

  1. Legal Check (TransUnion LegalCheckService) — ProcessType::LEGAL_CHECK. El fallo HTTP lanza ValidationException; los fallos de regla de negocio retornan un DTO de error y registran FINISH_UNSUCCESS. El contador de intentos diarios usa como clave los eventos LEGAL_CHECK / START.
  2. Validacion de Identidad (Experian CrossCore IdentityValidationService::validarIdentidad) — ProcessType::IDENTITY_VALIDATION. Pobla el cache {userId}.validacion (60 min) del que dependen las llamadas posteriores a Experian.
  3. Generacion + Verificacion de OTP (Experian CrossCore) — ProcessType::IV_OTP_GENERATION y IV_OTP_VERIFICATION. Ambas fases son requeridas para contar, pero el backend no valida que la verificacion OTP fuera exitosa antes de que el endpoint del cuestionario sea alcanzable — la unica precondicion es el cache {userId}.validacion de la Fase 2.
  4. Cuestionario (Experian CrossCore, condicional) — IV_QUESTION_GENERATION y IV_QUESTION_VERIFICATION. Solo requerido cuando requiere_cuestionario se establecio durante la generacion del OTP; esa flag vive solamente en cache y no se aplica como precondicion del backend.
  5. Validacion HDC (DataCredito via HDCValidationService) — ProcessType::HDC_VALIDATION. El servicio retorna bool; responseCode === 13 desde DataCredito es la unica condicion de exito. Aqui no se exige un score minimo (el mapeo score-a-porcentaje en ExtenderCupoService es post-aprobacion).
  6. Aprobacion del Credito (Fase 7) — no es un ProcessType ni esta limitado por CheckIntentosLimiteDiarios. /usuario/cupo/aprobar corre el gate >= 5, establece cupo_vence_en, luego intenta extender el cupo via ExtenderCupoService (EMCALI + score de DataCredito) y empuja el resultado al Core Credito SHIVAM via CreditoService::crearClienteEnCredito(force=true).
  7. Pagare (Certicamara) — creado en checkout, no durante la aprobacion. El callback asincrono del webhook es la senal de finalizacion.

No hay fallbacks entre servicios (no hay buro de credito alternativo si DataCredito se cae). Las llamadas a HDC, EMCALI y SHIVAM fallan cerradas de formas distintas: HDC retorna false ante cualquier excepcion, EMCALI retorna unexpectedError() y es capturado por clientePresentaMora() (falla abierta), las excepciones de SHIVAM se propagan.

Comportamiento Especifico por Entorno

EntornoComportamiento de DataCredito
localHace proxy de consultas de historia crediticia a https://test.miplante.com/api/v1/datacredito/historial para data mock
staging/productionLlamadas directas a la API de DataCredito

Apendice: Referencia Completa de Variables ENV Por Integracion

TransUnion (4 vars)

  • TRANSUNION_API_URL
  • TRANSUNION_API_USERNAME
  • TRANSUNION_API_PASSWORD
  • TRANSUNION_PORCENTAJE_NOMBRE_MINIMO (default: 70)

Experian CrossCore (13 vars)

  • EXPIRIAN_CROSS_CORE_AUTH_API_URL
  • EXPIRIAN_CROSS_CORE_AUTH
  • EXPIRIAN_CROSS_CORE_API_URL
  • EXPIRIAN_CROSS_CORE_API_CLIENT_SECRET
  • EXPIRIAN_CROSS_CORE_API_CLIENT_ID
  • EXPIRIAN_CROSS_CORE_API_USERNAME
  • EXPIRIAN_CROSS_CORE_API_PASSWORD
  • EXPIRIAN_CROSS_CORE_ID_USUARIO_ENTIDAD
  • EXPIRIAN_CROSS_CORE_COD_PRODUCTO
  • EXPIRIAN_CROSS_CORE_COD_PARAMETRO_PRODUCTO
  • EXPIRIAN_CROSS_CORE_NIT_ENTIDAD
  • EXPIRIAN_CROSS_CORE_CANAL_ENTIDAD
  • EXPIRIAN_CROSS_CORE_API_QUESTIONNAIRE_MIN_SCORE (default: 100)

DataCredito (12 vars)

  • DATACREDITO_API_URL
  • DATACREDITO_CLIENT_ID
  • DATACREDITO_CLIENT_SECRET
  • DATACREDITO_USERNAME
  • DATACREDITO_PASSWORD
  • DATACREDITO_USER
  • DATACREDITO_USER_PASSWORD
  • DATACREDITO_SERVER_IP
  • DATACREDITO_PRODUCT_ID
  • DATACREDITO_INFO_ACCOUNT_TYPE (default: 1)
  • DATACREDITO_ORIGINATOR_CHANNEL_NAME
  • DATACREDITO_ORIGINATOR_CHANNEL_TYPE

Certicamara (5 vars)

  • CERTICAMARA_CREATE_URL (default: https://services.eworkflow.co/core/ws/rest/create)
  • CERTICAMARA_SEARCH_URL (default: https://services.epagare.co/.../search)
  • CERTICAMARA_TOKEN
  • CERTICAMARA_TEMPLATE_ID (default: Pagare_v12025.pdf)
  • CERTICAMARA_OWNER_EMAIL (default: gerenciaadministrativa@miplante.com)

Core Credito (8 vars)

  • CORE_CREDITO_ENDPOINT (default: https://10.241.88.102:8443/...)
  • CORE_CREDITO_REQ_PRC_CODE (default: 038000)
  • CORE_CREDITO_LOG_CHANNEL (default: MP)
  • CORE_CREDITO_REQ_USER_ID
  • CORE_CREDITO_REQ_PASSWD
  • CORE_CREDITO_REQ_MSG_CODE (default: 0340)
  • CORE_CREDITO_REQ_TYPE (default: 038000)
  • CORE_CREDITO_RES_MSG_CODE (default: 0370)

EMCALI (1 var)

  • EMCALI_MEMBRESIAS_API_URL

Slack (3 vars, ninguna en .env.example)

  • SLACK_BOT_USER_OAUTH_TOKEN — referenciada desde config/services.php
  • SLACK_BOT_USER_DEFAULT_CHANNEL — referenciada desde config/services.php
  • LOG_SLACK_WEBHOOK_URL — referenciada desde config/logging.php (canal de log Slack; no esta en LOG_STACK=single)