php-e-invoice-it icon indicating copy to clipboard operation
php-e-invoice-it copied to clipboard

A PHP package for managing italian e-invoice and notice XML formats. (Pacchetto PHP per gestire il formato XML di fatture e notifiche come richiesto dal SdI).

#+TITLE: PHP E-invoice It

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 [[https://github.com/Slamdunk/php-validatore-fattura-elettronica][Slamdunk/php-validatore-fattura-elettronica]]

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

/([[file:README.it.org][Qui]] la documentazione aggiornata in italiano)./

Please refer to

  • [[https://github.com/taocomp/php-sdicoop-server][PHP SdICoop - Server]] for implementing web services required by the Italian Exchange System (aka "SdI")
  • [[https://github.com/taocomp/php-sdicoop-client][PHP SdICoop - Client]] to connect to SdI web services

See [[https://forum.italia.it/c/fattura-pa][Forum Italia - Fatturazione Elettronica]] for server configuration, interoperability tests, etc. In particular:

  • Apache configuration :: [[https://forum.italia.it/t/accreditamento-sdicoop-configurazione-ssl-su-apache/3314][Accreditamento SDICoop: configurazione SSL su Apache - Fatturazione Elettroni...]]
  • Interoperability tests :: [[https://forum.italia.it/t/test-interoperabilita-soluzioni/4370][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: #+BEGIN_SRC $invoice = new FatturaElettronica('FPA12'); #+END_SRC

Create a new FPR12 invoice: #+BEGIN_SRC $invoice = new FatturaElettronica('FPR12'); #+END_SRC

Create a new invoice from file #+BEGIN_SRC $invoice = new FatturaElettronica('/path/to/invoice.xml'); #+END_SRC *** Create a custom template invoice to be used later #+BEGIN_SRC $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(); #+END_SRC *** Invoice lot and line items Set 3 bodies: #+BEGIN_SRC $invoice->addBody(2); // or $invoice->setBodyCount(3); #+END_SRC

Set 4 line items for second body: #+BEGIN_SRC $invoice->addLineItem(3, 2); // or $invoice->setLineItemCount(4, 2); #+END_SRC

*** 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: #+BEGIN_SRC $invoice->getValue('ModalitaPagamento'); #+END_SRC

Get a value with a /context/: #+BEGIN_SRC $invoice->getValue('NumItem', 'DatiContratto'); #+END_SRC

Invalid queries (they return more than one element): #+BEGIN_SRC $invoice->getValue('IdPaese'); $invoice->getValue('Sede/Indirizzo', 'FatturaElettronicaHeader'); #+END_SRC

Set a value for a specific element: #+BEGIN_SRC $invoice->setValue('ProgressivoInvio', 10001); #+END_SRC

Set many single values at once: #+BEGIN_SRC $invoice->setValues('IdTrasmittente', array( 'IdCodice' => '09876543210', 'IdPaese' => 'IT' )); #+END_SRC

#+BEGIN_SRC $invoice->setValues('CedentePrestatore/Sede', array( 'Indirizzo' => 'VIA UNIVERSO 1' )); #+END_SRC

#+BEGIN_SRC $invoice->setValues('CessionarioCommittente', array( // CessionarioCommittente/DatiAnagrafici/CodiceFiscale 'DatiAnagrafici/CodiceFiscale' => '01234567890', // Denominazione, somewhere inside CessionarioCommittente 'Denominazione' => 'BETA SRL' )); #+END_SRC

#+BEGIN_SRC // Set values for second body $body2 = $invoice->getBody(2); $invoice->setValue('Numero', 44, $body2); $invoice->setValue('Data', '2018-12-12', $body2); #+END_SRC

Set values to multiple elements at once: #+BEGIN_SRC $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 )); #+END_SRC

Set values from an assoc array: #+BEGIN_SRC $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); #+END_SRC

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

*** Set/Unset stylesheet Set: #+BEGIN_SRC $invoice->setStylesheet('/path/to/xsl'); #+END_SRC

Unset: #+BEGIN_SRC $invoice->unsetStylesheet(); #+END_SRC

*** Validate invoice You need [[https://github.com/Slamdunk/php-validatore-fattura-elettronica][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. #+BEGIN_SRC $invoice->validate(); #+END_SRC An exception is thrown (with a message) if the XML is not valid, for example: #+BEGIN_SRC DOMDocument::schemaValidateSource(): Element 'DatiTrasmissione': Missing child element(s). Expected is ( CodiceDestinatario ). #+END_SRC

*** Save invoice Set an optional default destination dir for all invoices: #+BEGIN_SRC FatturaElettronica::setDefaultPrefixPath('path/to/dir'); #+END_SRC

Set an optional destination dir for current invoice: #+BEGIN_SRC $invoice->setPrefixPath('path/to/another/dir'); #+END_SRC

Save invoice: #+BEGIN_SRC $invoice->save(); #+END_SRC

Specify a custom filename: #+BEGIN_SRC $invoice->setFilename('my-invoice.xml')->save(); #+END_SRC

*** Send invoice to SdI Setup a ~\Taocomp\Einvoicing\SdicoopClient\Client~ object (for connecting to webservice SdIRiceviFile): #+BEGIN_SRC 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' )); #+END_SRC

Send invoice: #+BEGIN_SRC $fileSdI = new FileSdIBase(); $fileSdI->load($invoice); $response = new RispostaSdIRiceviFile($client->RiceviFile($fileSdI)); #+END_SRC

** Notices *** Create a new notice NotificaEsitoCommittente: #+BEGIN_SRC $notice = new EsitoCommittente(); #+END_SRC

*** Load a notice from file *** Set values #+BEGIN_SRC // Set some values from invoice, second body: $notice->setValuesFromInvoice($invoice, 2);

// Set values $notice->setValue('IdentificativoSdI', 1234567); $notice->setValue('Esito', EsitoCommittente::EC01); #+END_SRC *** Set/Unset stylesheet Set: #+BEGIN_SRC $notice->setStylesheet('/path/to/xsl'); #+END_SRC

Unset: #+BEGIN_SRC $notice->unsetStylesheet(); #+END_SRC

*** Save notice #+BEGIN_SRC // Set filename from invoice $notice->setFilenameFromInvoice($invoice, '_EC_001');

// Save notice $notice->save(); #+END_SRC

*** Send notice to SdI Setup a ~\Taocomp\Einvoicing\SdicoopClient\Client~ object (for connecting to webservice SdIRiceviNotifica): #+BEGIN_SRC 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' )); #+END_SRC

Send notice: #+BEGIN_SRC $fileSdI = new FileSdI(); $fileSdI->load($notice); $response = new RispostaSdINotificaEsito($client->NotificaEsito($fileSdI)); #+END_SRC

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

  • Credits We want to thank all contributors of [[https://forum.italia.it/c/fattura-pa][Forum Italia - Fatturazione Elettronica]] who have shared their snippets and any available info.

Thanks to @Slamdunk for [[https://github.com/Slamdunk/php-validatore-fattura-elettronica][Slamdunk/php-validatore-fattura-elettronica]]!

  • License GPLv3.