Vai al contenuto

Fattura elettronica in Ruby

Questo tutorial crea tre semplici applicazioni Ruby da zero:

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

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

Prerequisiti

Assumiamo che questi prerequisiti siano soddisfatti:

Tip

Per un'esperienza Ruby ottimale, considera l'uso di rbenv o RVM per la gestione delle versioni Ruby.

Lo sapevi?

Il Ruby SDK è compatibile con Rails, Sinatra e tutte le moderne applicazioni Ruby.

Receive

Creare l'applicazione

Il primo passo è creare la directory dell'applicazione:

mkdir receive && cd receive

Installare l'SDK

Crea un file Gemfile con il seguente contenuto:

Gemfile
source 'https://rubygems.org'

gem 'invoicetronic_sdk'

Poi installa le dipendenze:

bundle install

Configurare l'SDK

Crea il file receive.rb:

Configurare l'SDK
require 'invoicetronic_sdk'

# Configura l'SDK
InvoicetronicSdk.configure do |config|
  config.host = 'https://api.invoicetronic.com/v1'
  config.username = 'LA TUA CHIAVE API DI TEST (inizia con ik_test_)'
  config.password = ''
end

Come puoi vedere, configuriamo l'SDK impostando l'host e l'autenticazione HTTP Basic con la tua chiave API di test (non quella live). Nota come usiamo username per la chiave API e password vuoto.

Le chiavi API vengono fornite in coppia

Quando crei il tuo account, ottieni una coppia di chiavi API. Una è la chiave di test per l'API Sandbox, e l'altra è quella live. 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.

Scaricare le fatture

Siamo pronti per effettuare una richiesta. Vogliamo scaricare le nuove fatture passive che potrebbero essere disponibili dall'SDI. Aggiungi questo codice nel file:

Scaricare le fatture non lette
require 'base64'

# Scarica le fatture non lette
api_instance = InvoicetronicSdk::ReceiveApi.new

begin
  inbound_invoices = api_instance.receive_get(
    nil,    # company_id
    nil,    # identifier
    true,   # unread
    nil,    # committente
    nil,    # prestatore
    nil,    # file_name
    nil,    # last_update_from
    nil,    # last_update_to
    nil,    # date_sent_from
    nil,    # date_sent_to
    nil,    # document_date_from
    nil,    # document_date_to
    nil,    # document_number
    true,   # include_payload
    nil,    # page
    nil,    # page_size
    nil     # sort
  )

  puts "Ricevute #{inbound_invoices.length} fatture"

  inbound_invoices.each do |invoice|
    if invoice.encoding == 'Xml'
      File.write(invoice.file_name, invoice.payload)
    elsif invoice.encoding == 'Base64'
      File.write(invoice.file_name, Base64.decode64(invoice.payload))
    end

    puts "Scaricato #{invoice.file_name} da un fornitore con Partita IVA #{invoice.prestatore}"
  end
rescue InvoicetronicSdk::ApiError => e
  puts "Errore: #{e}"
end

Inclusione del Payload

Impostiamo include_payload a true per recuperare il contenuto effettivo della fattura nella proprietà payload. Senza questo parametro, il campo payload sarebbe nil di default, il che migliora le prestazioni e riduce la dimensione della risposta quando hai bisogno solo dei metadati.

Esegui l'applicazione:

ruby receive.rb

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 live?

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

Cosa abbiamo imparato

In questo esempio, abbiamo imparato diverse cose.

  1. Dobbiamo configurare l'SDK usando InvoicetronicSdk.configure, impostando l'host e configurando l'autenticazione HTTP Basic con username (chiave API) e password vuota.

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

  3. Le classi endpoint come ReceiveApi offrono metodi per interagire con la loro entità target. Chiamiamo receive_get per recuperare le fatture. Poiché vogliamo solo fatture nuove e non lette, passiamo true per il parametro unread. Passiamo anche true per include_payload per recuperare il contenuto effettivo della fattura.

  4. Gli oggetti fattura espongono proprietà come encoding, file_name e payload. L'ultimo contiene il contenuto della fattura, come testo semplice o codificato in Base64, come descritto da encoding che ha i valori 'Xml' o 'Base64'.

Codice sorgente su GitHub

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

Send

Creare l'applicazione

Il primo passo è creare la directory dell'applicazione:

mkdir send && cd send

Installare l'SDK

Crea un file Gemfile con il seguente contenuto:

Gemfile
source 'https://rubygems.org'

gem 'invoicetronic_sdk'

Poi installa le dipendenze:

bundle install

Configurare l'SDK

Crea il file send.rb:

Configurare l'SDK
require 'invoicetronic_sdk'

# Configura l'SDK
InvoicetronicSdk.configure do |config|
  config.host = 'https://api.invoicetronic.com/v1'
  config.username = 'LA TUA CHIAVE API DI TEST (inizia con ik_test_)'
  config.password = ''
end

Come puoi vedere, configuriamo l'SDK impostando l'host e l'autenticazione HTTP Basic con la tua chiave API di test (non quella live).

Le chiavi API vengono fornite in coppia

Quando crei il tuo account, ottieni una coppia di chiavi API. Una è la chiave di test per l'API Sandbox, e l'altra è quella live. 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.

Inviare una fattura

Siamo pronti per effettuare una richiesta. Vogliamo inviare una fattura all'SDI. Aggiungi questo codice nel file:

Inviare una fattura
# Invia una fattura
file_path = '/qualche/percorso/file/nomefile.xml'

meta_data = {
  'internal_id' => '123',
  'created_with' => 'myapp',
  'some_other_custom_data' => 'value'
}

api_instance = InvoicetronicSdk::SendApi.new

begin
  payload = File.read(file_path)

  send_data = InvoicetronicSdk::Send.new(
    file_name: File.basename(file_path),
    payload: payload,
    meta_data: meta_data
  )

  sent_invoice = api_instance.send_post(send_data)

  puts "La fattura è stata inviata con successo, ora ha l'Id univoco #{sent_invoice.id}."
rescue InvoicetronicSdk::ApiError => e
  puts "Errore: #{e}"
end

Esegui l'applicazione:

ruby send.rb

Dovresti ottenere un output simile a questo:

La fattura è 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: lo SDI esegue dei controlli e restituisce una sequenza di notifiche che descrivono lo stato del processo (Inviato, Consegnato, Scartato, ecc.). Il modello Send espone l'attributo latest_state 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
fresh = api_instance.send_id_get(sent_invoice.id)
puts "Stato corrente: #{fresh.latest_state || 'In elaborazione'}"

Subito dopo l'invio, latest_state può essere nil: lo 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 latest_state 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 usando InvoicetronicSdk.configure, impostando l'host e configurando l'autenticazione HTTP Basic.

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

  3. Il modello Send accetta parametri nel costruttore: file_name, payload e meta_data. Il payload contiene il contenuto della fattura, mentre meta_data è opzionale e lega dati personalizzati al documento.

  4. Il modello Send espone anche latest_state con lo stato SDI corrente, leggibile via send_id_get(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 latest_state dal modello 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.

Creare l'applicazione

mkdir update && cd update

Installare l'SDK

Crea un file Gemfile con il seguente contenuto:

Gemfile
source 'https://rubygems.org'

gem 'invoicetronic_sdk'

Poi installa le dipendenze:

bundle install

Recuperare la cronologia delle notifiche

Crea il file update.rb:

Cronologia delle notifiche per una fattura
require 'invoicetronic_sdk'

# Configura l'SDK
InvoicetronicSdk.configure do |config|
  config.host = 'https://api.invoicetronic.com/v1'
  config.username = 'LA TUA CHIAVE API DI TEST (inizia con ik_test_)'
  config.password = ''
end

# Id della fattura inviata di cui vogliamo ricostruire la cronologia
send_id = 225

api_instance = InvoicetronicSdk::UpdateApi.new

begin
  updates = api_instance.update_get(
    nil,           # company_id
    nil,           # identifier
    nil,           # prestatore
    nil,           # unread
    send_id,       # send_id
    nil,           # state
    nil,           # last_update_from
    nil,           # last_update_to
    nil,           # date_sent_from
    nil,           # date_sent_to
    nil,           # page
    nil,           # page_size
    'last_update'  # sort
  )

  puts "Trovate #{updates.length} notifiche per la fattura #{send_id}"

  updates.each do |update|
    description = update.description || 'OK'
    puts "  [#{update.last_update}] state=#{update.state} - #{description}"
  end
rescue InvoicetronicSdk::ApiError => e
  puts "Errore: #{e}"
end

Esegui l'applicazione:

ruby update.rb

Dovresti ottenere un output simile a questo:

Trovate 2 notifiche per la fattura 225
  [2025-01-23 16:56:14 UTC] state=Inviato - OK
  [2025-01-23 17:12:03 UTC] state=Consegnato - OK

Il campo state è la proprietà 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.

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 update_get() accetta filtri come send_id (per le notifiche di una specifica fattura inviata), state (per filtrare per stato), last_update_from/last_update_to (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.