#!/usr/bin/env python3 """ Peticion directa al endpoint VeriFactu de la AEAT (sin pasar por la API). Usa mTLS con los PEM ya convertidos en data/certs/. """ import hashlib from datetime import datetime, timezone import requests # Certificado (los PEM no tienen contrasena) CERT_PEM = "data/certs/cert_cert.pem" KEY_PEM = "data/certs/cert_key.pem" # Identidad NIF = "53950250R" NOMBRE = "JOSEP VICENT MESTRE LLOBELL" # Endpoint de pruebas AEAT URL = "https://prewww1.aeat.es/wlpl/TIKE-CONT/ws/SistemaFacturacion/VerifactuSOAP" # Datos de la factura de prueba NUM_SERIE = "TEST-DIRECTO-003" FECHA_EXP = "13-05-2026" TIPO_FACTURA = "F1" BASE = 100.00 CUOTA = 21.00 TOTAL = 121.00 # Registro anterior (encadenamiento) PREV_NUM_SERIE = "TEST-DIRECTO-002" PREV_FECHA_EXP = "13-05-2026" PREV_HUELLA = "B4F12C2C6407438501BBB5C81A8443E78860CD2D736D614C032CEDB4CC521D90" # Timestamp generacion (mismo formato para hash y XML) _now = datetime.now(timezone.utc) FECHA_GEN = _now.strftime("%Y-%m-%dT%H:%M:%S+00:00") def calcular_huella(nif, num_serie, fecha_exp, tipo, cuota, total, prev_hash, fecha_gen): """SHA-256 segun la especificacion VeriFactu (formato key=value&).""" campos = ( f"IDEmisorFactura={nif}&" f"NumSerieFactura={num_serie}&" f"FechaExpedicionFactura={fecha_exp}&" f"TipoFactura={tipo}&" f"CuotaTotal={cuota:.2f}&" f"ImporteTotal={total:.2f}&" f"Huella={prev_hash}&" f"FechaHoraHusoGenRegistro={fecha_gen}" ) print(f" Campos huella : {campos}") return hashlib.sha256(campos.encode()).hexdigest().upper() huella = calcular_huella(NIF, NUM_SERIE, FECHA_EXP, TIPO_FACTURA, CUOTA, TOTAL, PREV_HUELLA, FECHA_GEN) SOAP = f""" {NOMBRE} {NIF} 1.0 {NIF} {NUM_SERIE} {FECHA_EXP} {NOMBRE} {TIPO_FACTURA} Factura de prueba directa {NOMBRE} {NIF} 01 S1 21.00 {BASE:.2f} {CUOTA:.2f} {CUOTA:.2f} {TOTAL:.2f} {NIF} {PREV_NUM_SERIE} {PREV_FECHA_EXP} {PREV_HUELLA} {NOMBRE} {NIF} VerifactuMidAPI 01 1.0.0 1 S N N {FECHA_GEN} 01 {huella} """ print(f"\n{'='*60}") print(f"Endpoint : {URL}") print(f"NIF : {NIF}") print(f"Num serie : {NUM_SERIE}") print(f"Huella : {huella}") print(f"Fecha gen : {FECHA_GEN}") print(f"{'='*60}\n") try: resp = requests.post( URL, data=SOAP.encode("utf-8"), headers={"Content-Type": "text/xml; charset=utf-8", "SOAPAction": ""}, cert=(CERT_PEM, KEY_PEM), verify=True, timeout=30, ) print(f"HTTP Status : {resp.status_code}") print(f"\nRespuesta AEAT:\n{resp.text}") except requests.exceptions.SSLError as e: print(f"[ERROR SSL] Problema con el certificado: {e}") except requests.exceptions.ConnectionError as e: print(f"[ERROR CONEXION] No se pudo conectar: {e}") except Exception as e: print(f"[ERROR] {type(e).__name__}: {e}")