Search by

darvis / ubl-peppol

darvis

Generates UBL 2.1 invoices and credit notes that pass PEPPOL BIS Billing 3.0 and EN 16931 validation, with Dutch and Belgian rules, VIES and company registration checks. Works in plain PHP; the Laravel integration is optional.

Package info

github.com/ArvidDeJong/ubl-peppol

Homepage

pkg:composer/darvis/ubl-peppol

Statistics

Installs: 1 853

Dependents: 0

Suggesters: 0

Stars: 8

Open Issues: 1

v1.10.1 2026-09-21 13:40 UTC

README

Latest version Tests PHP version License

A PHP library that builds UBL 2.1 e-invoices for PEPPOL BIS Billing 3.0, the format the PEPPOL network requires (built on EN 16931). It has one builder for Dutch and one for Belgian invoices and credit notes. The builders are plain PHP; an optional Laravel layer posts the XML to your access point provider.

Features

  • Dutch invoices and credit notes with UblNlBis3Service, which puts the elements in schema order for you
  • Belgian invoices and credit notes with UblBeBis3Service, which can add up the lines with calculateTotals()
  • validate() before sending: code formats and the Dutch NL-R rules in the Dutch builder, the totals (BR-CO-10, 13, 15, 16, BR-S-08) in the Belgian builder
  • ViesService checks a European VAT number against VIES and tells "invalid" apart from "VIES did not answer"
  • CompanyRegistrationService checks the format of a KvK, KBO, RCS, SIREN/SIRET or Handelsregister number
  • In Laravel: PeppolService posts the XML to your provider, with an optional peppol_logs table and a peppol:cleanup command

It is not an access point, and validate() is not the full Schematron a receiver runs: check a document with an official validator before you go live.

Requirements

  • PHP 8.2 or newer with the dom and libxml extensions
  • The bcmath extension to check an IBAN, the soap extension for ViesService
  • Laravel 11, 12 or 13, only for the optional Laravel layer

Installation

composer require darvis/ubl-peppol

In Laravel the service provider registers itself. To send invoices, set PEPPOL_URL, PEPPOL_USERNAME and PEPPOL_PASSWORD in .env. The config file and the log table are optional:

php artisan vendor:publish --tag=ubl-peppol-config
php artisan vendor:publish --tag=ubl-peppol-migrations

Quick start

<?php
// invoice.php

require __DIR__.'/vendor/autoload.php';

use Darvis\UblPeppol\UblNlBis3Service;

$ubl = new UblNlBis3Service();

$ubl->createDocument();
$ubl->addInvoiceHeader('INV-2026-001', '2026-01-15', '2026-02-14');
$ubl->addBuyerReference('CLIENT-001');

$ubl->addAccountingSupplierParty(
    '12345678', '0106', '12345678', 'My Dutch Company BV',
    'Damrak 1', '1012 JS', 'Amsterdam', 'NL', 'NL123456789B01'
);
$ubl->addSupplierLegalRegistration('12345678'); // your KvK number, scheme 0106
$ubl->addAccountingCustomerParty(
    '87654321', '0106', '87654321', 'Customer Company BV',
    'Nieuwezijds Voorburgwal 123', '1012 RJ', 'Amsterdam', 'NL',
    null, '87654321', null, null, null, 'NL987654321B01'
);

$ubl->addPaymentMeans('30', 'Credit transfer', 'INV-2026-001', 'NL91ABNA0417164300', null, 'ABNANL2A');
$ubl->addPaymentTerms('Payment within 30 days');

$ubl->addTaxTotal([[
    'taxable_amount' => 425.00,
    'tax_amount' => 89.25,
    'currency' => 'EUR',
    'tax_category_id' => 'S',
    'tax_percent' => 21.0,
    'tax_scheme_id' => 'VAT',
]]);

$ubl->addLegalMonetaryTotal([
    'line_extension_amount' => 425.00,
    'tax_exclusive_amount' => 425.00,
    'tax_inclusive_amount' => 514.25,
    'charge_total_amount' => 0.00,
    'payable_amount' => 514.25,
], 'EUR');

$ubl->addInvoiceLine([
    'id' => '1',
    'quantity' => 5,
    'unit_code' => 'HUR',
    'price_amount' => 85.00,
    'currency' => 'EUR',
    'name' => 'Software development',
    'description' => 'Frontend development, 5 hours',
    'tax_category_id' => 'S',
    'tax_percent' => 21.0,
]);

// Throws an InvalidArgumentException when validate() finds an error.
file_put_contents(__DIR__.'/invoice.xml', $ubl->generateXml(validateFirst: true));

Use UblBeBis3Service when the receiver is Belgian. Create a new builder for every document. The documentation explains every argument.

Documentation

Full documentation at arviddejong.github.io/ubl-peppol:

Runnable examples for both countries are in examples/.

Laravel Boost

The package ships a Laravel Boost guideline and skill in resources/boost/, so an AI assistant in your project knows how the builders work. Run php artisan boost:install, or php artisan boost:update --discover in a project that already uses Boost.

Testing

composer test      # Pest
composer lint      # Pint, check only; composer format fixes
composer analyse   # Larastan

Changelog

See CHANGELOG.md.

Contributing

See CONTRIBUTING.md.

Security

Found a way to inject XML through invoice data, or another vulnerability? Please report it privately; see SECURITY.md.

License

MIT, see LICENSE. A package by ARVID.NL.