← Back to all articles

Wie Peppol SMP- und SML-Discovery tatsächlich funktioniert

SealDoc Team · · 5 min read

Bevor eine Peppol-Rechnung zugestellt werden kann, muss das System des Absenders den Access Point des Empfängers finden. Es gibt kein zentrales Register, das direkt abgefragt werden kann. Stattdessen verwendet Peppol eine zweistufige Discovery-Kette, die wie DNS funktioniert.

Das Verständnis dieser Kette ist unerlässlich, wenn Sie eine direkte Peppol-Integration aufbauen, anstatt das Routing an einen Access-Point-Anbieter zu delegieren. Selbst wenn Sie einen Anbieter nutzen, hilft das Verständnis des Discovery-Mechanismus bei der Fehlersuche bei Zustellungsfehlern.

Die zwei Komponenten

SML (Service Metadata Locator) ist die Wurzel der Kette. Es ist ein DNS-basierter Dienst, der von OpenPEPPOL betrieben wird. Seine Aufgabe ist es, Ihnen mitzuteilen, wo Sie den SMP eines Teilnehmers finden.

SMP (Service Metadata Publisher) ist ein teilnehmerseitiger Dienst. Jeder Peppol-Access-Point betreibt einen SMP für seine registrierten Teilnehmer. Der SMP veröffentlicht, welche Dokumenttypen ein Teilnehmer empfangen kann und die Endpunkt-URL, an die diese Dokumente zugestellt werden sollen.

Der vollständige Discovery-Ablauf:

  1. Sie haben eine Teilnehmerkennung (z.B. eine belgische Unternehmensnummer)
  2. Hash und Kodierung in einen DNS-Hostnamen
  3. Abfrage der SML-DNS-Zone, um den SMP-Hostnamen des Teilnehmers zu finden
  4. Abfrage des SMP, um die Dienstmetadaten für den Zieldokumenttyp zu erhalten
  5. Extraktion der Endpunkt-URL und des Empfängerzertifikats
  6. Zustellung der signierten AS4-Nachricht an diesen Endpunkt

Schritt 1: Aufbau der DNS-Abfrage

Die Peppol-Teilnehmerkennung hat zwei Teile: einen Schemacode und einen Wert. Für ein belgisches Unternehmen, identifiziert durch seine Unternehmensnummer:

Scheme: 0208
Value:  0468863455
Full:   iso6523-actorid-upis::0208:0468863455

Um dies in einen DNS-Hostnamen umzuwandeln:

  1. Die vollständige Teilnehmerkennung in Kleinbuchstaben umwandeln
  2. Den MD5-Hash berechnen
  3. Den Hash in Base32 kodieren (ohne Padding, Kleinbuchstaben)
  4. b- voranstellen (das Peppol-SML-Präfix)
  5. Die SML-Domain anhängen: 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";
}

Base32-Kodierung ist RFC 4648. Die .NET-Standardbibliothek enthält kein Base32; verwenden Sie ein kleines Hilfsprogramm oder das SimpleBase-NuGet-Paket.

Schritt 2: Die SML-DNS-Abfrage

Den Hostnamen als CNAME abfragen. Die Antwort gibt den SMP-Hostnamen zurück.

static async Task<string> LookupSmpHostname(string smlHostname)
{
    var result = await Dns.GetHostEntryAsync(smlHostname);
    // The CNAME target is the SMP hostname
    return result.HostName;
}

Wenn die DNS-Abfrage fehlschlägt (NXDOMAIN), ist der Teilnehmer nicht im Peppol-Netzwerk registriert. Dies ist eine definitive “kein solcher Teilnehmer”-Antwort, kein vorübergehender Fehler. Protokollieren und dem Benutzer anzeigen, anstatt erneut zu versuchen.

Schritt 3: SMP abfragen

Die SMP-Endpunkt-URL wird aus dem SMP-Hostnamen, dem Teilnehmerschema und dem Teilnehmerwert konstruiert. Die Peppol-SMP-Spezifikation (Version 2.0) definiert die URL-Struktur:

https://{smp-hostname}/{scheme}%3A%3A{value}/services/{doctype}

Der :: Trenner zwischen Schema und Wert ist prozent-kodiert. Die Dokumenttypenkennung ist ebenfalls prozent-kodiert.

Für eine Peppol BIS Billing 3.0-Rechnung:

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

Vollständiges Beispiel-Request:

GET https://{smp-hostname}/iso6523-actorid-upis%3A%3A0208%3A0468863455/services/urn%3Aoasis%3Anames...

Der SMP gibt ein signiertes XML-Dokument zurück (die Dienstmetadaten). Hier ist, wie die Antwort aussieht, auf die relevanten Teile reduziert:

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

Schritt 4: Verifizierung der SMP-Signatur

Die SMP-Antwort ist mit dem Zertifikat des Access Points signiert. Diese Signatur muss verifiziert werden, bevor der Endpunkt-URL vertraut werden kann.

Hier stoßen die meisten Implementierungen auf Probleme. SMP-Antworten verwenden XML-Digitalsignaturen (XMLDSig). Viele SMP-Server re-serialisieren das signierte Dokument bei der Auslieferung, was die Namespace-Präfix-Deklarationen ändert. Das bricht den Referenz-Digest in der Signatur.

Das Problem und seine Lösung werden ausführlich in XML-Signatur-Validierungsfallen in Peppol beschrieben. Kurzversion: Einen XML-Parser mit PreserveWhitespace = true verwenden und das Dokument nicht vor der Verifizierung re-serialisieren.

Nach der Verifizierung die Endpunkt-URL und das Zertifikat extrahieren:

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 ?? ""));

Schritt 5: Zustellung

Mit der Endpunkt-URL und dem Zertifikat in der Hand wird die Rechnung in eine AS4-Nachricht verpackt und über HTTPS zugestellt. AS4 ist das Peppol-Transportprotokoll. Es erfordert:

  • Signierung der AS4-Nachricht mit dem Zertifikat Ihres Access Points
  • Verschlüsselung der Nutzlast mit dem Zertifikat des Empfängers (aus der SMP-Antwort)
  • Senden an den EndpointURI aus dem SMP

Die AS4-Implementierung liegt außerhalb des Rahmens dieses Artikels. In der Praxis ist die Erstellung einer eigenen AS4-Schicht ein erheblicher Entwicklungsaufwand. Die meisten Organisationen verwenden einen zertifizierten Access-Point-Anbieter anstatt AS4 direkt zu implementieren.

Caching

SMP-Lookups sollten gecacht werden. Der DNS-TTL des SML-Eintrags beträgt typischerweise 3600 Sekunden. Die SMP-Dienstmetadaten ändern sich nicht häufig. Ein 24-Stunden-Cache für SMP-Antworten ist für die meisten Produktionssysteme angemessen.

Negative Ergebnisse (NXDOMAIN) nicht unbegrenzt cachen. Ein Teilnehmer kann sich nach Ihrer ersten Abfrage registrieren. Negative Ergebnisse 15 bis 30 Minuten cachen, nicht tagelang.

Was schiefgehen kann

NXDOMAIN vom SML: Der Teilnehmer ist nicht registriert. Das ist dauerhaft, nicht vorübergehend. Nicht ohne Untersuchung erneut versuchen.

SMP gibt 404 zurück: Der Teilnehmer ist im SML registriert, hat aber keine Dienstmetadaten für den angeforderten Dokumenttyp. Der Access Point des Empfängers hat möglicherweise keine Unterstützung für Peppol BIS Billing 3.0 konfiguriert.

Zertifikatsvalidierungsfehler: Die SMP-Antwortsignatur verwendet ein Zertifikat, das nicht in der Peppol-PKI-Vertrauensliste steht. Dies sollte als Sicherheitsfehler behandelt werden, nicht als Verbindungsfehler. Die Antwort ablehnen.

Namespace-bezogener Signaturfehler: Siehe XML-Signatur-Validierungsfallen in Peppol.

Endpunkt gibt AS4-SOAP-Fehler zurück: Die Rechnung wurde zugestellt, aber vom Access Point des Empfängers abgelehnt. Der Fehlercode gibt an, ob die Ablehnung auf Zertifikatsabweichung, nicht unterstützten Dokumenttyp oder Nutzlastvalidierungsfehler zurückzuführen ist.

SealDoc und SMP-Discovery

SealDocs REST API führt die vollständige SMP-Discovery-Kette intern durch. Wenn Sie eine Rechnungsgenerierungsanfrage mit einer Peppol-Teilnehmerkennung übermitteln, löst die API den Endpunkt auf, validiert die Kette und leitet das Dokument weiter. Wenn die Discovery fehlschlägt, gibt die API einen strukturierten Fehler zurück, der angibt, welcher Schritt fehlgeschlagen ist. Sie müssen keine SML- oder SMP-Lookup-Logik selbst implementieren.

Für Teilnehmer, die Abfragen gegen das Peppol-Netzwerk zu Test- oder Prüfzwecken durchführen müssen, kann der öffentliche SealDoc-Validator prüfen, ob eine Peppol-Rechnung an einen bestimmten Teilnehmer zustellbar ist, bevor Sie sich zur Zustellung verpflichten.


← Back to all articles