Vai al contenuto

Fattura elettronica in C#

Questo tutorial crea tre semplici applicazioni console C# da zero:

  1. Receive: si connette e autentica con Invoicetronic API e scarica eventuali nuove fatture in arrivo.
  2. Send: si connette e autentica con Invoicetronic API e invia una fattura allo SDI.
  3. Update: si connette e autentica con Invoicetronic API e consulta la cronologia delle notifiche restituite dallo SDI.

Prima di continuare, assicurati che tutti i prerequisiti sotto siano soddisfatti.

Prerequisiti

Presupponiamo che questi prerequisiti siano soddisfatti:

Utilizziamo lo strumento dotnet e VS Code in quanto sono disponibili sulla maggior parte dei sistemi, ma puoi seguire con il tuo IDE preferito (Visual Studio, Rider, ecc.) se preferisci.

Tip

Per un'esperienza C# ottimale in VS Code, assicurati che l'estensione C# Dev Kit sia installata e abilitata. Per ulteriori informazioni, consulta Iniziare con C# in VS Code.

Lo sapevi?

Siamo autori e maintainer del package open-source FatturaElettronica.NET. Se ti serve una liberia per leggere, scrivere, serializzare, de-serializzare e convalidare fatture, faresti bene a dargli una occhiata.

Receive

Crea l'app

Il primo passo è creare l'applicazione:

dotnet new console -n receive
Il comando ha creato un nuovo progetto C# chiamato "receive" in una directory con lo stesso nome. Entra in quella directory:

cd receive

Installa l'SDK

Una volta nella directory receive, installa l'SDK C#:

 dotnet add package Invoicetronic.Sdk

Una volta fatto, apri VS Code nella directory corrente:

code .

Clicca sul file Program.cs per vedere il suo contenuto nel pannello destro di VS Code.

Configura l'SDK

Sostituisci il contenuto predefinito di Program.cs con il seguente:

Configura l'SDK
using Invoicetronic.Sdk.Api;
using Invoicetronic.Sdk.Client;
using static Invoicetronic.Sdk.Model.Receive;

// Configura l'SDK.
var config = new Configuration
{
    BasePath = "https://api.invoicetronic.com/v1",
    Username = "LA TUA CHIAVE API DI TEST (inizia con ik_test_)"
};

Come puoi vedere, inizializziamo un'istanza di Configuration impostando il percorso base dell'API e la tua chiave API di test (non quella live). Nota come utilizziamo la proprietà Username per impostare la chiave API.

Le chiavi API vengono fornite in coppia

Quando crei il tuo account, ottieni una coppia di chiavi API. Una è la chiave di test per la Sandbox API, e l'altra è quella live dell'API. Puoi distinguerle perché la prima inizia con ik_test_, mentre la seconda inizia con ik_live_. In questo tutorial, usa sempre la chiave di test.

Scarica le fatture

Siamo pronti per effettuare una richiesta. Vogliamo scaricare nuove fatture dei fornitori che potrebbero essere disponibili dallo SDI. Aggiungi queste righe:

Scarica le fatture non lette
// Scarica le fatture non lette.
var receiveApi = new ReceiveApi(config);

try
{
    var inboundInvoices = await receiveApi.ReceiveGetAsync(unread:true, includePayload:true);
    Console.WriteLine($"Ricevute {inboundInvoices.Count} fatture");

    foreach (var invoice in inboundInvoices)
    {
        switch (invoice.Encoding)
        {
            case EncodingEnum.Xml:
                File.WriteAllText(invoice.FileName, invoice.Payload);
                break;
            case EncodingEnum.Base64:
                File.WriteAllBytes(invoice.FileName, Convert.FromBase64String(invoice.Payload));
                break;
        }

        Console.WriteLine($"Scaricato {invoice.FileName} da un fornitore con Partita IVA {invoice.Prestatore}");
    }
}
catch (ApiException e)
{
    Console.WriteLine($"{e.Message} - {e.ErrorCode}");
}

Inclusione del Payload

Impostiamo includePayload: true per recuperare il contenuto effettivo della fattura nella proprietà Payload. Senza questo parametro, il campo Payload sarebbe null per impostazione predefinita, il che aumenta le prestazioni e riduce le dimensioni della risposta quando hai bisogno solo dei metadati.

Passa al terminale(1) poi digita:

  1. Se il pannello del terminale non è già aperto, clicca sul menu Terminale, poi Nuovo Terminale.
dotnet run

Dovresti ottenere un output simile a questo:

Ricevute 3 fatture
Scaricato file1.xml da un fornitore con Partita IVA IT06157670966
Scaricato file2.xml.p7m da un fornitore con Partita IVA IT01280270057
Scaricato file3.xml.p7m da un fornitore con Partita IVA IT01280270057

I file sono nella directory corrente, pronti per essere ispezionati.

Non ricevi fatture nell'ambiente di produzione?

Assicurati di esserti registrato presso l'Agenzia delle Entrate, che è un requisito per l'ambiente di produzione.

Cosa abbiamo imparato

In questo esempio, abbiamo imparato diverse cose.

  1. Dobbiamo configurare l'SDK impostando sia la proprietà BasePath che Username, quest'ultima inizializzata con la chiave API.

  2. Dobbiamo istanziare una classe che rappresenta l'endpoint con cui vogliamo lavorare. In questo caso, sfruttiamo ReceiveApi per scaricare le fatture in arrivo.

  3. Le classi endpoint come ReceiveApi offrono metodi per interagire con la loro entità target. Chiamiamo ReceiveGetAsync per recuperare le fatture. Poiché vogliamo solo fatture nuove e non lette, passiamo unread: true. Passiamo anche includePayload: true per recuperare il contenuto effettivo della fattura (se esegui l'esempio una seconda volta, probabilmente non riceverai alcuna fattura a meno che non ne sia arrivata qualcuna).

  4. La classe Receive espone proprietà preziose come Encoding, FileName e Payload. Quest'ultima contiene il contenuto della fattura, come testo normale o codificato in Base64, come descritto da Encoding.

Codice sorgente su GitHub

Il codice sorgente per questo Quickstart è disponibile anche su GitHub.

Send

Crea l'app

Il primo passo è creare l'applicazione:

dotnet new console -n send
Il comando ha creato un nuovo progetto C# chiamato "quickstart" in una directory con lo stesso nome. Entra in quella directory:

cd send

Installa l'SDK

Una volta nella directory quickstart, installa l'SDK C#:

 dotnet add package Invoicetronic.Sdk

Una volta fatto, apri VS Code nella directory corrente:

code .

Clicca sul file Program.cs per vedere il suo contenuto nel pannello destro di VS Code.

Configura l'SDK

Sostituisci il contenuto predefinito di Program.cs con il seguente:

Configura l'SDK
using Invoicetronic.Sdk.Api;
using Invoicetronic.Sdk.Client;
using Invoicetronic.Sdk.Model;

// Configura l'SDK.
var config = new Configuration
{
    BasePath = "https://api.invoicetronic.com/v1",
    Username = "LA TUA CHIAVE API DI TEST (inizia con ik_test_)"
};

Come puoi vedere, inizializziamo un'istanza di Configuration impostando il percorso base dell'API e la tua chiave API di test (non quella live). Nota come utilizziamo la proprietà Username per impostare la chiave API.

Le chiavi API vengono fornite in coppia

Quando crei il tuo account, ottieni una coppia di chiavi API. Una è la chiave di test per la Sandbox API, e l'altra è quella live dell'API. Puoi distinguerle perché la prima inizia con ik_test_, mentre la seconda inizia con ik_live_. In questo tutorial, usa sempre la chiave di test.

Invia una fattura

Siamo pronti per effettuare una richiesta. Vogliamo inviare una fattura allo SDI. Aggiungi il seguente codice:

Invia una fattura
// Invia una fattura
var filePath = "/qualche/percorso/file/nomefile.xml";

var metaData = new Dictionary<string, string>
{
    { "internal_id", "123" },
    { "created_with", "myapp" },
    { "some_other_custom_data", "value" },
};

var sendApi = new SendApi(config);

try
{
    var sentInvoice = await sendApi.SendPostAsync(new Send(payload: File.ReadAllText(filePath))
    {
        FileName = Path.GetFileName(filePath),
        MetaData = metaData
    });

    Console.WriteLine($"La fattura è stata inviata con successo, ora ha l'Id univoco {sentInvoice.Id}.");
}
catch (ApiException e)
{
    Console.WriteLine($"{e.Message} - {e.ErrorCode}");
}

Passa al terminale(1) poi digita:

  1. Se il pannello del terminale non è già aperto, clicca sul menu Terminale, poi Nuovo Terminale.
dotnet run

Dovresti ottenere un output simile a questo:

La fattura nomefile.xml è stata inviata con successo, ora ha l'Id univoco 123.

Verificare lo stato della fattura

Quando inoltri una fattura allo SDI, la consegna non è istantanea: l'SDI esegue dei controlli e restituisce una sequenza di notifiche che descrivono lo stato del processo (Inviato, Consegnato, Scartato, ecc.). La classe Send espone la proprietà LatestState con lo stato corrente, evitando una chiamata separata a /update quando ti serve sapere solo come è andata.

Leggere lo stato corrente
// Recupera lo stato più recente di una fattura già inviata
var fresh = await sendApi.SendIdGetAsync(sentInvoice.Id);
Console.WriteLine($"Stato corrente: {fresh.LatestState?.ToString() ?? "In elaborazione"}");

Subito dopo l'invio, LatestState può essere null: l'SDI non ha ancora processato il documento. Ricontrolla dopo qualche secondo o, meglio, configura un webhook per ricevere una notifica push ad ogni cambio di stato.

Risparmia richieste API

Usa LatestState su Send ogni volta che ti serve solo lo stato corrente: una sola chiamata invece di una a /send più una a /update. Ricorri a UpdateApi solo quando ti serve la cronologia completa delle transizioni.

Cosa abbiamo imparato

In questo esempio, abbiamo imparato diverse cose.

  1. Dobbiamo configurare l'SDK impostando sia la proprietà BasePath che Username, quest'ultima inizializzata con la chiave API.

  2. Dobbiamo istanziare una classe che rappresenta l'endpoint con cui vogliamo lavorare. In questo caso, sfruttiamo SendApi per inviare fatture. Le classi endpoint come SendApi offrono metodi per interagire con la loro entità target. Chiamiamo InvoiceV1SendPosttAsync per inviare una fattura.

  3. La classe Send espone proprietà preziose come FileName, MetaData e Payload. Quest'ultima contiene il contenuto della fattura, mentre MetaData è opzionale e associa dati personalizzati al documento.

  4. La classe Send espone anche LatestState con lo stato SDI corrente, leggibile via SendIdGetAsync(id). Evita una chiamata a /update quando serve solo conoscere lo stato.

Codice sorgente su GitHub

Il codice sorgente per questo Quickstart è disponibile anche su GitHub.

Update

Per lo stato corrente di una fattura inviata, è sufficiente leggere LatestState dalla classe Send (vedi Verificare lo stato della fattura). Se invece vuoi la cronologia completa delle transizioni — per esempio per capire perché una fattura è stata scartata, mostrare in UI tutti i passaggi di stato con timestamp, o tracciare le notifiche restituite da un ente della Pubblica Amministrazione — usa UpdateApi.

Le query su /update sono gratuite

Le richieste a /update non vengono conteggiate sul tuo piano: puoi consultare la cronologia delle notifiche con la frequenza che preferisci.

Crea l'app

dotnet new console -n update
cd update

Installa l'SDK

dotnet add package Invoicetronic.Sdk

Recuperare la cronologia delle notifiche

Sostituisci il contenuto di Program.cs con il seguente:

Cronologia delle notifiche per una fattura
using Invoicetronic.Sdk.Api;
using Invoicetronic.Sdk.Client;

// Configura l'SDK
var config = new Configuration
{
    BasePath = "https://api.invoicetronic.com/v1",
    Username = "LA TUA CHIAVE API DI TEST (inizia con ik_test_)"
};

// Id della fattura inviata di cui vogliamo ricostruire la cronologia
const int sendId = 225;

var updateApi = new UpdateApi(config);

try
{
    var updates = await updateApi.UpdateGetAsync(
        sendId: sendId,
        sort: "last_update");

    Console.WriteLine($"Trovate {updates.Count} notifiche per la fattura {sendId}");

    foreach (var update in updates)
    {
        var description = update.Description ?? "OK";
        Console.WriteLine($"  [{update.LastUpdate:O}] state={update.State} - {description}");
    }
}
catch (ApiException e)
{
    Console.WriteLine($"{e.Message} - {e.ErrorCode}");
}

Esegui l'applicazione:

dotnet run

Dovresti ottenere un output simile a questo:

Trovate 2 notifiche per la fattura 225
  [2025-01-23T16:56:14.1110000Z] state=Inviato - OK
  [2025-01-23T17:12:03.8420000Z] state=Consegnato - OK

La proprietà State è la più importante. I valori più comuni sono:

Valore Nome Descrizione
2 Inviato Inviata allo SDI.
5 Consegnato Consegnata al destinatario.
7 Scartato Rifiutata dallo SDI. In Description trovi il motivo.

L'elenco completo dei valori è disponibile nella API Reference. Puoi anche filtrare per stato, per esempio per ottenere solo le fatture scartate:

var updates = await updateApi.UpdateGetAsync(state: State.Scartato);

Monitora sempre lo stato delle fatture inviate

Lo stato Inviato significa solo che il documento è stato preso in carico dallo SDI, non che sia stato consegnato. Uno stato Scartato indica che la fattura non è stata accettata e potrebbe richiedere una correzione e un nuovo invio.

Cosa abbiamo imparato

  1. Per consultare la cronologia delle notifiche utilizziamo la classe UpdateApi invece di SendApi o ReceiveApi.

  2. Il metodo UpdateGetAsync() accetta filtri come sendId (per le notifiche di una specifica fattura inviata), state (per filtrare per stato), lastUpdateFrom/lastUpdateTo (intervallo temporale) e altri.

  3. Le query su /update sono gratuite e non vengono conteggiate sul tuo piano, quindi puoi richiamarle con la frequenza che ti serve.

Codice sorgente su GitHub

Il codice sorgente per questo Quickstart è disponibile anche su GitHub.