Come funziona davvero la discovery Peppol SMP e SML
Prima che una fattura Peppol possa essere consegnata, il sistema del mittente deve trovare l’Access Point del destinatario. Non esiste un registro centrale che si possa interrogare direttamente. Peppol utilizza invece una catena di discovery a due livelli che funziona come il DNS.
Comprendere questa catena è essenziale se si sta costruendo un’integrazione Peppol diretta piuttosto che delegare il routing a un provider di Access Point. Anche se si utilizza un provider, conoscere il meccanismo di discovery aiuta a diagnosticare i problemi di consegna.
I due componenti
SML (Service Metadata Locator) è la radice della catena. È un servizio basato su DNS gestito da OpenPEPPOL. Il suo compito è indicare dove trovare l’SMP di un partecipante.
SMP (Service Metadata Publisher) è un servizio a livello di partecipante. Ogni Access Point Peppol gestisce un SMP per i propri partecipanti registrati. L’SMP pubblica quali tipi di documento un partecipante può ricevere e l’URL dell’endpoint dove quei documenti devono essere consegnati.
Il flusso di discovery completo:
- Si dispone di un identificatore del partecipante (ad esempio, un numero di impresa belga)
- Si esegue l’hash e la codifica in un hostname DNS
- Si interroga la zona DNS dell’SML per trovare l’hostname SMP del partecipante
- Si interroga l’SMP per ottenere i metadati del servizio per il tipo di documento target
- Si estrae l’URL dell’endpoint e il certificato del destinatario
- Si consegna il messaggio AS4 firmato a quell’endpoint
Fase 1: costruire la ricerca DNS
L’identificatore del partecipante Peppol ha due parti: un codice schema e un valore. Per un’azienda belga identificata dal suo numero di impresa:
Scheme: 0208
Value: 0468863455
Full: iso6523-actorid-upis::0208:0468863455
Per trasformarlo in un hostname DNS:
- Portare in minuscolo l’identificatore completo del partecipante
- Calcolare l’hash MD5
- Codificare l’hash in Base32 (senza padding, minuscolo)
- Aggiungere il prefisso
b-(il prefisso SML Peppol) - Aggiungere il dominio SML:
edelivery.tech.ec.europa.eu
In C#:
static string BuildSmlHostname(string participantId)
{
var lower = participantId.ToLowerInvariant();
var hash = MD5.HashData(Encoding.UTF8.GetBytes(lower));
var b32 = Base32.ToBase32String(hash).ToLowerInvariant().TrimEnd('=');
return $"b-{b32}.iso6523-actorid-upis.edelivery.tech.ec.europa.eu";
}
La codifica Base32 è RFC 4648. La libreria standard .NET non include Base32; utilizzare una piccola utility o il pacchetto NuGet SimpleBase.
Fase 2: la query DNS SML
Interrogare l’hostname come CNAME. La risposta fornisce l’hostname SMP.
static async Task<string> LookupSmpHostname(string smlHostname)
{
var result = await Dns.GetHostEntryAsync(smlHostname);
// The CNAME target is the SMP hostname
return result.HostName;
}
Se la query DNS fallisce (NXDOMAIN), il partecipante non è registrato nella rete Peppol. Questa è una risposta definitiva “nessun partecipante trovato”, non un errore transitorio. Registrarlo e mostrarlo all’utente piuttosto che riprovare.
Fase 3: interrogare l’SMP
L’URL dell’endpoint SMP viene costruito dall’hostname SMP, dallo schema del partecipante e dal valore del partecipante. La specifica SMP Peppol (versione 2.0) definisce la struttura dell’URL:
https://{smp-hostname}/{scheme}%3A%3A{value}/services/{doctype}
Il separatore :: tra schema e valore è codificato in percent. Anche l’identificatore del tipo di documento è codificato in percent.
Per una fattura Peppol BIS Billing 3.0:
doctype: urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1
Esempio di richiesta completa:
GET https://{smp-hostname}/iso6523-actorid-upis%3A%3A0208%3A0468863455/services/urn%3Aoasis%3Anames...
L’SMP restituisce un documento XML firmato (i metadati del servizio). Ecco come appare la risposta, ridotta alle parti rilevanti:
<ServiceMetadata>
<ServiceInformation>
<ParticipantIdentifier scheme="iso6523-actorid-upis">0208:0468863455</ParticipantIdentifier>
<DocumentIdentifier>urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::...</DocumentIdentifier>
<ProcessList>
<Process>
<ProcessIdentifier scheme="cenbii-procid-ubl">urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</ProcessIdentifier>
<ServiceEndpointList>
<Endpoint transportProfile="peppol-as4-2.0">
<EndpointURI>https://ap.example.com/as4</EndpointURI>
<Certificate>MIIBxTCCA...</Certificate>
</Endpoint>
</ServiceEndpointList>
</Process>
</ProcessList>
</ServiceInformation>
<Signature>...</Signature>
</ServiceMetadata>
Fase 4: verificare la firma SMP
La risposta SMP è firmata con il certificato dell’Access Point. È necessario verificare questa firma prima di fidarsi dell’URL dell’endpoint.
Qui è dove la maggior parte delle implementazioni incontra problemi. Le risposte SMP utilizzano le Firme Digitali XML (XMLDSig). Molti server SMP ri-serializzano il documento firmato durante la distribuzione, il che modifica le dichiarazioni dei prefissi dei namespace. Questo interrompe il riferimento digest nella firma.
Il problema e la sua soluzione sono trattati in dettaglio in Problemi di validazione delle firme XML in Peppol. La versione breve: utilizzare un parser XML con PreserveWhitespace = true e non ri-serializzare il documento prima della verifica.
Dopo la verifica, estrarre l’URL dell’endpoint e il certificato:
var ns = new XmlNamespaceManager(doc.NameTable);
ns.AddNamespace("wsa", "http://www.w3.org/2005/08/addressing");
ns.AddNamespace("bdxr", "http://docs.oasis-open.org/bdxr/ns/SMP/2016/05");
var endpointNode = doc.SelectSingleNode(
"//bdxr:Endpoint[@transportProfile='peppol-as4-2.0']/bdxr:EndpointURI", ns);
var certNode = doc.SelectSingleNode(
"//bdxr:Endpoint[@transportProfile='peppol-as4-2.0']/bdxr:Certificate", ns);
var endpointUrl = endpointNode?.InnerText;
var cert = new X509Certificate2(Convert.FromBase64String(certNode?.InnerText ?? ""));
Fase 5: consegna
Con l’URL dell’endpoint e il certificato a disposizione, la fattura viene avvolta in un messaggio AS4 e consegnata tramite HTTPS. AS4 è il protocollo di trasporto Peppol. Richiede:
- La firma del messaggio AS4 con il certificato del proprio Access Point
- La cifratura del payload con il certificato del destinatario (dalla risposta SMP)
- L’invio all’
EndpointURIdall’SMP
L’implementazione di AS4 esula dall’ambito di questo articolo. In pratica, costruire il proprio livello AS4 è un lavoro di ingegneria significativo. La maggior parte delle organizzazioni utilizza un provider di Access Point certificato piuttosto che implementare direttamente AS4.
Caching
Le ricerche SMP dovrebbero essere memorizzate nella cache. Il TTL DNS sulla voce SML è tipicamente 3600 secondi. I metadati del servizio SMP non cambiano frequentemente. Una cache di 24 ore sulle risposte SMP è ragionevole per la maggior parte dei sistemi di produzione.
Non memorizzare nella cache i risultati negativi (NXDOMAIN) indefinitamente. Un partecipante potrebbe registrarsi dopo la prima ricerca. Memorizzare i risultati negativi per 15-30 minuti, non giorni.
Cosa può andare storto
NXDOMAIN dall’SML: il partecipante non è registrato. Questo è permanente, non transitorio. Non riprovare senza indagine.
SMP restituisce 404: il partecipante è registrato nell’SML ma non ha metadati di servizio per il tipo di documento richiesto. L’Access Point del destinatario potrebbe non aver configurato il supporto per Peppol BIS Billing 3.0.
Errore di validazione del certificato: la firma della risposta SMP utilizza un certificato non presente nell’elenco di fiducia della PKI Peppol. Questo dovrebbe essere trattato come un errore di sicurezza, non un errore di connettività. Rifiutare la risposta.
Errore di firma correlato ai namespace: vedere Problemi di validazione delle firme XML in Peppol.
L’endpoint restituisce un errore SOAP AS4: la fattura è stata consegnata ma rifiutata dall’Access Point del destinatario. Il codice di errore indica se il rifiuto è dovuto a mancata corrispondenza del certificato, tipo di documento non supportato o errore di validazione del payload.
SealDoc e la discovery SMP
L’API REST di SealDoc esegue internamente la catena di discovery SMP completa. Quando si invia una richiesta di generazione di fattura con un ID partecipante Peppol, l’API risolve l’endpoint, convalida la catena e instrada il documento. Se la discovery fallisce, l’API restituisce un errore strutturato che indica quale fase è fallita. Non è necessario implementare da soli la ricerca SML o SMP.
Per i partecipanti che devono eseguire ricerche sulla rete Peppol per test o audit, il validatore pubblico SealDoc può verificare se una fattura Peppol è instradabile a un partecipante specifico prima di procedere alla consegna.