mariodevv.com

PHP FacturaE — Docs

Modern PHP library to generate, validate and sign FacturaE electronic invoices. Fluent API, XAdES-EPES signature, zero dependencies.

Introduction

PHP FacturaE is a modern, typed library to generate, validate and sign electronic invoices in the FacturaE format — the official electronic invoicing standard in Spain.

What is FacturaE?

FacturaE is the XML-based electronic invoice format required by the Spanish Public Administrations (AAPP) and widely adopted in the private sector. It is managed by the Spanish tax agency (AEAT) and guarantees tax compliance and interoperability.

Why PHP FacturaE?

PHP FacturaE provides a fluent, typed API that makes building compliant invoices intuitive and error-free:

Invoice::create('FAC-001')
->series('A')
->date('2025-03-01')
->seller(Party::company('B12345678', 'My Company 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('Logo design', price: 450.00, vat: 21)
->transferPayment(iban: 'ES91 2100 0418 4502 0005 1332', dueDate: '2025-03-31')
->export('invoice.xml');

Key features

  • Fluent API with Enums — No associative arrays or loose constants — everything typed with PHP 8.2+ enums and readonly properties
  • XAdES-EPES digital signature — Native support for PKCS#12 (.pfx) and PEM certificates with optional TSA time-stamping
  • XSD validation — Automatic validation against the official FacturaE 3.2, 3.2.1 and 3.2.2 schemas
  • Zero dependencies — Only standard PHP extensions: ext-openssl, ext-dom — no external packages

Full tax support

  • 29 tax types including VAT, IRPF, IGIC, equivalence surcharge and excise duties
  • 19 payment methods from wire transfer to card and direct debit
  • 36 units of measure from units to kWh and hours
  • 22 correction reasons for corrective invoices

Performance

  • ~0.2 ms per simple invoice
  • ~22 ms for 100 invoices
  • Efficient XML generation with minimal memory footprint

Use cases

  • SaaS platforms generating invoices for Spanish customers
  • E-commerce needing FacturaE format for B2B sales
  • Accounting software with FACe/FACeB2B integration
  • Freelancers and agencies invoicing the Public Administration

Architecture

The library is organized in focused namespaces:

  • Invoice — Main entry point with fluent API
  • Party — Seller/buyer entities (companies and individuals)
  • Entities/ — Lines, payments, attachments, tax breakdown, addresses
  • Enums/ — Tax types, payment methods, invoice types, correction reasons
  • Exporter/ — XML generation
  • Signer/ — XAdES-EPES digital signature
  • Validation/ — Schema validation

Every class uses readonly properties and strict types (PHP 8.2+) for maximum safety and IDE autocompletion support.


Installation

Requirements

PHP FacturaE requires PHP 8.2 or higher.

Required PHP extensions:

  • ext-openssl — Required for XAdES-EPES digital signatures and certificate handling
  • ext-dom — Required for XML generation and manipulation

Install via Composer

Terminal window
composer require php-facturae/php-facturae

Verify the installation

<?php
require_once 'vendor/autoload.php';
use PhpFacturae\Invoice;
use PhpFacturae\Party;
$invoice = Invoice::create('TEST-001')
->seller(Party::company('B12345678', 'Test Company'))
->buyer(Party::company('B87654321', 'Client Company'))
->line('Test product', price: 100.00, vat: 21);
echo "✓ PHP FacturaE is correctly installed!\n";
echo "Invoice number: " . $invoice->getNumber() . "\n";

Autoloading

PHP FacturaE uses PSR-4 autoloading:

  • PhpFacturae\Invoice maps to src/Invoice.php
  • PhpFacturae\Party maps to src/Party.php
  • PhpFacturae\Entities\Line maps to src/Entities/Line.php

Development dependencies

Terminal window
composer install --dev

Includes PHPUnit 11.0+ and PHPStan 2.0+ (level 8).

Terminal window
# Run tests
vendor/bin/phpunit
# Run static analysis
vendor/bin/phpstan analyse src --level=8

Troubleshooting

“ext-openssl is missing” — Install php8.2-openssl (Ubuntu/Debian) or enable it in php.ini (Windows).

“ext-dom is missing” — Install php8.2-xml (Ubuntu/Debian).

“Class ‘PhpFacturae\Invoice’ not found” — Make sure you include vendor/autoload.php. Run composer dump-autoload if needed.

Optional: TSA time-stamping

For time-stamping authority (TSA) support, you will need ext-curl:

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

Quick start

Your first invoice

<?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', 'My Company S.L.')
->address('C/ Mayor 10', '28013', 'Madrid', 'Madrid')
->email('info@mycompany.es')
)
->buyer(
Party::person('12345678Z', 'Laura', 'Gómez', 'Ruiz')
->address('C/ Sol 3', '28012', 'Madrid', 'Madrid')
->email('laura@example.com')
)
->line('Logo design', price: 450.00, vat: 21)
->transferPayment(
iban: 'ES91 2100 0418 4502 0005 1332',
dueDate: '2025-03-31'
)
->export('invoice.xml');
echo "✓ Invoice generated: invoice.xml\n";

Advanced tax scenarios

VAT + IRPF withholding:

$invoice->line(
description: 'IT consulting',
price: 500.00,
vat: 21,
irpf: 15
);

Canary Islands (IGIC):

$invoice->line('Product shipped to the Canary Islands', price: 100, igic: 7);

Equivalence surcharge:

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

Exempt line:

$invoice->exemptLine('Training course', price: 2000, reason: 'Exempt under Art. 20 LIVA');

Multiple taxes per line

use PhpFacturae\Entities\TaxBreakdown;
use PhpFacturae\Enums\Tax;
$invoice->customLine(
description: 'Product with multiple taxes',
price: 300.00,
taxes: [
new TaxBreakdown(Tax::IGIC, 7),
new TaxBreakdown(Tax::REIGIC, 0.5),
]
);

Split payments

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

Validation

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

Invoice

The Invoice class is the heart of PHP FacturaE. It provides a fluent API to build compliant FacturaE XML documents with automatic validation, tax calculation and digital signature.

Create an invoice

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

Basic configuration

Series and dates:

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

Schema and type:

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

Schema versions: V3_2, V3_2_1, V3_2_2 (default). Invoice types: Full (FC), Simplified (FA), SimplifiedRectified (AF).

Currency and description:

$invoice->currency('EUR')
->description('Monthly consulting services');

General discounts and charges

$invoice->generalDiscount('VIP customer discount', rate: 10);
$invoice->generalDiscount('Early payment', amount: 50.00);
$invoice->generalCharge('Shipping costs', amount: 15.00);

Corrective invoices

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

Attachments

$invoice->attachFile('/path/to/contract.pdf', 'Signed contract');

Export to XML

$xml = $invoice->toXml();
$invoice->export('/path/to/invoice.xml');

Digital signature

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

Method reference

MethodParametersDescription
create()string $numberStatic constructor
series()string $seriesSet series
date()string|DateTimeImmutable $dateIssue date
operationDate()string|DateTimeImmutable $dateOperation date
billingPeriod()$from, $toBilling period
schema()Schema $schemaFacturaE version
type()InvoiceType $typeInvoice type
currency()string $currencyCurrency (ISO 4217)
description()string $descriptionDescription
seller()Party $sellerSeller
buyer()Party $buyerBuyer
line()See Lines and taxesAdd line
exemptLine()See Lines and taxesExempt line
customLine()See Lines and taxesLine with custom taxes
transferPayment()string $iban, ?string $dueDate, ?float $amountWire transfer payment
cashPayment()?string $dueDate, ?float $amountCash payment
cardPayment()?string $dueDate, ?float $amountCard payment
directDebitPayment()string $iban, ?string $dueDate, ?float $amountDirect debit
splitPayments()See PaymentsSplit payments
sign()InvoiceSigner $signerSign invoice
toXml()Generate XML
export()string $pathExport to file

Parties

Every FacturaE invoice requires two parties: a seller (issuer) and a buyer (recipient).

Companies

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

Individuals

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

Address

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

Country codes use ISO 3166-1 alpha-3 (ESP, FRA, DEU, etc.).

Contact details

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

Trade name

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

Administrative centers (FACe)

$buyer = Party::company('Q2819002D', 'Ministry of Finance')
->centre(role: '01', code: 'L01281901', name: 'Accounting Office')
->centre(role: '02', code: 'L01281902', name: 'Processing Unit')
->centre(role: '03', code: 'L01281903', name: 'Managing Office');

Commercial register

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

Economic activity codes

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

International parties

$foreignBuyer = 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'
);

Lines and taxes

Basic lines

$invoice->line(
description: 'Laptop computer',
quantity: 2,
price: 899.99,
vat: 21
);

Method signature

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

Tax shortcuts

VAT:

$invoice->line('Software license', price: 100, vat: 21); // Standard 21%
$invoice->line('Book', price: 20, vat: 10); // Reduced 10%
$invoice->line('Essential food', price: 15, vat: 4); // Super-reduced 4%

IRPF (withholding):

2120.00
$invoice->line('Legal advisory', price: 2000, vat: 21, irpf: 15);

IGIC (Canary Islands):

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

Don’t combine VAT and IGIC on the same line.

Equivalence surcharge:

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

Surcharge rates: VAT 21% → 5.2%, VAT 10% → 1.4%, VAT 4% → 0.5%.

Excise duties (IE):

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

Line-level discounts

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

Article codes and units

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

Exempt lines

$invoice->exemptLine(
description: 'Professional training course',
price: 2000,
reason: 'Exempt under Article 20 LIVA'
);

Custom tax configuration

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

Tax enum (29 types)

Tax::IVA // Value Added Tax
Tax::IPSI // Production Tax (Ceuta and Melilla)
Tax::IGIC // Canary Islands Indirect General Tax
Tax::IRPF // IRPF Withholding
Tax::IRNR // Non-Resident Income Tax
Tax::IE // Excise Duty
Tax::RA // Agricultural equivalence surcharge
Tax::ITPAJD // Transfer Tax
Tax::REIVA // Equivalence surcharge (VAT)
Tax::REIGIC // Equivalence surcharge (IGIC)
Tax::REIPSI // Equivalence surcharge (IPSI)
// ... and 18 more specialized

Payments

Payment methods

Wire transfer:

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

Cash payment:

$invoice->cashPayment();

Card payment:

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

Direct debit:

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

Split payments

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

Custom amounts per installment

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'
));

PaymentMethod enum (19 methods)

PaymentMethod::Cash // 01 — Cash
PaymentMethod::DirectDebit // 02 — Direct debit
PaymentMethod::Receipt // 03 — Receipt
PaymentMethod::Transfer // 04 — Wire transfer
PaymentMethod::AcceptedBillOfExchange // 05 — Accepted bill of exchange
PaymentMethod::DocumentaryCredit // 06 — Documentary credit
PaymentMethod::ContractAward // 07 — Contract award
PaymentMethod::BillOfExchange // 08 — Bill of exchange
PaymentMethod::TransferablePromissory // 09 — Transferable promissory note
PaymentMethod::PromissoryNote // 10 — Non-transferable promissory note
PaymentMethod::Cheque // 11 — Cheque
PaymentMethod::Reimbursement // 12 — Reimbursement
PaymentMethod::Special // 13 — Special
PaymentMethod::Setoff // 14 — Set-off
PaymentMethod::Postgiro // 15 — Postal giro
PaymentMethod::CertifiedCheque // 16 — Certified cheque
PaymentMethod::BankersDraft // 17 — Banker's draft
PaymentMethod::CashOnDelivery // 18 — Cash on delivery
PaymentMethod::Card // 19 — Card

IBAN format

IBANs are normalized automatically — spaces and dashes are stripped internally.


Digital signature

PHP FacturaE supports digital signature with XAdES-EPES compliant with FacturaE signature policy v3.1.

PKCS#12 certificates (.pfx / .p12)

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

PEM certificates

$signer = Signer::pem(
certPath: 'certificate.pem',
keyPath: 'private-key.pem',
passphrase: 'keyPassword'
);

Time-stamping (TSA)

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

With authentication:

->timestamp(
url: 'https://tsa.example.com/tsr',
user: 'myUser',
password: 'myPassword'
)

Cryptographic details

  • Canonicalization: C14N (Canonical XML 1.0)
  • Digest algorithm: SHA-256
  • Signature algorithm: RSA-SHA256
  • Transformation: Enveloped signature

Certificate conversion

Terminal window
# PEM to PKCS#12
openssl pkcs12 -export -in certificate.pem -inkey private-key.pem -out certificate.pfx
# PKCS#12 to PEM
openssl pkcs12 -in certificate.pfx -out certificate.pem -nodes
# Remove passphrase from PEM key
openssl rsa -in encrypted-key.pem -out decrypted-key.pem

Verify signatures

Terminal window
xmlsec1 --verify signed-invoice.xml

Corrective invoices

Basic corrective invoice

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

Correction reasons (22 types)

Administrative (01-09): Invoice number, series, issue date, issuer name, recipient name, issuer tax ID, recipient tax ID, issuer address, recipient address.

Transaction (10-16): Operation detail, tax rate, tax amount, tax period, invoice class, legal literals, taxable base.

Tax calculation (80-85): Output tax calculation, withheld tax calculation, base modified by returns, base modified by discounts, base modified by court decision, base modified by insolvency.

Correction methods

  • FullReplacement (01) — Full replacement (most common)
  • Differences (02) — Only the differences
  • VolumeDiscount (03) — Volume discount
  • TaxAuthorityAuthorized (04) — Authorized by the tax authority

Corrections with a tax period

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

Discounts and charges

General discounts

$invoice->generalDiscount('VIP customer discount', amount: 50.00);
$invoice->generalDiscount('Volume discount', rate: 10);

General charges

$invoice->generalCharge('Shipping costs', amount: 15.00);
$invoice->generalCharge('Urgency surcharge', rate: 5);

General discounts and charges apply to the gross total before taxes.

Line-level discounts

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

Attachments

Quick usage

$invoice->attachFile('/path/to/contract.pdf', 'Signed service contract');

Using the Attachment entity

use PhpFacturae\Entities\Attachment;
// From file
$attachment = Attachment::fromFile('/path/to/doc.pdf', 'Contract');
// From raw data
$attachment = Attachment::fromData($pdfData, 'application/pdf', 'Report');
$invoice->attach($attachment);

Multiple attachments

$invoice
->attachFile('/path/to/contract.pdf', 'Contract')
->attachFile('/path/to/delivery-note.pdf', 'Delivery note');

Keep attachments below 5 MB whenever possible.


Validation

Validation runs automatically when calling toXml() or export().

Validation rules

  1. Seller required (with address)
  2. Buyer required (with address)
  3. At least one invoice line
  4. Invoice number required
  5. Billing period requires start and end dates
  6. Start date must be earlier than end date

Handling validation errors

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

XSD schema validation

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

Available: V3_2, V3_2_1, V3_2_2.


FACe integration

FACe (the General Entry Point for Electronic Invoices) is the centralized electronic invoicing platform for the Spanish Public Administration.

Administrative centers (DIR3)

$publicEntity = Party::company('Q2826004D', 'City Council of Las Rozas')
->address('Plaza Mayor 1', '28230', 'Las Rozas', 'Madrid')
->centre(role: '01', code: 'L01282249', name: 'Accounting Office')
->centre(role: '02', code: 'L01282249', name: 'City Council')
->centre(role: '03', code: 'L01282249', name: 'Contracting Unit');

Role codes

CodeRoleName
01Accounting officeAccounting office
02Managing bodyManaging body
03Processing unitProcessing unit
04Proposing bodyProposing body

How to find DIR3 codes

  1. Request them directly from the entity
  2. Look them up at dir3.redsara.es
  3. Check purchase orders
  4. FACe documentation

FACe checklist

  • ✅ Valid DIR3 codes for centers (01, 02, 03)
  • ✅ Correct tax ID for the public entity (P/S/Q + 7 digits + letter)
  • ✅ Full address for both parties
  • ✅ Valid IBAN for the payment
  • ✅ Due date (usually 30-60-90 days)
  • ✅ Legal literal referencing Law 25/2013

Example: Basic invoice

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

Example: Canary Islands (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', 'Demo Client S.L.')
->address('C/ Gran Vía, 1', '28013', 'Madrid', 'Madrid')
)
->line('Web development', price: 1200.00, igic: 7)
->line('WordPress maintenance (3 months)', price: 150.00, quantity: 3, igic: 7)
->line('SSL certificate', price: 45.50, igic: 7)
->transferPayment(
iban: 'ES91 2100 0418 4502 0005 1332',
dueDate: '2025-01-15'
)
->legalLiteral('Invoice exempt from VAT under the Canary Islands REF regime. IGIC at the standard rate.')
->export('canary-invoice.xsig');

IGIC rates: 0% (super-reduced), 3% (reduced), 7% (standard), 15% (increased).


Example: Public Administration (FACe)

use PhpFacturae\Invoice;
use PhpFacturae\Party;
$invoice = Invoice::create('FAC-FACE-001')
->series('F')
->date('2024-12-15')
->seller(
Party::company('B12345678', 'IT Consulting S.L.')
->address('C/ Serrano, 25', '28001', 'Madrid', 'Madrid')
)
->buyer(
Party::company('S2800001A', 'Ministry of Education')
->address('C/ Alcalá, 36', '28014', 'Madrid', 'Madrid')
->centre('01', 'EA0001234')
->centre('02', 'EA0001234')
->centre('03', 'EA0001234')
)
->line('Education system consulting', price: 15000.00, vat: 21)
->line('Software licenses (50 users)', price: 5000.00, vat: 21)
->transferPayment(
iban: 'ES91 2100 0418 4502 0005 1332',
dueDate: '2025-02-15'
)
->legalLiteral('Invoice intended for the Public Administration. Law 25/2013.')
->export('face-invoice.xsig');

Example: Split payments

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', 'Demo Client S.L.')
->address('C/ Gran Vía, 1', '28013', 'Madrid', 'Madrid')
)
->line('Mobile app development', 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('split-payments-invoice.xsig');

Total: 6,000 € + 7% IGIC = 6,420 € in 3 installments of 2,140 € each.

For custom schedules, use manual Payment objects:

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'
));