diff --git a/ERRORES.md b/ERRORES.md deleted file mode 100644 index b089ffb..0000000 --- a/ERRORES.md +++ /dev/null @@ -1,15 +0,0 @@ -# Códigos de Error - -## Errores de Validación (propios de la API) - -| Código | Descripción | -|--------|-------------| -| `VALIDATION_REQUIRED` | Campo obligatorio vacío | -| `VALIDATION_INVALID_NIF` | Formato NIF inválido | -| `VALIDATION_INVALID_DATE` | Formato de fecha inválido | -| `VALIDATION_INVALID_TYPE` | Tipo de factura inválido | -| `VALIDATION_INVALID_AMOUNT` | Importe inválido | - -## Errores AEAT - -Ver `Documentacion de Verifactu/08_errores_y_respuestas.md` para la lista completa de códigos de la AEAT. diff --git a/README.md b/README.md index d115381..f12122d 100644 --- a/README.md +++ b/README.md @@ -1,187 +1,48 @@ -# VeriFactu Middle API +# VeriFactu MidAPI -API intermediaria para el protocolo VeriFactu de la AEAT. +API intermediaria para enviar facturas a la AEAT a través del protocolo VeriFactu. + +Recibe facturas en JSON, calcula el hash encadenado, genera el XML SOAP y lo envía a la AEAT. Si la AEAT no está disponible, guarda la factura localmente (fallback). --- -## Instalación +## Documentación -```bash -go build . -``` +| | | +|---|---| +| [Requisitos y setup](documentacion/PREREQUISITES.md) | Go, Python, OpenSSL, certificado, configuración | +| [API Reference](documentacion/api.md) | Endpoints, requests, responses | +| [Protocolo VeriFactu](documentacion/verifactu.md) | Operaciones, hash, URLs AEAT, XML | +| [Formato de datos](documentacion/formato_datos.md) | NIF, fechas, tipos factura, IVA, ejemplo JSON | +| [Formatos de entrada](documentacion/formatos.md) | native, dolibarr, y cómo añadir nuevos | +| [Arquitectura](documentacion/arqui.md) | Capas, flujo de datos, cifrado | +| [Seguridad](documentacion/seguridad.md) | Certificados, RSA, HTTPS | +| [Certificados](documentacion/certificado_pruebas.md) | Obtener y configurar certificado FNMT | +| [Tokens](documentacion/tokens.md) | Sistema de autenticación por tokens | +| [Configuración](documentacion/config.md) | config.yml, variables de entorno | +| [Testing](documentacion/testing.md) | Tests, depuración | +| [Errores](documentacion/ERRORES.md) | Códigos de error | --- -## Configuración +## Endpoints -Editar `config.yml`: - -```yaml -server: - port: 6789 - -verifactu: - production: false # true para producción - -certificates: - storage_path: ./data/certs/ - cert_file: ./data/certs/personal.p12 - cert_password: TU_CONTRASEÑA - -crypto: - keys_path: ./keys/ - name: "VeriFactu API" - email: "admin@example.com" -``` - -Las claves RSA se generan automáticamente en `./keys/` si no existen. +| Método | Ruta | Descripción | +|--------|------|-------------| +| `GET` | `/api/v1/health` | Health check | +| `GET` | `/api/v1/auth/public-key` | Clave pública RSA | +| `POST` | `/api/v1/auth/register` | Registrar certificado .p12 | +| `GET` | `/api/v1/formats` | Lista formatos disponibles | +| `POST` | `/api/v1/facturas` | Alta de factura (formato auto-detectado) | +| `POST` | `/api/v1/facturas/anular` | Anular factura | --- -## Autenticación - -### 1. Obtener clave pública - -**GET /api/v1/auth/public-key** - -Devuelve la clave pública RSA para cifrar la contraseña del certificado. - -### 2. Registrar certificado - -**POST /api/v1/auth/register** - -```json -{ - "cert_name": "mi-certificado", - "cert_path": "archivo.p12", - "password_encrypted": "BASE64_RSA_ENCRYPTED_PASSWORD" -} -``` - -Respuesta: -```json -{ - "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." -} -``` - -### 3. Usar token - -En todas las peticiones siguientes: -``` -Authorization: Bearer -``` - ---- - -## Estructura de datos - -### Enviar factura (POST /api/v1/facturas) - -```json -{ - "tipo": "alta", - "factura": { - "emisor_nif": "A12345678", - "emisor_nombre": "NOMBRE REGISTRADO EN AEAT", - "num_serie": "2024-001", - "fecha_expedicion": "13-09-2024", - "tipo_factura": "F1", - "descripcion": "Descripción", - "destinatario": { - "nombre": "CLIENTE SL", - "nif": "B98765432" - }, - "iva": [ - {"base": 100.00, "cuota": 21.00, "tipo": 21.00} - ], - "importe_total": 121.00 - }, - "sistema": { - "nombre": "NOMBRE REGISTRADO EN AEAT PARA EL NIF PROVEEDOR", - "nif_proveedor": "A12345678", - "version": "1.0.0" - } -} -``` - -### Anular factura (POST /api/v1/facturas/anular) - -```json -{ - "factura": { - "emisor_nif": "A12345678", - "num_serie": "2024-001", - "fecha_expedicion": "13-09-2024" - }, - "sistema": { - "nombre": "Software", - "nif_proveedor": "A12345678", - "version": "1.0.0" - } -} -``` - ---- - -## Campos obligatorios - -| Campo | Tipo | Descripción | -|-------|------|-------------| -| `tipo` | string | `alta` o `anulacion` | -| `factura.emisor_nif` | string | NIF emisor (9 caracteres) | -| `factura.emisor_nombre` | string | Nombre del emisor exactamente como figura en el censo AEAT | -| `factura.num_serie` | string | Número de serie | -| `factura.fecha_expedicion` | string | Fecha (`dd-mm-yyyy`) | -| `factura.tipo_factura` | string | `F1`, `F2`, `R1`-`R5` | -| `factura.destinatario` | object | Obligatorio para F1, F3 y rectificativas | -| `factura.iva[]` | array | Al menos un registro | -| `factura.importe_total` | number | > 0 | -| `sistema.nombre` | string | Nombre del proveedor del software exactamente como figura en el censo AEAT para su NIF | -| `sistema.nif_proveedor` | string | NIF del proveedor del software | -| `sistema.version` | string | Versión del software | - ---- - -## Respuestas - -### Éxito - -```json -{ - "success": true, - "csv": "ABC123...", - "estado": "Correcto" -} -``` - -### Error de validación - -```json -{ - "success": false, - "error": "validation_failed", - "details": [{"field": "emisor_nif", "message": "invalid NIF format"}] -} -``` - -### Error AEAT - -```json -{ - "success": false, - "error": "aeat_error", - "codigo": "1000", - "mensaje": "Descripción" -} -``` - -Ver `ERRORES.md` para códigos de error completos. - ---- - -## Límites - --Máximo 1.000 registros por solicitud (actualmente 1) -- Entorno actual: pruebas (sandbox) +## Estado +- [x] Alta de facturas con hash encadenado +- [x] Fallback local +- [x] Registro y validación de certificados +- [ ] Anulación con AEAT +- [ ] Consultas +- [ ] Subsanación diff --git a/documentacion/ERRORES.md b/documentacion/ERRORES.md new file mode 100644 index 0000000..1b6783c --- /dev/null +++ b/documentacion/ERRORES.md @@ -0,0 +1,55 @@ +# Códigos de Error + +## Errores de autenticación + +| Código | Descripción | +|--------|-------------| +| `missing_fields` | Faltan campos obligatorios en el registro | +| `invalid_json` | El cuerpo de la petición no es JSON válido | +| `invalid_password_encrypted` | La contraseña cifrada no es Base64 válido | +| `decrypt_failed` | No se pudo descifrar la contraseña con la clave privada RSA | +| `file_not_found` | El archivo de certificado no existe | +| `invalid_password_or_format` | Contraseña incorrecta o formato de certificado inválido | +| `certificate_not_yet_valid` | El certificado aún no es válido | +| `certificate_expired` | El certificado ha expirado | +| `certificate_expiring_soon` | El certificado caduca en menos de 30 días (warning) | +| `temp_storage_failed` | Error guardando el certificado temporal | +| `storage_failed` | Error moviendo el certificado a almacenamiento permanente | +| `token_generation_failed` | Error generando el token de sesión | + +## Errores de validación de facturas + +La API devuelve `validation_failed` con detalles por campo: + +```json +{ + "success": false, + "error": "validation_failed: factura.emisor_nif: invalid NIF format; ..." +} +``` + +| Campo | Error | +|-------|-------| +| `tipo` | Debe ser `alta` o `anulacion` | +| `factura.emisor_nif` | Vacío o formato inválido (esperado: 9 caracteres, regex `^[A-Z0-9]\d{7}[A-Z]$`) | +| `factura.num_serie` | Vacío | +| `factura.fecha_expedicion` | Vacío o formato inválido (esperado: `dd-mm-yyyy`) | +| `factura.tipo_factura` | Vacío o no es `F1`, `F2`, `R1`-`R5` | +| `factura.iva[]` | Sin registros, o base/cuota/tipo negativos | +| `factura.importe_total` | Menor o igual a 0 | +| `sistema.nombre` | Vacío | +| `sistema.nif_proveedor` | Vacío | +| `sistema.version` | Vacío | + +## Errores de procesamiento + +| Código | Descripción | +|--------|-------------| +| `hash_storage_error` | Error leyendo el último hash almacenado | +| `hash_save_error` | Error guardando el hash de la factura actual | +| `aeat_error: ` | Error comunicando con la AEAT | +| `aeat_fault: ` | Fault SOAP devuelto por la AEAT | + +## Errores AEAT + +La AEAT devuelve códigos de error en el campo `CodigoErrorRegistro` de la respuesta SOAP. Consulta la documentación oficial de la AEAT para la lista completa. diff --git a/documentacion/PREREQUISITES.md b/documentacion/PREREQUISITES.md new file mode 100644 index 0000000..9662524 --- /dev/null +++ b/documentacion/PREREQUISITES.md @@ -0,0 +1,167 @@ +# Prerequisites + +## System Requirements + +### Go + +- **Version:** 1.26 or higher +- **Download:** https://go.dev/dl/ +- **Verify installation:** + ```bash + go version + ``` + +### Python 3 + +Required for test scripts and certificate conversion utilities. + +- **Version:** 3.8 or higher +- **Verify installation:** + ```bash + python --version + ``` + +### OpenSSL (optional but recommended) + +Used as an alternative to the Python conversion script for `.p12` to `.pem` certificates. + +- **Linux:** `sudo apt install openssl` / `sudo pacman -S openssl` +- **macOS:** `brew install openssl` +- **Windows:** https://slproweb.com/products/Win32OpenSSL.html +- **Verify installation:** + ```bash + openssl version + ``` + + + +## Project Setup + +### 1. Clone the repository + +```bash +git clone +cd VerifactuMidAPI +``` + +### 2. Install Go dependencies + +```bash +go mod download +``` + +### 3. Create required directories + +```bash +mkdir -p data/certs data keys +``` + +| Directory | Purpose | +|---|---| +| `data/certs/` | Stored `.p12` certificates | +| `data/` | Hash chain records (JSON files per emitter) | +| `keys/` | Auto-generated RSA key pair for password encryption | + +### 4. Configure the application + +Copy or edit `config.yml`: + +```yaml +server: + port: 6789 + +verifactu: + production: false + +certificates: + storage_path: ./data/certs/ + cert_file: ./data/certs/personal.p12 + cert_password: YOUR_PASSWORD + +crypto: + keys_path: ./keys/ + name: "VeriFactu API" + email: "admin@example.com" +``` + +> **Important:** Change `cert_password` and `email` to your own values. + +### 5. Obtain a digital certificate + +VeriFactu requires a **qualified electronic certificate** (eIDAS compliant) in `.p12` or `.pfx` format. + +- **FNMT Persona Fisica** (free): https://www.fnmt.es +- Must be valid and registered with AEAT for the testing environment +- Place it at `./data/certs/personal.p12` (or update `cert_file` in config) + +--- + +## Build & Run + +### Development (auto-reload with source) + +```bash +go run . +``` + +### Production build + +```bash +go build -o verifactu-api . +./verifactu-api +``` + +The server starts on `http://localhost:6789` (or the port configured in `config.yml`). + +--- + +## Verify the installation + +### 1. Health check + +```bash +curl http://localhost:6789/api/v1/health +# Expected: {"status":"ok"} +``` + +### 2. Get public key + +```bash +curl http://localhost:6789/api/v1/auth/public-key +# Expected: {"public_key":""} +``` + +--- + +## Troubleshooting + +### `go: command not found` + +Go is not installed or not in your `PATH`. Add it: + +```bash +# Linux/macOS +export PATH=$PATH:/usr/local/go/bin + +# Windows: add C:\Program Files\Go\bin to system PATH +``` + +### `config.yml not found` + +The API falls back to defaults but logs a warning. Create the file as described in step 4. + +### `certificate expired` / `invalid_password_or_format` + +- Verify the certificate dates with: + ```bash + openssl pkcs12 -in ./data/certs/personal.p12 -info -nokeys + ``` +- Ensure the password in `config.yml` matches the certificate. + +### `403 Forbidden` from AEAT + +The certificate is not authorized in the AEAT testing environment. Contact AEAT or verify your FNMT certificate is enabled for VeriFactu. + +### Hardcoded Windows paths + +`verifactu/client.go` and `internal/cert/validator.go` contain hardcoded Windows paths (`C:\Users\jmest\...`). Update them to your environment or use the `cert_file` config option instead. diff --git a/documentacion/README.md b/documentacion/README.md index 3371778..06b8e93 100644 --- a/documentacion/README.md +++ b/documentacion/README.md @@ -1,91 +1,35 @@ -# VeriFactu MidAPI +# Documentación -API intermediaria para la comunicación con el sistema de facturación VeriFactu de la AEAT (Agencia Estatal de Administración Tributaria) de España. +Índice de documentación técnica de VeriFactu MidAPI. -## Propósito +## Guías -Esta API actúa como intermediaria entre aplicaciones empresariales y el sistema VeriFactu de Hacienda, permitiendo: +| Documento | Descripción | +|-----------|-------------| +| [PREREQUISITES.md](PREREQUISITES.md) | Requisitos del sistema, setup paso a paso, build, run y troubleshooting | +| [ERRORES.md](ERRORES.md) | Códigos de error de la API y de la AEAT | -- **Alta de facturas**: Registro de facturas emitidas en el sistema de Hacienda -- **Anulación de facturas**: Cancelación de facturas previamente registradas -- **Gestión de certificados**: Registro y validación de certificados digitales cualificados -- **Sistema de tokens**: Autenticación mediante tokens para operaciones con facturas +## Referencia técnica -## Características +| Documento | Descripción | +|-----------|-------------| +| [api.md](api.md) | Referencia completa de endpoints, requests y responses | +| [verifactu.md](verifactu.md) | Protocolo VeriFactu: operaciones, hash encadenado, URLs AEAT, formato XML | +| [formato_datos.md](formato_datos.md) | Formatos de datos: NIF, fechas, tipos de factura, IVA, ejemplo JSON | +| [formatos.md](formatos.md) | Formatos de entrada soportados: native, dolibarr, y cómo añadir nuevos | +| [arqui.md](arqui.md) | Arquitectura del proyecto, capas y flujo de datos | -- Implementación en **Go 1.26+** -- Sin dependencias externas -- **Endpoints REST** para integración -- Criptografía **RSA** para cifrado de contraseñas -- certificados almacenados temporalmente para validación, luego de forma permanente -- Tokens de acceso similares a APIs como OpenAI +## Seguridad y certificados -## Estructura del Proyecto +| Documento | Descripción | +|-----------|-------------| +| [seguridad.md](seguridad.md) | Certificados digitales, cifrado RSA, HTTPS, rate limiting | +| [certificado_pruebas.md](certificado_pruebas.md) | Obtención y configuración de certificados FNMT para pruebas | +| [tokens.md](tokens.md) | Sistema de tokens: flujo, almacenamiento, seguridad | -``` -VerifactuMidAPI/ -├── api/ → Handlers HTTP, rutas -├── internal/ → Lógica de negocio -│ ├── cert/ → Gestión de certificados -│ ├── config/ → Configuración -│ └── crypto/ → Criptografía RSA -├── verifactu/ → Cliente SOAP para AEAT -├── documentacion/ → Documentación técnica -└── test/ → Pruebas -``` +## Configuración y testing -## Inicio Rápido - -```bash -# Compilar -go build -o verifactu-api.exe ./main.go - -# Ejecutar -./verifactu-api.exe -``` - -## Configuración - -Editar `config.yml`: - -```yaml -server: - port: 6789 - -verifactu: - production: false # true para producción - -certificates: - storage_path: ./data/certs/ - -crypto: - keys_path: ./keys/ -``` - -## Estado - -- [x] Alta de facturas -- [x] Fallback local (cuando AEAT no disponible) -- [x] Tokens para certificados -- [x] Registro de certificados -- [x] Cifrado RSA de contraseñas -- [x] Anulación de facturas (básico, sin comunicación AEAT) -- [ ] Consultas -- [ ] Subsanación -- [ ] Conexión real con AEAT (necesita certificado FNMT registrado) - -## Pruebas - -```bash -# Tests de certificados (en test/) -python test/run_tests.py - -# Test de factura -python test/test_invoice.py -``` - -## Notas - -- AEAT devuelve 403 Forbidden (necesita certificado cliente) -- Fallback local guarda facturas cuando AEAT no disponible -- Certificado se convierte usando Python cryptography \ No newline at end of file +| Documento | Descripción | +|-----------|-------------| +| [config.md](config.md) | Fichero config.yml, variables de entorno, estructura de directorios | +| [testing.md](testing.md) | Tests de certificados, tests de facturas, depuración |