jh3ady / einvoicing
Anti-Corruption Layer for European e-invoicing (UBL + Factur-X)
v0.1.0
2026-04-05 18:21 UTC
Requires
- php: ^8.1
- ext-bcmath: *
- ext-dom: *
- ext-libxml: *
Requires (Dev)
- phpstan/phpstan: ^2.0
- phpunit/phpunit: ^10.5
README
PHP 8.1+ library for producing and validating European e-invoices in UBL 2.1 and Factur-X (CII).
Installation
composer require jh3ady/einvoicing
Quick Start
1. Build an invoice
use Jh3ady\EInvoicing\Enum\CountryCode; use Jh3ady\EInvoicing\Enum\CurrencyCode; use Jh3ady\EInvoicing\Enum\InvoiceType; use Jh3ady\EInvoicing\Enum\TaxCategoryCode; use Jh3ady\EInvoicing\Model\Invoice; use Jh3ady\EInvoicing\Model\InvoiceLine; use Jh3ady\EInvoicing\Model\Item; use Jh3ady\EInvoicing\Model\MonetaryTotal; use Jh3ady\EInvoicing\Model\Party; use Jh3ady\EInvoicing\Model\PostalAddress; use Jh3ady\EInvoicing\Model\Price; use Jh3ady\EInvoicing\Model\TaxSubtotal; use Jh3ady\EInvoicing\Model\TaxTotal; use Jh3ady\EInvoicing\Model\ValueObject\Amount; use Jh3ady\EInvoicing\Model\ValueObject\Quantity; $address = new PostalAddress('10 rue de la Paix', 'Paris', CountryCode::FR, '75002'); $invoice = new Invoice( number: 'FA-2024-001', issueDate: new \DateTimeImmutable('2024-01-15'), type: InvoiceType::Invoice, currency: CurrencyCode::EUR, seller: new Party(name: 'Seller SAS', address: $address, vatNumber: 'FR12345678901'), buyer: new Party(name: 'Buyer SA', address: $address, vatNumber: 'FR98765432101'), lines: [ new InvoiceLine( id: '1', quantity: new Quantity('2', 'C62'), item: new Item(name: 'Consulting service'), price: new Price(amount: new Amount('500.00')), taxCategory: TaxCategoryCode::StandardRate, taxRate: '20.00', lineTotal: new Amount('1000.00'), ), ], taxTotal: new TaxTotal( taxAmount: new Amount('200.00'), subtotals: [ new TaxSubtotal( taxableAmount: new Amount('1000.00'), taxAmount: new Amount('200.00'), category: TaxCategoryCode::StandardRate, taxRate: '20.00', ), ], ), monetaryTotal: new MonetaryTotal( lineExtensionAmount: new Amount('1000.00'), taxExclusiveAmount: new Amount('1000.00'), taxInclusiveAmount: new Amount('1200.00'), payableAmount: new Amount('1200.00'), ), );
2. Serialize to UBL 2.1
use Jh3ady\EInvoicing\EInvoicing; use Jh3ady\EInvoicing\Specification; $xml = EInvoicing::serialize($invoice, Specification::ubl21());
3. Serialize to Factur-X
use Jh3ady\EInvoicing\EInvoicing; use Jh3ady\EInvoicing\Enum\FacturXProfile; use Jh3ady\EInvoicing\Specification; $xml = EInvoicing::serialize($invoice, Specification::facturX(FacturXProfile::EN16931));
4. Validate
$result = EInvoicing::validate($invoice, $spec); if (!$result->isValid()) { foreach ($result->errors() as $error) { echo "[{$error->code}] {$error->message}\n"; } }
5. Serialize and validate in one step
$output = EInvoicing::process($invoice, $spec); if ($output->isValid()) { file_put_contents('invoice.xml', $output->xml); }
Supported Formats
| Format | Specification |
|---|---|
| UBL 2.1 | Specification::ubl21() |
| Factur-X Minimum | Specification::facturX(FacturXProfile::Minimum) |
| Factur-X BasicWL | Specification::facturX(FacturXProfile::BasicWL) |
| Factur-X Basic | Specification::facturX(FacturXProfile::Basic) |
| Factur-X EN16931 | Specification::facturX(FacturXProfile::EN16931) |
| Factur-X Extended | Specification::facturX(FacturXProfile::Extended) |
Sandbox
Une application Laravel/Livewire est incluse dans sandbox/ pour tester la lib en local :
cd sandbox
composer install
cp .env.example .env
php artisan key:generate
php artisan serve
Deux modes disponibles :
- Créer une facture : formulaire complet avec presets (UBL, Factur-X, avoir)
- Valider un XML : collez du XML UBL ou Factur-X, validation complète (règles métier + XSD)
Requirements
- PHP 8.1 or higher
- ext-dom
- ext-libxml
- ext-bcmath
License
MIT