taocomp/php-e-invoice-it

A PHP package for managing italian e-invoice and notice XML formats

v0.2.1 2022-06-06 20:26 UTC

This package is auto-updated.

Last update: 2024-05-07 00:49:54 UTC


README

A PHP package for managing italian e-invoice and notice XML formats:

  • XML management through DOMDocument and DOMXPath
  • full FatturaElettronica (FatturaPA) XML skeleton
  • smart simplified xpath strings for getting/setting values (and for adding/getting/removing elements if needed)
  • multiple bodies (invoice lot)
  • multiple line items (DettaglioLinee)
  • multiple generic elements with setElementCount()
  • XML normalization: remove empty elements and automatically split Causale in chunks if > 200 characters
  • optional FatturaElettronica validation thanks to Slamdunk/php-validatore-fattura-elettronica

(Pacchetto PHP per gestire il formato XML di fatture e notifiche come richiesto dal SdI).

(Qui la documentazione aggiornata in italiano).

Please refer to

See Forum Italia - Fatturazione Elettronica for server configuration, interoperability tests, etc. In particular:

Apache configuration
Accreditamento SDICoop: configurazione SSL su Apache - Fatturazione Elettroni…
Interoperability tests
Test Interoperabilità Soluzioni - Fatturazione Elettronica - Forum Italia

Quickstart

Dependencies

  • php-xml
  • tested for PHP 7+ should work on PHP 5.5 too

Installation

Composer

composer require taocomp/php-e-invoice-it

Manually

  • Clone/download the repository
  • require_once('/path/to/php-e-invoice-it/vendor/autoload.php');

Invoice

Create a new invoice

Create a new FPA12 invoice:

$invoice = new FatturaElettronica('FPA12');

Create a new FPR12 invoice:

$invoice = new FatturaElettronica('FPR12');

Create a new invoice from file

$invoice = new FatturaElettronica('/path/to/invoice.xml');

Create a custom template invoice to be used later

$prefixPath = __DIR__ . '/tmpfiles';
$filename = 'my-custom-template.xml';
$invoice = new FatturaElettronica('FPR12');
$invoice->setValue('IdTrasmittente/IdCodice', '00011122233');
$invoice->setValue('IdTrasmittente/IdPaese', 'IT');
$invoice->setFilename($filename);
$invoice->setPrefixPath($prefixPath)->save();

Invoice lot and line items

Set 3 bodies:

$invoice->addBody(2);
// or
$invoice->setBodyCount(3);

Set 4 line items for second body:

$invoice->addLineItem(3, 2);
// or
$invoice->setLineItemCount(4, 2);

Get/Set values

In general, you can get/set values (and add/get/remove elements) by using a tag/path and an optional context.

Please note that:

  • an absolute path is relative to the root element: /FatturaElettronicaHeader means /p:FatturaElettronica/FatturaElettronicaHeader
  • tags and relative paths are prefixed with (.)//
  • xpath predicates are allowed: $invoice->getValue('DettaglioLinee[2]/NumeroLinea');

Get a value:

$invoice->getValue('ModalitaPagamento');

Get a value with a context:

$invoice->getValue('NumItem', 'DatiContratto');

Invalid queries (they return more than one element):

$invoice->getValue('IdPaese');
$invoice->getValue('Sede/Indirizzo', 'FatturaElettronicaHeader');

Set a value for a specific element:

$invoice->setValue('ProgressivoInvio', 10001);

Set many single values at once:

$invoice->setValues('IdTrasmittente', array(
    'IdCodice' => '09876543210',
    'IdPaese' => 'IT'
));
$invoice->setValues('CedentePrestatore/Sede', array(
    'Indirizzo' => 'VIA UNIVERSO 1'
));
$invoice->setValues('CessionarioCommittente', array(
    // CessionarioCommittente/DatiAnagrafici/CodiceFiscale
    'DatiAnagrafici/CodiceFiscale' => '01234567890',
    // Denominazione, somewhere inside CessionarioCommittente
    'Denominazione' => 'BETA SRL'
));
// Set values for second body
$body2 = $invoice->getBody(2);
$invoice->setValue('Numero', 44, $body2);
$invoice->setValue('Data', '2018-12-12', $body2);

Set values to multiple elements at once:

$invoice->setValuesToAll('DatiGenerali', array(
    // All "RiferimentoNumeroLinea" somewhere inside DatiGenerali
    'RiferimentoNumeroLinea' => 1,
    // All "IdDocumento" somewhere inside DatiGenerali
    'IdDocumento' => 4455,
    // All "NumItem" somewhere inside DatiGenerali
    'NumItem' => 1
));

Set values from an assoc array:

$array =  array(
    'DatiAnagraficiVettore' => array(
        'IdFiscaleIVA' => array(
            'IdPaese' => 'IT',
            'IdCodice' => '09876543210'
        ),
        'Anagrafica' => array(
            'Denominazione' => 'TRASPORTO SRLS'
        ),
        'NumeroLicenzaGuida' => 'AA090909'
    ),
    'MezzoTrasporto' => 'Mezzo',
    'CausaleTrasporto' => 'La causale del traporto',
    'NumeroColli' => '1',
    'Descrizione' => 'La descrizione'
);

$invoice->setValuesFromArray('DatiTrasporto', $array);

All but setValueToAll and setValuesToAll methods will throw an exception if $expr/$context don’t return just one element.

Set/Unset stylesheet

Set:

$invoice->setStylesheet('/path/to/xsl');

Unset:

$invoice->unsetStylesheet();

Validate invoice

You need Slamdunk/php-validatore-fattura-elettronica. If you install php-e-invoice-it via-composer, you got it as dependency; otherwise you must download and require it manually.

$invoice->validate();

An exception is thrown (with a message) if the XML is not valid, for example:

DOMDocument::schemaValidateSource(): Element 'DatiTrasmissione': Missing child element(s). Expected is ( CodiceDestinatario ).

Save invoice

Set an optional default destination dir for all invoices:

FatturaElettronica::setDefaultPrefixPath('path/to/dir');

Set an optional destination dir for current invoice:

$invoice->setPrefixPath('path/to/another/dir');

Save invoice:

$invoice->save();

Specify a custom filename:

$invoice->setFilename('my-invoice.xml')->save();

Send invoice to SdI

Setup a \Taocomp\Einvoicing\SdicoopClient\Client object (for connecting to webservice SdIRiceviFile):

use \Taocomp\Einvoicing\SdicoopClient\Client;
use \Taocomp\Einvoicing\SdicoopClient\FileSdIBase;
use \Taocomp\Einvoicing\SdicoopClient\RispostaSdIRiceviFile;

Client::setPrivateKey('/path/to/client.key');
Client::setClientCert('/path/to/client.pem');
Client::setCaCert('/path/to/ca.pem');

$client = new Client(array(
    'endpoint' => 'https://testservizi.fatturapa.it/ricevi_file',
    'wsdl'     => '/path/to/wsdl/SdIRiceviFile_v1.0.wsdl'
));

Send invoice:

$fileSdI = new FileSdIBase();
$fileSdI->load($invoice);
$response = new RispostaSdIRiceviFile($client->RiceviFile($fileSdI));

Notices

Create a new notice

NotificaEsitoCommittente:

$notice = new EsitoCommittente();

Load a notice from file

Set values

// Set some values from invoice, second body:
$notice->setValuesFromInvoice($invoice, 2);

// Set values
$notice->setValue('IdentificativoSdI', 1234567);
$notice->setValue('Esito', EsitoCommittente::EC01);

Set/Unset stylesheet

Set:

$notice->setStylesheet('/path/to/xsl');

Unset:

$notice->unsetStylesheet();

Save notice

// Set filename from invoice
$notice->setFilenameFromInvoice($invoice, '_EC_001');

// Save notice
$notice->save();

Send notice to SdI

Setup a \Taocomp\Einvoicing\SdicoopClient\Client object (for connecting to webservice SdIRiceviNotifica):

use \Taocomp\Einvoicing\SdicoopClient\Client;
use \Taocomp\Einvoicing\SdicoopClient\FileSdI;
use \Taocomp\Einvoicing\SdicoopClient\RispostaSdINotificaEsito;

Client::setPrivateKey('/path/to/client.key');
Client::setClientCert('/path/to/client.pem');
Client::setCaCert('/path/to/ca.pem');

$client = new Client(array(
    'endpoint' => 'https://testservizi.fatturapa.it/ricevi_notifica',
    'wsdl'     => __DIR__ . '/../wsdl/SdIRiceviNotifica_v1.0.wsdl'
));

Send notice:

$fileSdI = new FileSdI();
$fileSdI->load($notice);
$response = new RispostaSdINotificaEsito($client->NotificaEsito($fileSdI));

Tests

From inside the project root dir: ./vendor/bin/phpunit --testdox tests

Credits

We want to thank all contributors of Forum Italia - Fatturazione Elettronica who have shared their snippets and any available info.

Thanks to @Slamdunk for Slamdunk/php-validatore-fattura-elettronica!

License

GPLv3.