diff --git a/.env.example b/.env.example index 1ef60c19..c0578339 100644 --- a/.env.example +++ b/.env.example @@ -61,6 +61,9 @@ S3_USE_SSL=false S3_FILE_STORAGE=true S3_PRESIGNED_EXPIRES_SECONDS=3600 +COVE_FIEL_PASSWORD= +COVE_FIEL_HASH_KEY= + # ----- Sitar API ----- SITAR_API_URL=http://api.sitar.aduanasoft.com SITAR_API_USER=user_sitar_api diff --git a/backend/.env.example b/backend/.env.example index 77ae339c..b3614acf 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -28,6 +28,9 @@ CORS_ORIGINS=http://localhost:5173,http://localhost:3000 # License Service LICENSE_CHECK_ENABLED=True +COVE_FIEL_PASSWORD= +COVE_FIEL_HASH_KEY= + # Synchronization (Hub & Spoke) SYNC_SECRET_TOKEN=change-this-sync-token-in-production # Only for spokes/clients. Leave empty if this is the Hub. diff --git a/backend/api/v1/modules/a76/factura_cove/service.py b/backend/api/v1/modules/a76/factura_cove/service.py index 19df3840..7f51c469 100644 --- a/backend/api/v1/modules/a76/factura_cove/service.py +++ b/backend/api/v1/modules/a76/factura_cove/service.py @@ -28,16 +28,6 @@ from .schemas import ( PersonaCove, ) - -# Clave de encriptado/sal para hash de FIEL. -# TODO: mover a configuración (p. ej. variable de entorno) cuando se habilite el flujo real. -FIEL_ENCRYPTION_KEY = "6a7f92d3c8d1e5b3b0ac23ff1926a7c9" - -# Flag para, en el futuro, activar el uso real de la FIEL hasheada. -# Mientras sea False, se seguirá usando la clave FIEL hardcodeada de pruebas. -USE_HASHED_FIEL_FOR_COVE = True - - @dataclass class InvoiceContext: invoice: InvoiceHeader @@ -92,13 +82,18 @@ class FacturaCoveDomainService: def _hash_fiel(self, raw_fiel: str) -> str: """ Calcula un hash determinista (base64) de la clave FIEL usando una - clave de encriptado fija. Este valor es el que se enviará como - `clave_fiel` al API externo cuando se active USE_HASHED_FIEL_FOR_COVE. + clave de encriptado fija obtenida desde configuración. Este valor es + el que se enviará como `clave_fiel` al API externo cuando exista una + clave FIEL capturada en VU. """ if not raw_fiel: return "" - data = f"{FIEL_ENCRYPTION_KEY}:{raw_fiel}".encode("utf-8") + hash_key = (settings.COVE_FIEL_HASH_KEY or "").strip() + if not hash_key: + return "" + + data = f"{hash_key}:{raw_fiel}".encode("utf-8") digest = hashlib.sha256(data).digest() return base64.b64encode(digest).decode("ascii") @@ -121,12 +116,12 @@ class FacturaCoveDomainService: # Determinar clave FIEL efectiva. # Orden de prioridad: - # 1) Si USE_HASHED_FIEL_FOR_COVE=True y existe vu.fiel_access_key, se hashea. + # 1) Si existe vu.fiel_access_key, se hashea. # 2) En caso contrario, se usa la variable de entorno COVE_FIEL_PASSWORD. clave_fiel_value = "" - if USE_HASHED_FIEL_FOR_COVE and vu and getattr(vu, "fiel_access_key", None): - # Usar la clave capturada en VU, hasheada con hashlib + FIEL_ENCRYPTION_KEY + if vu and getattr(vu, "fiel_access_key", None): + # Usar la clave capturada en VU, hasheada con hashlib + COVE_FIEL_HASH_KEY clave_fiel_value = self._hash_fiel(vu.fiel_access_key or "") if not clave_fiel_value: diff --git a/backend/core/config.py b/backend/core/config.py index e52af02d..5f8bea29 100644 --- a/backend/core/config.py +++ b/backend/core/config.py @@ -54,10 +54,9 @@ class Settings(BaseSettings): # External APIs SITAR_API_URL: str = "api.sitar.aduanasoft.com:880" - # Endpoint base para el servicio externo de Factura COVE COVE_API_URL: str = "" - # Clave FIEL (contraseña) para COVE/VUCEM. Debe configurarse vía entorno en entornos reales. COVE_FIEL_PASSWORD: str = "" + COVE_FIEL_HASH_KEY: str = "" SITAR_API_USER: str = "" SITAR_API_PASSWORD: str = ""