mariodevv.com

PHP FacturaE

Librería PHP moderna para generar, validar y firmar facturas electrónicas FacturaE. API fluent, firma XAdES-EPES, cero dependencias.

Introducción

PHP FacturaE es una librería moderna y tipada para generar, validar y firmar facturas electrónicas en formato FacturaE — el estándar oficial de facturación electrónica en España.

¿Qué es FacturaE?

FacturaE es el formato de factura electrónica basado en XML exigido por las Administraciones Públicas españolas (AAPP) y ampliamente adoptado en el sector privado. Está gestionado por la Agencia Tributaria (AEAT) y garantiza el cumplimiento fiscal y la interoperabilidad.

¿Por qué PHP FacturaE?

PHP FacturaE proporciona una API fluent y tipada que hace que crear facturas conformes sea intuitivo y libre de errores:

Invoice::create('FAC-001')
->series('A')
->date('2025-03-01')
->seller(Party::company('B12345678', 'Mi Empresa S.L.')
->address('C/ Mayor 10', '28013', 'Madrid', 'Madrid'))
->buyer(Party::person('12345678Z', 'Laura', 'Gómez', 'Ruiz')
->address('C/ Sol 3', '28012', 'Madrid', 'Madrid'))
->line('Diseño logotipo', price: 450.00, vat: 21)
->transferPayment(iban: 'ES91 2100 0418 4502 0005 1332', dueDate: '2025-03-31')
->export('factura.xml');

Características principales

  • API fluent con Enums — Sin arrays asociativos ni constantes sueltas — todo tipado con enums y propiedades readonly de PHP 8.2+
  • Firma digital XAdES-EPES — Soporte nativo para certificados PKCS#12 (.pfx) y PEM con sellado de tiempo TSA opcional
  • Validación XSD — Validación automática contra los esquemas oficiales FacturaE 3.2, 3.2.1 y 3.2.2
  • Cero dependencias — Solo extensiones PHP estándar: ext-openssl, ext-dom — sin paquetes externos

Soporte fiscal completo

  • 29 tipos impositivos incluyendo IVA, IRPF, IGIC, recargo de equivalencia e impuestos especiales
  • 19 métodos de pago desde transferencia hasta tarjeta y domiciliación
  • 36 unidades de medida desde unidades hasta kWh y horas
  • 22 motivos de corrección para facturas rectificativas

Rendimiento

  • ~0.2 ms por factura simple
  • ~22 ms para 100 facturas
  • Generación XML eficiente con huella de memoria mínima

Casos de uso

  • Plataformas SaaS que generan facturas para clientes españoles
  • E-commerce que necesita formato FacturaE para ventas B2B
  • Software de contabilidad con integración FACe/FACeB2B
  • Autónomos y agencias que facturan a la Administración Pública

Arquitectura

La librería está organizada en namespaces enfocados:

  • Invoice — Punto de entrada principal con API fluent
  • Party — Entidades vendedor/comprador (empresas e individuos)
  • Entities/ — Líneas, pagos, adjuntos, desglose fiscal, direcciones
  • Enums/ — Tipos impositivos, métodos de pago, tipos de factura, motivos de corrección
  • Exporter/ — Generación XML
  • Signer/ — Firma digital XAdES-EPES
  • Validation/ — Validación contra esquemas

Cada clase usa propiedades readonly y tipos estrictos (PHP 8.2+) para máxima seguridad y soporte de autocompletado en el IDE.


Instalación

Requisitos

PHP FacturaE requiere PHP 8.2 o superior.

Extensiones PHP necesarias:

  • ext-openssl — Necesaria para firmas digitales XAdES-EPES y manejo de certificados
  • ext-dom — Necesaria para generación y manipulación de XML

Instalación vía Composer

Terminal window
composer require php-facturae/php-facturae

Verificar la instalación

<?php
require_once 'vendor/autoload.php';
use PhpFacturae\Invoice;
use PhpFacturae\Party;
$invoice = Invoice::create('TEST-001')
->seller(Party::company('B12345678', 'Empresa Test'))
->buyer(Party::company('B87654321', 'Empresa Cliente'))
->line('Producto de prueba', price: 100.00, vat: 21);
echo "✓ PHP FacturaE está correctamente instalado!\n";
echo "Número de factura: " . $invoice->getNumber() . "\n";

Autoloading

PHP FacturaE usa autoloading PSR-4:

  • PhpFacturae\Invoice mapea a src/Invoice.php
  • PhpFacturae\Party mapea a src/Party.php
  • PhpFacturae\Entities\Line mapea a src/Entities/Line.php

Dependencias de desarrollo

Terminal window
composer install --dev

Incluye PHPUnit 11.0+ y PHPStan 2.0+ (nivel 8).

Terminal window
# Ejecutar tests
vendor/bin/phpunit
# Ejecutar análisis estático
vendor/bin/phpstan analyse src --level=8

Solución de problemas

«ext-openssl is missing» — Instala php8.2-openssl (Ubuntu/Debian) o actívalo en php.ini (Windows).

«ext-dom is missing» — Instala php8.2-xml (Ubuntu/Debian).

«Class ‘PhpFacturae\Invoice’ not found» — Asegúrate de incluir vendor/autoload.php. Ejecuta composer dump-autoload si es necesario.

Opcional: Sellado de tiempo TSA

Para soporte de autoridad de sellado de tiempo (TSA), necesitarás ext-curl:

Terminal window
sudo apt-get install php8.2-curl

Inicio rápido

Tu primera factura

<?php
require_once 'vendor/autoload.php';
use PhpFacturae\Invoice;
use PhpFacturae\Party;
$invoice = Invoice::create('FAC-001')
->series('A')
->date('2025-03-01')
->seller(
Party::company('B12345678', 'Mi Empresa S.L.')
->address('C/ Mayor 10', '28013', 'Madrid', 'Madrid')
->email('info@miempresa.es')
)
->buyer(
Party::person('12345678Z', 'Laura', 'Gómez', 'Ruiz')
->address('C/ Sol 3', '28012', 'Madrid', 'Madrid')
->email('laura@example.com')
)
->line('Diseño de logotipo', price: 450.00, vat: 21)
->transferPayment(
iban: 'ES91 2100 0418 4502 0005 1332',
dueDate: '2025-03-31'
)
->export('factura.xml');
echo "✓ Factura generada: factura.xml\n";

Escenarios fiscales avanzados

IVA + retención de IRPF:

$invoice->line(
description: 'Consultoría informática',
price: 500.00,
vat: 21,
irpf: 15
);

Canarias (IGIC):

$invoice->line('Producto enviado a Canarias', price: 100, igic: 7);

Recargo de equivalencia:

$invoice->line('Producto minorista', price: 100, vat: 21, surcharge: 5.2);

Línea exenta:

$invoice->exemptLine('Curso de formación', price: 2000, reason: 'Exenta según Art. 20 LIVA');

Múltiples impuestos por línea

use PhpFacturae\Entities\TaxBreakdown;
use PhpFacturae\Enums\Tax;
$invoice->customLine(
description: 'Producto con múltiples impuestos',
price: 300.00,
taxes: [
new TaxBreakdown(Tax::IGIC, 7),
new TaxBreakdown(Tax::REIGIC, 0.5),
]
);

Pagos fraccionados

use PhpFacturae\Enums\PaymentMethod;
$invoice->splitPayments(
method: PaymentMethod::Transfer,
installments: 3,
firstDueDate: '2025-04-01',
intervalDays: 30,
iban: 'ES91 2100 0418 4502 0005 1332'
);

Validación

use PhpFacturae\Exceptions\InvoiceValidationException;
try {
$invoice->export('factura.xml');
} catch (InvoiceValidationException $e) {
echo "Errores de validación:\n";
foreach ($e->getErrors() as $error) {
echo " - $error\n";
}
}

Factura

La clase Invoice es el corazón de PHP FacturaE. Proporciona una API fluent para construir documentos XML FacturaE conformes con validación automática, cálculo de impuestos y firma digital.

Crear una factura

use PhpFacturae\Invoice;
$invoice = Invoice::create('2024-001')
->date('2024-03-09')
->seller($seller)
->buyer($buyer)
->line('Servicio', price: 100, vat: 21)
->transferPayment('ES12 3456 7890 1234 5678 9012');

Configuración básica

Series y fechas:

$invoice->series('A')
->date('2024-03-09')
->operationDate('2024-03-01')
->billingPeriod(from: '2024-03-01', to: '2024-03-31');

Esquema y tipo:

use PhpFacturae\Enums\Schema;
use PhpFacturae\Enums\InvoiceType;
$invoice->schema(Schema::V3_2_2)
->type(InvoiceType::Full);

Versiones de esquema: V3_2, V3_2_1, V3_2_2 (por defecto). Tipos de factura: Full (FC), Simplified (FA), SimplifiedRectified (AF).

Moneda y descripción:

$invoice->currency('EUR')
->description('Servicios de consultoría mensual');

Descuentos y cargos generales

$invoice->generalDiscount('Descuento cliente VIP', rate: 10);
$invoice->generalDiscount('Pronto pago', amount: 50.00);
$invoice->generalCharge('Gastos de envío', amount: 15.00);

Facturas rectificativas

use PhpFacturae\Enums\CorrectionReason;
use PhpFacturae\Enums\CorrectionMethod;
$invoice->corrects(
invoiceNumber: '2024-001',
reason: CorrectionReason::TransactionDetail,
method: CorrectionMethod::FullReplacement,
series: 'A'
);

Adjuntos

$invoice->attachFile('/ruta/al/contrato.pdf', 'Contrato firmado');

Exportar a XML

$xml = $invoice->toXml();
$invoice->export('/ruta/a/factura.xml');

Firma digital

use PhpFacturae\Signer;
$invoice->sign(Signer::pfx('certificado.pfx', 'password'))
->export('factura-firmada.xml');

Referencia de métodos

MétodoParámetrosDescripción
create()string $numberConstructor estático
series()string $seriesEstablecer serie
date()string|DateTimeImmutable $dateFecha de emisión
operationDate()string|DateTimeImmutable $dateFecha de operación
billingPeriod()$from, $toPeriodo de facturación
schema()Schema $schemaVersión FacturaE
type()InvoiceType $typeTipo de factura
currency()string $currencyMoneda (ISO 4217)
description()string $descriptionDescripción
seller()Party $sellerVendedor
buyer()Party $buyerComprador
line()Ver Líneas e impuestosAñadir línea
exemptLine()Ver Líneas e impuestosLínea exenta
customLine()Ver Líneas e impuestosLínea con impuestos custom
transferPayment()string $iban, ?string $dueDate, ?float $amountPago por transferencia
cashPayment()?string $dueDate, ?float $amountPago en efectivo
cardPayment()?string $dueDate, ?float $amountPago con tarjeta
directDebitPayment()string $iban, ?string $dueDate, ?float $amountDomiciliación
splitPayments()Ver PagosPagos fraccionados
sign()InvoiceSigner $signerFirmar factura
toXml()Generar XML
export()string $pathExportar a archivo

Partes

Toda factura FacturaE requiere dos partes: un vendedor (emisor) y un comprador (receptor).

Empresas

use PhpFacturae\Party;
$empresa = Party::company(
taxNumber: 'B12345678',
name: 'Acme Corporation S.L.'
);

Personas físicas

$persona = Party::person(
taxNumber: '12345678Z',
name: 'Juan',
firstSurname: 'García',
lastSurname: 'López'
);

Dirección

$party->address(
street: 'Gran Vía 1, 3ª Planta',
postalCode: '28013',
town: 'Madrid',
province: 'Madrid',
countryCode: 'ESP'
);

El código de país usa ISO 3166-1 alpha-3 (ESP, FRA, DEU, etc.).

Datos de contacto

$party->email('info@ejemplo.com')
->phone('+34 91 123 4567')
->fax('+34 91 123 4568')
->website('https://ejemplo.com')
->contactPeople('Juan García, Departamento de Contabilidad');

Nombre comercial

$party->tradeName('Acme Tech');

Centros administrativos (FACe)

$comprador = Party::company('Q2819002D', 'Ministerio de Hacienda')
->centre(role: '01', code: 'L01281901', name: 'Oficina Contable')
->centre(role: '02', code: 'L01281902', name: 'Unidad Tramitadora')
->centre(role: '03', code: 'L01281903', name: 'Oficina Gestora');

Registro Mercantil

$party->merchantRegister(
register: 'Madrid',
book: '1234',
folio: '56',
sheet: 'M-123456',
section: '8',
volume: '789'
);

Códigos de actividad económica

$party->cnoCnae('6201');
$party->ineTownCode('28079');

Partes internacionales

$compradorExtranjero = Party::company('FR12345678901', 'Société Française SARL')
->address(
street: '10 Avenue des Champs-Élysées',
postalCode: '75008',
town: 'Paris',
province: 'Île-de-France',
countryCode: 'FRA'
);

Líneas e impuestos

Líneas básicas

$invoice->line(
description: 'Ordenador portátil',
quantity: 2,
price: 899.99,
vat: 21
);

Firma del método

public function line(
string $description,
float $price,
float $quantity = 1,
?float $vat = null,
?float $irpf = null,
?float $igic = null,
?float $surcharge = null,
?float $ie = null,
bool $ieWithheld = false,
?float $discount = null,
?string $articleCode = null,
?string $detailedDescription = null,
?UnitOfMeasure $unit = null,
): self

Atajos fiscales

IVA:

$invoice->line('Licencia software', price: 100, vat: 21); // General 21%
$invoice->line('Libro', price: 20, vat: 10); // Reducido 10%
$invoice->line('Alimento esencial', price: 15, vat: 4); // Superreducido 4%

IRPF (retención):

2120.00
$invoice->line('Asesoría legal', price: 2000, vat: 21, irpf: 15);

IGIC (Canarias):

$invoice->line('Producto', price: 100, igic: 7);

No combines IVA e IGIC en la misma línea.

Recargo de equivalencia:

$invoice->line('Producto minorista', price: 100, vat: 21, surcharge: 5.2);

Tipos de recargo: IVA 21% → 5.2%, IVA 10% → 1.4%, IVA 4% → 0.5%.

Impuestos especiales (IE):

$invoice->line('Alcohol', price: 50, vat: 21, ie: 10);

Descuentos por línea

$invoice->line('Producto', quantity: 10, price: 100, discount: 20, vat: 21);
// Subtotal: 1000, Descuento -20% = 800, IVA +168, Total: 968

Códigos de artículo y unidades

use PhpFacturae\Enums\UnitOfMeasure;
$invoice->line('Electricidad', quantity: 150.5, price: 0.15,
unit: UnitOfMeasure::KWh, vat: 21, articleCode: 'ELEC-001');

Líneas exentas

$invoice->exemptLine(
description: 'Curso de formación profesional',
price: 2000,
reason: 'Exenta según Artículo 20 LIVA'
);

Configuración fiscal personalizada

use PhpFacturae\Entities\TaxBreakdown;
use PhpFacturae\Enums\Tax;
$invoice->customLine(
description: 'Servicio complejo',
price: 1000,
taxes: [
new TaxBreakdown(Tax::IVA, rate: 21),
new TaxBreakdown(Tax::IRPF, rate: 15),
]
);

Enum Tax (29 tipos)

Tax::IVA // Impuesto sobre el Valor Añadido
Tax::IPSI // Impuesto sobre la Producción (Ceuta y Melilla)
Tax::IGIC // Impuesto General Indirecto Canario
Tax::IRPF // Retención del IRPF
Tax::IRNR // Impuesto sobre la Renta de No Residentes
Tax::IE // Impuesto Especial
Tax::RA // Recargo de equivalencia agrario
Tax::ITPAJD // Impuesto de Transmisiones Patrimoniales
Tax::REIVA // Recargo de equivalencia (IVA)
Tax::REIGIC // Recargo de equivalencia (IGIC)
Tax::REIPSI // Recargo de equivalencia (IPSI)
// ... y 18 más especializados

Pagos

Métodos de pago

Transferencia bancaria:

$invoice->transferPayment(
iban: 'ES12 3456 7890 1234 5678 9012',
dueDate: '2024-04-09'
);

Pago en efectivo:

$invoice->cashPayment();

Pago con tarjeta:

$invoice->cardPayment(dueDate: '2024-03-09');

Domiciliación bancaria:

$invoice->directDebitPayment(
iban: 'ES98 7654 3210 9876 5432 1098',
dueDate: '2024-04-09'
);

Pagos fraccionados

use PhpFacturae\Enums\PaymentMethod;
$invoice->splitPayments(
method: PaymentMethod::Transfer,
installments: 3,
firstDueDate: '2024-04-09',
intervalDays: 30,
iban: 'ES12 3456 7890 1234 5678 9012'
);

Importes personalizados por plazo

use PhpFacturae\Entities\Payment;
$invoice->payment(new Payment(
method: PaymentMethod::Transfer,
dueDate: new DateTimeImmutable('2024-04-09'),
amount: 1000.00,
iban: 'ES12 3456 7890 1234 5678 9012'
));

Enum PaymentMethod (19 métodos)

PaymentMethod::Cash // 01 — Efectivo
PaymentMethod::DirectDebit // 02 — Domiciliación
PaymentMethod::Receipt // 03 — Recibo
PaymentMethod::Transfer // 04 — Transferencia
PaymentMethod::AcceptedBillOfExchange // 05 — Letra de cambio aceptada
PaymentMethod::DocumentaryCredit // 06 — Crédito documentario
PaymentMethod::ContractAward // 07 — Adjudicación de contrato
PaymentMethod::BillOfExchange // 08 — Letra de cambio
PaymentMethod::TransferablePromissory // 09 — Pagaré transferible
PaymentMethod::PromissoryNote // 10 — Pagaré no a la orden
PaymentMethod::Cheque // 11 — Cheque
PaymentMethod::Reimbursement // 12 — Reposición
PaymentMethod::Special // 13 — Especial
PaymentMethod::Setoff // 14 — Compensación
PaymentMethod::Postgiro // 15 — Giro postal
PaymentMethod::CertifiedCheque // 16 — Cheque conformado
PaymentMethod::BankersDraft // 17 — Cheque bancario
PaymentMethod::CashOnDelivery // 18 — Contra reembolso
PaymentMethod::Card // 19 — Tarjeta

Formato IBAN

Los IBAN se normalizan automáticamente — los espacios y guiones se eliminan internamente.


Firma digital

PHP FacturaE soporta firma digital con XAdES-EPES conforme a la política de firma FacturaE v3.1.

Certificados PKCS#12 (.pfx / .p12)

use PhpFacturae\Signer;
$signer = Signer::pfx('certificado.pfx', 'miPasswordSeguro');
$invoice->sign($signer);

Certificados PEM

$signer = Signer::pem(
certPath: 'certificado.pem',
keyPath: 'clave-privada.pem',
passphrase: 'passwordClave'
);

Sellado de tiempo (TSA)

$signer = Signer::pfx('certificado.pfx', 'password')
->timestamp('https://freetsa.org/tsr');

Con autenticación:

->timestamp(
url: 'https://tsa.ejemplo.com/tsr',
user: 'miUsuario',
password: 'miPassword'
)

Detalles criptográficos

  • Canonicalización: C14N (Canonical XML 1.0)
  • Algoritmo de resumen: SHA-256
  • Algoritmo de firma: RSA-SHA256
  • Transformación: Firma envolvente (enveloped signature)

Conversión de certificados

Terminal window
# PEM a PKCS#12
openssl pkcs12 -export -in certificado.pem -inkey clave-privada.pem -out certificado.pfx
# PKCS#12 a PEM
openssl pkcs12 -in certificado.pfx -out certificado.pem -nodes
# Eliminar passphrase de clave PEM
openssl rsa -in clave-cifrada.pem -out clave-descifrada.pem

Verificar firmas

Terminal window
xmlsec1 --verify factura-firmada.xml

Facturas rectificativas

Rectificativa básica

use PhpFacturae\Enums\CorrectionReason;
use PhpFacturae\Enums\CorrectionMethod;
$invoice = Invoice::create('FAC-002')
->date('2024-02-15')
->seller($seller)
->buyer($buyer)
->line('Servicio corregido', price: 1000.00, vat: 21)
->corrects(
invoiceNumber: 'FAC-001',
reason: CorrectionReason::TaxableBase,
method: CorrectionMethod::FullReplacement
)
->toXml();

Motivos de corrección (22 tipos)

Administrativos (01-09): Número de factura, serie, fecha de emisión, nombre del emisor, nombre del receptor, NIF del emisor, NIF del receptor, dirección del emisor, dirección del receptor.

De transacción (10-16): Detalle de la operación, tipo impositivo, cuota impositiva, periodo fiscal, clase de factura, literales legales, base imponible.

De cálculo fiscal (80-85): Cálculo de cuotas repercutidas, cálculo de cuotas retenidas, base modificada por devoluciones, base modificada por descuentos, base modificada por resolución judicial, base modificada por insolvencia.

Métodos de corrección

  • FullReplacement (01) — Sustitución completa (el más habitual)
  • Differences (02) — Solo las diferencias
  • VolumeDiscount (03) — Descuento por volumen
  • TaxAuthorityAuthorized (04) — Autorizado por la AEAT

Correcciones con periodo fiscal

$invoice->corrects(
invoiceNumber: 'FAC-2024-001',
reason: CorrectionReason::TaxPeriod,
method: CorrectionMethod::FullReplacement,
periodStart: '2024-01-01',
periodEnd: '2024-03-31'
);

Descuentos y cargos

Descuentos generales

$invoice->generalDiscount('Descuento cliente VIP', amount: 50.00);
$invoice->generalDiscount('Descuento por volumen', rate: 10);

Cargos generales

$invoice->generalCharge('Gastos de envío', amount: 15.00);
$invoice->generalCharge('Recargo por urgencia', rate: 5);

Los descuentos y cargos generales se aplican al total bruto antes de impuestos.

Descuentos a nivel de línea

->line('Producto', price: 100.00, vat: 21, discount: 10)

Adjuntos

Uso rápido

$invoice->attachFile('/ruta/al/contrato.pdf', 'Contrato de servicio firmado');

Usando la entidad Attachment

use PhpFacturae\Entities\Attachment;
// Desde archivo
$adjunto = Attachment::fromFile('/ruta/al/doc.pdf', 'Contrato');
// Desde datos en bruto
$adjunto = Attachment::fromData($pdfData, 'application/pdf', 'Informe');
$invoice->attach($adjunto);

Múltiples adjuntos

$invoice
->attachFile('/ruta/al/contrato.pdf', 'Contrato')
->attachFile('/ruta/al/albaran.pdf', 'Albarán de entrega');

Mantén los adjuntos por debajo de 5 MB cuando sea posible.


Validación

La validación ocurre automáticamente al llamar a toXml() o export().

Reglas de validación

  1. Vendedor obligatorio (con dirección)
  2. Comprador obligatorio (con dirección)
  3. Al menos una línea de factura
  4. Número de factura obligatorio
  5. El periodo de facturación requiere fecha de inicio y fin
  6. La fecha de inicio del periodo debe ser anterior a la de fin

Manejo de errores de validación

use PhpFacturae\Exceptions\InvoiceValidationException;
try {
$xml = $invoice->toXml();
} catch (InvoiceValidationException $e) {
foreach ($e->errors as $error) {
echo "- $error\n";
}
}

Validación de esquema XSD

use PhpFacturae\Enums\Schema;
$invoice->schema(Schema::V3_2_2); // Por defecto

Disponibles: V3_2, V3_2_1, V3_2_2.


Integración FACe

FACe (Punto General de Entrada de Facturas Electrónicas) es la plataforma centralizada de facturación electrónica para la Administración Pública española.

Centros administrativos (DIR3)

$entidadPublica = Party::company('Q2826004D', 'Ayuntamiento de Las Rozas')
->address('Plaza Mayor 1', '28230', 'Las Rozas', 'Madrid')
->centre(role: '01', code: 'L01282249', name: 'Oficina Contable')
->centre(role: '02', code: 'L01282249', name: 'Ayuntamiento')
->centre(role: '03', code: 'L01282249', name: 'Unidad Contratación');

Códigos de rol

CódigoRolNombre
01Oficina contableOficina contable
02Órgano gestorÓrgano gestor
03Unidad tramitadoraUnidad tramitadora
04Órgano proponenteÓrgano proponente

Cómo encontrar códigos DIR3

  1. Solicitar directamente a la entidad
  2. Buscar en dir3.redsara.es
  3. Revisar órdenes de compra
  4. Documentación de FACe

Checklist FACe

  • ✅ Códigos DIR3 válidos para centros (01, 02, 03)
  • ✅ NIF correcto de la entidad pública (P/S/Q + 7 dígitos + letra)
  • ✅ Dirección completa de ambas partes
  • ✅ IBAN válido para el pago
  • ✅ Fecha de vencimiento (normalmente 30-60-90 días)
  • ✅ Literal legal mencionando Ley 25/2013

Ejemplo: Factura básica

use PhpFacturae\Invoice;
use PhpFacturae\Party;
$invoice = Invoice::create('FAC-001')
->series('A')
->date('2024-01-15')
->seller(
Party::company('A00000000', 'Empresa Test S.L.')
->address('C/ Test, 1', '28001', 'Madrid', 'Madrid')
->email('admin@empresa.es')
)
->buyer(
Party::person('00000000A', 'Juan', 'García', 'López')
->address('C/ Comprador, 5', '08001', 'Barcelona', 'Barcelona')
)
->line('Servicio de consultoría', price: 1000.00, vat: 21)
->transferPayment(
iban: 'ES91 2100 0418 4502 0005 1332',
dueDate: '2024-02-15'
)
->export('factura-001.xsig');

Ejemplo: Canarias (IGIC)

use PhpFacturae\Invoice;
use PhpFacturae\Party;
$invoice = Invoice::create('FAC-2024-0001')
->series('A')
->date('2024-12-15')
->seller(
Party::company('B76123456', 'Atlantic Systems S.L.')
->tradeName('Atsys')
->address('C/ Triana, 52', '35002', 'Las Palmas de Gran Canaria', 'Las Palmas')
->email('info@atsys.es')
)
->buyer(
Party::company('A28000001', 'Cliente Demo S.L.')
->address('C/ Gran Vía, 1', '28013', 'Madrid', 'Madrid')
)
->line('Desarrollo web', price: 1200.00, igic: 7)
->line('Mantenimiento WordPress (3 meses)', price: 150.00, quantity: 3, igic: 7)
->line('Certificado SSL', price: 45.50, igic: 7)
->transferPayment(
iban: 'ES91 2100 0418 4502 0005 1332',
dueDate: '2025-01-15'
)
->legalLiteral('Factura exenta de IVA por aplicación del REF Canario. IGIC al tipo general.')
->export('factura-canaria.xsig');

Tipos IGIC: 0% (superreducido), 3% (reducido), 7% (general), 15% (incrementado).


Ejemplo: Administración Pública (FACe)

use PhpFacturae\Invoice;
use PhpFacturae\Party;
$invoice = Invoice::create('FAC-FACE-001')
->series('F')
->date('2024-12-15')
->seller(
Party::company('B12345678', 'Consultoría IT S.L.')
->address('C/ Serrano, 25', '28001', 'Madrid', 'Madrid')
)
->buyer(
Party::company('S2800001A', 'Ministerio de Educación')
->address('C/ Alcalá, 36', '28014', 'Madrid', 'Madrid')
->centre('01', 'EA0001234')
->centre('02', 'EA0001234')
->centre('03', 'EA0001234')
)
->line('Consultoría sistema educativo', price: 15000.00, vat: 21)
->line('Licencias software (50 usuarios)', price: 5000.00, vat: 21)
->transferPayment(
iban: 'ES91 2100 0418 4502 0005 1332',
dueDate: '2025-02-15'
)
->legalLiteral('Factura destinada a Administración Pública. Ley 25/2013.')
->export('factura-face.xsig');

Ejemplo: Pagos fraccionados

use PhpFacturae\Invoice;
use PhpFacturae\Party;
use PhpFacturae\Enums\PaymentMethod;
$invoice = Invoice::create('FAC-008')
->series('F')
->date('2024-10-01')
->seller(
Party::company('B76123456', 'Atlantic Systems S.L.')
->address('C/ Triana, 52', '35002', 'Las Palmas de Gran Canaria', 'Las Palmas')
)
->buyer(
Party::company('A28000001', 'Cliente Demo S.L.')
->address('C/ Gran Vía, 1', '28013', 'Madrid', 'Madrid')
)
->line('Desarrollo aplicación móvil', price: 6000.00, igic: 7)
->splitPayments(
method: PaymentMethod::Transfer,
installments: 3,
firstDueDate: '2024-11-01',
intervalDays: 30,
iban: 'ES91 2100 0418 4502 0005 1332'
)
->export('factura-pagos-fraccionados.xsig');

Total: 6.000 € + 7% IGIC = 6.420 € en 3 plazos de 2.140 € cada uno.

Para calendarios personalizados, usa objetos Payment manuales:

use PhpFacturae\Entities\Payment;
$invoice
->payment(new Payment(
method: PaymentMethod::Transfer,
dueDate: new \DateTimeImmutable('2024-12-30'),
amount: 12100.00,
iban: 'ES91 2100 0418 4502 0005 1332'
))
->payment(new Payment(
method: PaymentMethod::Transfer,
dueDate: new \DateTimeImmutable('2025-01-30'),
amount: 12100.00,
iban: 'ES91 2100 0418 4502 0005 1332'
));