Validazione fatture elettroniche off-line

Vorrei sapere se esistono strumenti per validare (controlli formali) le fatture elettroniche off-line (meglio ancora se richiamabili da procedure batch).

Grazie.

Prova a guadare qui:


Hanno rilasciato in OpenSource anche il software, in .NET, su Github

Spero ti sia di aiuto.
Leo.

1 Mi Piace

Se vuoi validare la firma in modo corretto serve connessione. Se ti basta una verifica dell’xml allora basta usare un normale validatore xml, con un repository locale dei vari xsd (altrimenti anche quest’ultimo richiede connessione).

L’xsd non riesce a fare tutti i controlli formali, ci sono diverse casistiche nelle specifiche che prevedono ad esempio la popolazione di un campo a patto che un altro campo abbia un determinato valore (es. verifica dei totali e/o i riepiloghi IVA).

Molto interessante, vincolato però alla piattaforma .NET che non utilizzo. Prodotti simili non .NET ne conosci?

Purtroppo no: ma non li ho nemmeno cercati a fondo.

LM

In realtĂ  per validare la firma non serve la connessione, basta la lista dei certificati.
(serve la connessione solo per eventualmente verificare la CRL dato che le CRL si aggiornano di frequente)
La lista dei certificati è facilmente ottenibile dal sito dell’eidas per l’Italia o dagli equivalenti siti europei per le firme non italiane.

questo è lo script che uso io per aggiornare i certificati ogni notte…

#! /bin/bash
XML_CERTS='https://eidas.agid.gov.it/TL/TSL-IT.xml'
wget -q --tries=2 -O /tmp/Ca.xml ${XML_CERTS}
if [ -f /tmp/Ca.xml ]; then
  cmp /tmp/Ca.xml /etc/efatt/Ca.xml > /dev/null 2>&1
  if [ $? -ne 0 ]; then
    for i in `grep '<X509Certificate' /tmp/Ca.xml`; do
      echo -e "-----BEGIN CERTIFICATE-----"
      echo $i| sed -e 's/<\/*X509Certificate>//g'| openssl base64 -d -A| openssl base64
      echo -e "-----END CERTIFICATE-----"
    done >/etc/efatt/CA.pem
    mv /tmp/Ca.xml /etc/efatt/Ca.xml
  else
    rm /tmp/Ca.xml
  fi
fi

Si memorizza l’xml scaricato dall’eidas in /tmp lo confronta con la vecchia copia in /etc/efatt e se le due versioni differiscono estrae i certificati in /etc/efatt/CA.pem e sposta la nuova versione dell’xml in /etc/efatt

ho visto che la variazione della lista avviene poche volte al mese… (ultima variazione il 14 di gennaio)

1 Mi Piace

Ah ok, avevo male interpretato la richiesta… In effetti per quelli serve della logica, ma siamo sicuri che chiunque tranne sogei conosca davvero i controlli che fanno in modo preciso? Forse ci si può avvicinare ma penso non sarà possibile farlo “uguale”.

Intendevo proprio questo…

Sicuramente è come dici tu, a me basterebbe qualcosa che si limiti ai controlli delle specifiche tecniche, di quello che fa la Sogei ovviamente non possiamo saperlo.

Per quanto riguarda i controlli formali sulla fattura, sono tutti elencati nel documento:
https://www.fatturapa.gov.it/export/fatturazione/sdi/Elenco_Controlli_V1.5.pdf

Ce ne sono alcuni che non possono essere replicati (per esempio controllo validità partita IVA e C.F., oppure univocità del nome del file), ma molti dei controlli sono scritti (nella seconda parte del documento) sotto forma di pseudocodice che si può facilmente reimplementare.

Bisogna però fare attenzione perché ci sono dei controlli che sono stati eliminati, ma il documento non è stato aggiornato.

Per esempio, sembra che il controllo 426 sia stato eliminato.
Questo è dovuto al fatto che la prima parte del controllo (PEC non valorizzata in caso di codice destinatario 0000000) non si applica più per modifica delle specifiche tecniche (adesso è possibile indicare il solo codice destinatario 0000000 senza nient’altro). La seconda parte del controllo (PEC valorizzata con codice destinatario diverso da 0000000) dovrebbe continuare ad essere applicata ma non è così, probabilmente perché hanno eliminato del tutto il controllo invece di modificarlo.

1 Mi Piace

Grazie Vladan, davvero molto interessante. Se ne esistessero implementazioni già fatte (non .NET) sarebbe la ciliegina sulla torta, altrimenti procederò con l’implementazione

mio contributo al forum (non ho trovato altre occorrenze in altri thread).

Per la validazione file XML con file XSD in PHP si può usare quanto segue (copiato e incollato da stackxchange, in origine era un validatore di feed RSS che ho adattato). Non risolve tutti i problemi (non fa tutti i controlli dell’SDI), ma se il file passa la validazione locale per lo meno vi evitate l’errore generico 00200 (che ogni volta dovevo fare 80 tentativi per capire da cos’era generato)

ecco la classe:

class DOMValidator
{

/**
 * @var string
 */
//protected $feedSchema = __DIR__  .  '/sample.xsd';
public $feedSchema = NULL;

/**
 * @var int
 */
public $feedErrors = 0;
/**
 * Formatted libxml Error details
 *
 * @var array
 */
public $errorDetails;
/**
 * Validation Class constructor Instantiating DOMDocument
 *
 * @param \DOMDocument $handler [description]
 */
public function __construct()
{
    $this->handler = new \DOMDocument('1.0', 'utf-8');
}
/**
 * @param \libXMLError object $error
 *
 * @return string
 */
private function libxmlDisplayError($error)
{
    $errorString = "Error $error->code in $error->file (Line:{$error->line}):";
    $errorString .= trim($error->message);
    return $errorString;
}
/**
 * @return array
 */
private function libxmlDisplayErrors()
{
    $errors = libxml_get_errors();
    $result    = [];
    foreach ($errors as $error) {
        $result[] = $this->libxmlDisplayError($error);
    }
    libxml_clear_errors();
    return $result;
}
/**
 * Validate Incoming Feeds against Listing Schema
 *
 * @param resource $xml
 *
 * @return bool
 *
 * @throws \Exception
 */
public function validateFeeds($xml)
{
    if (!class_exists('DOMDocument')) {
        throw new \DOMException("'DOMDocument' class not found!");
        return false;
    }
    
    if (!file_exists($this->feedSchema)) {
        throw new \Exception('Schema is Missing, Please add schema to feedSchema property');
        return false;
    }
    
    libxml_use_internal_errors(true);
    

    $this->handler->loadXML($xml, LIBXML_NOBLANKS);
    if (!$this->handler->schemaValidate($this->feedSchema)) {
       $this->errorDetails = $this->libxmlDisplayErrors();
       $this->feedErrors   = 1;
    } else {
      //The file is valid
       return true;
    }
}
/**
 * Display Error if Resource is not validated
 *
 * @return array
 */
public function displayErrors()
{
    return $this->errorDetails;
}
}

esempio d’uso:

	$validator = new DomValidator;
	$validator->feedSchema = "/path/to/localcopy/schemafattel.xsd";
	$validated = $validator->validateFeeds($xml);
	
	if ($validated) {
		echo "File xml validato con successo";
	} else {
		echo "<pre>";
		print_r($validator->displayErrors());
		echo "</pre>";
	}		

$xml contiene lo stream xml vero e proprio (non il nome file)

Importante: usando l’xsd del ministero mi andava in timeout cercando di scaricare l’xsd del w3c (xmldsig-core-schema.xsd)

per risolvere ho messo una copia in locale del file e ho modificato l’xsd cambiando il percorso del file xsd. In questo modo valida all’istante

Saluti a tutti e buon uso