diff --git a/backend/.env.example b/backend/.env.example index acea07a6..677e007d 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -28,15 +28,14 @@ CORS_ORIGINS=http://localhost:5173,http://localhost:3000 # License Service LICENSE_CHECK_ENABLED=True -# Factura COVE / VUCEM / API Ventanilla Única -# Llave y IV AES-256-CBC para cifrar la clave FIEL (misma que usa VU y DODA). +# Factura COVE / VUCEM / DODA / API Ventanilla Única +# Llave y IV AES-256-CBC para cifrar la clave FIEL. COVE_FIEL_HASH_KEY= COVE_FIEL_HASH_IV= -# URL del API de digitalización de expediente (ExpedienteExternalService / CoveExternalService) +# URL base del API de Ventanilla Única (COVE, Expediente y DODA comparten esta variable). COVE_API_URL=https://api.vu.aduanasoft.com -# URL del API externo DODA/PITA (alta, status). Misma red que VU. -DODA_API_BASE_URL=http://192.168.1.66:8008 -DODA_API_VERIFY_SSL=False +# Verificación SSL para el API de VU (False en redes internas / dev, True en producción). +COVE_API_VERIFY_SSL=False # Synchronization (Hub & Spoke) SYNC_SECRET_TOKEN=change-this-sync-token-in-production diff --git a/backend/api/v1/modules/a76/expediente_archivos/external_service.py b/backend/api/v1/modules/a76/expediente_archivos/external_service.py index e5957bef..e55dcf6a 100644 --- a/backend/api/v1/modules/a76/expediente_archivos/external_service.py +++ b/backend/api/v1/modules/a76/expediente_archivos/external_service.py @@ -20,7 +20,8 @@ class ExpedienteExternalService: """ def __init__(self) -> None: - self.base_url = (settings.COVE_API_URL or "").strip() or "https://api.vu.aduanasoft.com" + self.base_url = settings.COVE_API_URL.strip() + self.verify_ssl = settings.COVE_API_VERIFY_SSL def digitalizar_archivo_json(self, payload: Dict[str, Any]) -> Dict[str, Any]: """ @@ -41,7 +42,7 @@ class ExpedienteExternalService: ) # connect=10s, read=120s: la subida del PDF puede tomar tiempo en el servidor VU - with httpx.Client(timeout=httpx.Timeout(120.0, connect=10.0), verify=False) as client: + with httpx.Client(timeout=httpx.Timeout(120.0, connect=10.0), verify=self.verify_ssl) as client: response = client.post(url, json=payload) response.raise_for_status() return response.json() @@ -55,7 +56,7 @@ class ExpedienteExternalService: # read=None: sin límite de lectura — VU mantiene la conexión abierta mientras procesa. # El timeout global del polling loop (300 s) actúa como cota máxima real. - with httpx.Client(timeout=httpx.Timeout(None, connect=10.0), verify=False) as client: + with httpx.Client(timeout=httpx.Timeout(None, connect=10.0), verify=self.verify_ssl) as client: response = client.get(url) response.raise_for_status() return response.json() diff --git a/backend/api/v1/modules/a76/factura_cove/external_service.py b/backend/api/v1/modules/a76/factura_cove/external_service.py index ee8af99c..f9811f6c 100644 --- a/backend/api/v1/modules/a76/factura_cove/external_service.py +++ b/backend/api/v1/modules/a76/factura_cove/external_service.py @@ -49,12 +49,8 @@ class CoveExternalService: """ def __init__(self) -> None: - """ - Inicializa el cliente usando COVE_API_URL si está definido; de lo contrario, - usa por defecto el endpoint público documentado en: - https://api.vu.aduanasoft.com/docs#/Factura%20COVE/generar_factura_cove_endpoint_api_v1_factura_cove_generar_factura_cove_post - """ - self.base_url = (settings.COVE_API_URL or "").strip() or "https://api.vu.aduanasoft.com" + self.base_url = settings.COVE_API_URL.strip() + self.verify_ssl = settings.COVE_API_VERIFY_SSL def generate_cove(self, payload: FacturaCoveRequest) -> CoveExternalResult: """ @@ -75,11 +71,7 @@ class CoveExternalService: len(configuracion_vu.get("archivo_key_base64") or ""), ) - # NOTA: verify=False desactiva la validación de certificado SSL. - # Esto es útil en entornos de desarrollo o cuando el entorno no confía - # en el certificado del endpoint externo. En producción, idealmente - # se debería habilitar la verificación SSL. - with httpx.Client(timeout=30.0, verify=False) as client: + with httpx.Client(timeout=30.0, verify=self.verify_ssl) as client: resp = client.post(url, json=json_payload) # Intentar parsear JSON siempre, incluso en errores 4xx/5xx @@ -176,8 +168,7 @@ class CoveExternalService: """ url = f"{self.base_url.rstrip('/')}/api/v1/factura-cove/status/{task_id}" - # Igual que en generate_cove, desactivamos verify solo para entornos de dev. - with httpx.Client(timeout=30.0, verify=False) as client: + with httpx.Client(timeout=30.0, verify=self.verify_ssl) as client: resp = client.get(url) try: diff --git a/backend/api/v1/modules/a76/general_catalogs/doda/external_service.py b/backend/api/v1/modules/a76/general_catalogs/doda/external_service.py index 81c00dec..a972bb66 100644 --- a/backend/api/v1/modules/a76/general_catalogs/doda/external_service.py +++ b/backend/api/v1/modules/a76/general_catalogs/doda/external_service.py @@ -12,28 +12,24 @@ logger = logging.getLogger(__name__) class DodaExternalService: """ - Cliente HTTP para el servicio externo de alta DODA. + Cliente HTTP para el servicio externo de alta DODA (API de Ventanilla Única). Endpoints: POST {base_url}/api/v1/doda/alta GET {base_url}/api/v1/doda/alta-status/{task_id} + + Usa COVE_API_URL como URL base (la misma variable que COVE y Expediente). """ def __init__(self) -> None: - self.base_url = (settings.DODA_API_BASE_URL or "").strip() - self.verify_ssl = settings.DODA_API_VERIFY_SSL + self.base_url = settings.COVE_API_URL.strip() + self.verify_ssl = settings.COVE_API_VERIFY_SSL def post_alta(self, payload: Dict[str, Any]) -> Dict[str, Any]: """ Envía el payload de alta DODA al servicio externo. Retorna {task_id, status, message}. """ - if not self.base_url: - raise ValueError( - "DODA_API_BASE_URL no está configurado. " - "Agrega la variable de entorno con la URL del servicio DODA." - ) - url = f"{self.base_url.rstrip('/')}/api/v1/doda/alta" configuracion_vu = payload.get("configuracion_vu") or {} @@ -56,9 +52,6 @@ class DodaExternalService: """ Consulta el estado de una tarea de alta DODA en el servicio externo. """ - if not self.base_url: - raise ValueError("DODA_API_BASE_URL no está configurado.") - url = f"{self.base_url.rstrip('/')}/api/v1/doda/alta-status/{task_id}" logger.debug("Consultando estado tarea DODA: task_id=%s url=%s", task_id, url) diff --git a/backend/core/config.py b/backend/core/config.py index e41f207b..207f8691 100644 --- a/backend/core/config.py +++ b/backend/core/config.py @@ -52,14 +52,12 @@ class Settings(BaseSettings): # External APIs SITAR_API_URL: str = "api.sitar.aduanasoft.com:880" - COVE_API_URL: str = "" + COVE_API_URL: str = "https://api.vu.aduanasoft.com" + COVE_API_VERIFY_SSL: bool = False COVE_FIEL_HASH_KEY: str = "" COVE_FIEL_HASH_IV: str = "" SITAR_API_USER: str = "" SITAR_API_PASSWORD: str = "" - DODA_API_BASE_URL: str = "" - DODA_API_VERIFY_SSL: bool = False - # SMTP Email Configuration SMTP_HOST: str = "smtp.gmail.com" SMTP_PORT: int = 587 diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 854a98d8..e24f7650 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -175,8 +175,8 @@ services: - COVE_FIEL_HASH_KEY=${COVE_FIEL_HASH_KEY} - COVE_FIEL_HASH_IV=${COVE_FIEL_HASH_IV} - COVE_API_URL=${COVE_API_URL:-https://api.vu.aduanasoft.com} - - DODA_API_BASE_URL=${DODA_API_BASE_URL} - - DODA_API_VERIFY_SSL=${DODA_API_VERIFY_SSL:-False} + - COVE_API_VERIFY_SSL=${COVE_API_VERIFY_SSL:-False} + - VALKEY_URL=${VALKEY_URL:-redis://valkey:6379/0} - CENTRAL_SERVER_URL=${CENTRAL_SERVER_URL:-""} - SYNC_SECRET_TOKEN=${SYNC_SECRET_TOKEN:-change-this-sync-token-in-production} @@ -246,8 +246,8 @@ services: - COVE_FIEL_HASH_KEY=${COVE_FIEL_HASH_KEY} - COVE_FIEL_HASH_IV=${COVE_FIEL_HASH_IV} - COVE_API_URL=${COVE_API_URL:-https://api.vu.aduanasoft.com} - - DODA_API_BASE_URL=${DODA_API_BASE_URL} - - DODA_API_VERIFY_SSL=${DODA_API_VERIFY_SSL:-False} + - COVE_API_VERIFY_SSL=${COVE_API_VERIFY_SSL:-False} + - CSV_IMPORT_STORAGE=${CSV_IMPORT_STORAGE:-minio} - S3_ENDPOINT_URL=${S3_ENDPOINT_URL:-http://minio:9000} - S3_ACCESS_KEY=${S3_ACCESS_KEY:-${MINIO_ROOT_USER:-minioadmin}} @@ -284,8 +284,8 @@ services: - COVE_FIEL_HASH_KEY=${COVE_FIEL_HASH_KEY} - COVE_FIEL_HASH_IV=${COVE_FIEL_HASH_IV} - COVE_API_URL=${COVE_API_URL:-https://api.vu.aduanasoft.com} - - DODA_API_BASE_URL=${DODA_API_BASE_URL} - - DODA_API_VERIFY_SSL=${DODA_API_VERIFY_SSL:-False} + - COVE_API_VERIFY_SSL=${COVE_API_VERIFY_SSL:-False} + - CSV_IMPORT_STORAGE=${CSV_IMPORT_STORAGE:-minio} - S3_ENDPOINT_URL=${S3_ENDPOINT_URL:-http://minio:9000} - S3_ACCESS_KEY=${S3_ACCESS_KEY:-${MINIO_ROOT_USER:-minioadmin}}