Zurück zum Blog SMS-Konnektivität und Betrieb

A2P-SMS-Nachrichtenkennungen: Referenzen normalisieren, ohne die Nachverfolgbarkeit zu verlieren

Entwerfen Sie ein Kennungsmodell, das Geschäftsereignis, technischen Versandversuch und externe Referenzen aus HTTP, SMPP, Anbietern und DLR trennt. Vermeiden Sie Überschreibungen, Kollisionen und falsche Zuordnungen bei Routenwechseln oder verspäteten Statusmeldungen.

Diagramm zur Nachverfolgbarkeit zwischen Geschäftsereignis, technischen Versandversuchen, Anbieterkennungen und SMS-DLR

Das Problem: Eine SMS kann mehrere Referenzen ansammeln

Ein einzelner logischer Versand kann während seines operativen Wegs mehrere Kennungen erzeugen. Die sendende Anwendung kann eine eigene Referenz erstellen; eine HTTP-API kann eine Ressourcen-ID zurückgeben; ein SMSC oder MC kann in submit_sm_resp eine message_id zurückgeben; der Anbieter kann in einem DLR eine andere Referenz senden; und das empfangende Callback-System kann eine eigene Ereignis-ID vergeben.

Diese Referenzen sind nicht austauschbar. Eine von einem Anbieter zurückgegebene Kennung gehört in der Regel zum Kontext dieser Plattform, dieses Kontos, dieser Integration und dieser Umgebung. Sie darf weder als globale Primärschlüssel-ID des Geschäftsbereichs behandelt noch als eindeutig über Anbieter, Routen, Konten oder Umgebungen hinweg angenommen werden.

Das Risiko entsteht, wenn ein System eine ID mit einer anderen überschreibt, externe Werte irreversibel umwandelt oder Ereignisse nur anhand einer Textübereinstimmung verknüpft. Dies kann dazu führen, dass ein alter DLR einem erneuten Versand zugeordnet wird, Status von zwei Anbietern vermischt werden oder die für die Untersuchung eines Vorfalls nötigen Belege verloren gehen.

  • Die ID des Geschäftsereignisses identifiziert die Absicht, beispielsweise eine OTP-Anfrage oder eine autorisierte Transaktionsbenachrichtigung.
  • Die ID des technischen Versandversuchs identifiziert eine konkrete Sendeausführung an ein bestimmtes Konto, einen Anbieter und eine Route.
  • Die externe ID identifiziert die Ressource oder Nachricht innerhalb des Systems, das sie ausgegeben hat.
  • Die ID des Callback-Ereignisses identifiziert die eingegangene Benachrichtigung und nicht zwingend die SMS, auf die sie sich bezieht.
Das Problem: Eine SMS kann mehrere Referenzen ansammeln

Welche Kennungen in HTTP, SMPP und DLR vorkommen können

Das genaue Inventar hängt vom Vertrag jeder Integration ab, doch es empfiehlt sich, stabile Kategorien zu modellieren. Ziel ist nicht, eine universelle Nomenklatur zu erzwingen, sondern festzuhalten, was jede Referenz darstellt, wer sie ausgegeben hat und in welchem Kontext sie verwendet werden kann.

In SMPP gibt submit_sm_resp eine message_id zurück, die vom MC oder SMSC vergeben wird. Die Spezifikation ordnet sie dem System zu, das das submit akzeptiert, und erlaubt ihre Verwendung in nachfolgenden Vorgängen wie Abfrage, Ersetzung oder Zuordnung zu einem Empfangsbericht. Sie sollte daher als externe Referenz des Versandversuchs und nicht als globale Nachrichtenkennung gespeichert werden.

Ein SMPP-Empfangsbericht kann über deliver_sm oder data_sm eintreffen. Wenn vorhanden, enthält das TLV receipted_message_id die Referenz der ursprünglich vom MC zurückgegebenen Nachricht. Empfangsberichtdaten können auch in anderen Feldern oder integrationsspezifischen Formaten enthalten sein. Speichern Sie zusätzlich zur normalisierten Extraktion die PDU oder ihre Rohdarstellung.

In HTTP kann eine Erstellungs- oder Annahmeantwort eine Nachrichten- oder Ressourcenkennung zurückgeben. Ihre synchrone Annahme beweist keine Zustellung an das Endgerät. Spätere Änderungen können per Callback, Ressourcenabfrage oder Zustellbericht eintreffen, jeweils mit eigener Ereignisreferenz und eigenen Zeitstempeln.

  • internal_event_id: Unveränderliche ID des logischen Geschäftsereignisses.
  • send_attempt_id: Unveränderliche ID jedes technischen Versandversuchs.
  • client_reference: Optionale Referenz des Kunden oder Ursprungssystems.
  • external_message_id: Vom Anbieter, MC, SMSC oder einer API zurückgegebene ID.
  • dlr_reference: Im Zustellbericht übertragene Referenz, etwa receipted_message_id, sofern zutreffend.
  • callback_event_id: ID der per Webhook oder Ereignisinfrastruktur eingegangenen Benachrichtigung.
  • provider_account_scope: Konto, Tenant, Integration, Umgebung und Anbieter, die die Bedeutung einer Referenz begrenzen.
Welche Kennungen in HTTP, SMPP und DLR vorkommen können

Designprinzip: Unveränderliche interne IDs und versionierte externe Referenzen

Die Grundlage des Designs ist einfach: Erzeugen Sie interne Kennungen, die Ihre Organisation kontrolliert und nicht wiederverwendet. Behandeln Sie anschließend jede externe Referenz als einem Ursprung und einem Beobachtungszeitpunkt zugeordneten Beleg.

Die Trennung zwischen dem logischen Ereignis und dem technischen Versandversuch ist entscheidend. Ein Geschäftsereignis kann einen ersten Versuch, einen kontrollierten Wiederholungsversuch oder ein Failover auf eine andere Route auslösen. Jeder Versuch benötigt seine eigene send_attempt_id, auch wenn alle von derselben internal_event_id abhängen. Dadurch wird verhindert, dass eine erneute Aussendung als Aktualisierung des vorherigen Versands interpretiert wird.

Auch externe Referenzen dürfen nicht überschrieben werden. Derselbe Versuch kann eine Annahmereferenz, eine weitere Referenz in einem DLR und eine zusätzliche Referenz bei einer späteren Abfrage erhalten. Speichern Sie jede als eigene Zeile oder eigenes Ereignis mit Typ, Originalwert, Vergleichswert und Betriebszusammenhang.

Die betriebliche Interpretation kann sich jedoch weiterentwickeln. Ein abgeleiteter Status kann beispielsweise von ausstehend zu zugestellt oder nicht zugestellt wechseln, wenn neue Belege eintreffen. Das empfangene Ereignis und die Belege, die diese Interpretation ausgelöst haben, müssen jedoch unverändert bleiben.

  • Verwenden Sie UUIDs oder ein anderes stabiles internes Schema für internal_event_id und send_attempt_id.
  • Verwenden Sie keine message_id eines Anbieters als Primärschlüssel der Geschäftsdomäne.
  • Pflegen Sie eine Eins-zu-viele-Beziehung zwischen technischem Versandversuch und externen Referenzen.
  • Pflegen Sie eine Eins-zu-viele-Beziehung zwischen technischem Versandversuch und Statusbeobachtungen.
  • Speichern Sie die Integrationsversion, die jede Antwort oder jeden Callback verarbeitet hat.
  • Unterscheiden Sie zwischen beobachtetem Status und abgeleitetem Status, den Ihr Betrieb verwendet.

Praktische Normalisierung ohne Zerstörung des empfangenen Werts

Normalisierung bedeutet nicht, den Originalwert zu ersetzen. Die sichere Regel lautet: Speichern Sie immer die exakt empfangene Darstellung und erstellen Sie separat eine Vergleichsdarstellung. Diese zweite Darstellung dient ausschließlich Suchvorgängen und dokumentierten Verknüpfungsregeln.

Für den Vergleich müssen möglicherweise Kodierung, Länge, Leerzeichen, Groß- und Kleinschreibung, Präfixe oder Kürzungen geprüft werden. Wenden Sie keine universellen Umwandlungen an: Eine Änderung der Groß- und Kleinschreibung kann bei einer Integration unbedenklich und bei einer anderen zerstörerisch sein; das Kürzen einer Zeichenfolge kann eine Kollision erzeugen; die Umwandlung von Bytes in Text ohne Kenntnis der Kodierung kann die Kennung verändern.

Jede Normalisierung muss reproduzierbar sein. Speichern Sie den Namen der Regel, ihre Version und das Ergebnis. Wenn die Integration das Format einer Referenz ändert, können Sie die Originalwerte erneut prüfen, ohne Belege zu verlieren.

  • external_value_raw: Exakt empfangener Wert, unverändert gespeichert.
  • external_value_compare: Abgeleiteter Vergleichswert nach einer expliziten Regel.
  • normalization_rule_version: Version der angewendeten Regel.
  • external_id_type: Beispielsweise submit_sm_resp_message_id, receipted_message_id oder http_message_id.
  • observed_at: Zeitpunkt, zu dem das System den Wert empfangen oder beobachtet hat.
  • source_payload_id: Verknüpfung mit dem kontrolliert gespeicherten Roh-Payload, der PDU oder dem Rohereignis.
  • Entfernen Sie Leerzeichen, Nullen, Präfixe oder nicht alphanumerische Zeichen nicht ohne eine anbieterspezifische Regel.

Minimales Datenmodell zur Untersuchung ohne Überschreiben von Belegen

Ein minimales relationales Modell kann die meisten Untersuchungen abdecken, wenn es die Trennung zwischen Absicht, Ausführung, Referenzen und Beobachtungen bewahrt. Es muss nicht erzwingen, dass alle Anbieter dieselben Felder zurückgeben; es muss explizit erfassen, was empfangen wurde und unter welchem Geltungsbereich.

Die Tabelle der Geschäftsereignisse repräsentiert die autorisierte funktionale Anfrage. Die Tabelle der Versandversuche repräsentiert jede technische Aussendung. Externe Referenzen und Statusereignisse werden dem Versuch zugeordnet, nicht direkt dem logischen Ereignis, außer wenn der Vertrag des Anbieters diese Beziehung nachweisbar erlaubt.

Um die Offenlegung zu minimieren, muss das Ziel als sensibles Datum behandelt werden. Speichern Sie es, wenn es für Untersuchungen und zusammengesetzte Schlüssel erforderlich ist, in einer konsistenten internationalen Form, mit Zugriffskontrollen, angemessener Aufbewahrung sowie gegebenenfalls Tokenisierung oder gleichwertigem Schutz. Es ist nicht erforderlich, den vollständigen Nachrichteninhalt zu speichern, um alle Vorfälle zu lösen; ein sicherer Hash des Payloads oder einer kanonischen Darstellung kann helfen, Versuche zu unterscheiden, ohne die Datenexposition unnötig zu erhöhen.

  • business_event: internal_event_id, tenant_id, Ereignistyp, idempotency_key, created_at.
  • send_attempt: send_attempt_id, internal_event_id, provider_id, provider_account_id, route_id, environment, integration_version, submitted_at.
  • external_reference: reference_id, send_attempt_id, external_id_type, raw_value, compare_value, normalization_rule_version, observed_at.
  • status_observation: observation_id, send_attempt_id, callback_event_id, raw_status, normalized_status, provider_timestamp, received_at, payload_reference.
  • investigation_context: Geschütztes oder tokenisiertes Ziel, sicherer Hash des Payloads, Versandursprung und erforderliche Auditdaten.

Wenn der Anbieter eine Referenz wiederverwendet, verändert oder keine korrelierbare Referenz zurückgibt

Nicht alle Anbieter bewahren eine vom Kunden gesendete Referenz, geben eine stabile ID zurück oder enthalten dieselbe ID in DLRs. Das Modell muss diese Einschränkung zulassen, ohne eine Beziehung zu erfinden, die nicht nachgewiesen werden kann.

Wenn ein Anbieter Kennungen wiederverwendet, kann die Referenz nur innerhalb eines zusammengesetzten Schlüssels eindeutig sein. Berücksichtigen Sie mindestens Tenant, Anbieter, Anbieterkonto, Umgebung, Referenztyp und ein zeitliches Beobachtungsintervall. Ergänzen Sie Route und Integration, wenn sie die operative Bedeutung des Werts verändern können.

Wenn der Anbieter die Kennung umwandelt, speichern Sie beide Werte und die bekannte Umwandlungsregel. Besteht keine vertragliche oder technisch überprüfbare Regel, erstellen Sie keine automatische Zuordnung aufgrund teilweiser Ähnlichkeit. Kennzeichnen Sie den Fall als mehrdeutig und leiten Sie ihn zur Abstimmung oder Untersuchung weiter.

Wenn keine korrelierbare Referenz vorhanden ist, kann die Nachverfolgbarkeit bis zum technischen Versandversuch und dem Annahmebeleg fortgesetzt werden, die Verbindung zu einem konkreten DLR bleibt jedoch unsicher. Diese Grenze muss im Dashboard und in den Betriebsverfahren sichtbar sein.

  • Deduplizieren Sie niemals global anhand einer isolierten external_message_id.
  • Verwenden Sie Übereinstimmungen anhand von Präfix, Suffix oder Kürzung nicht als Identitätsnachweis.
  • Fordern Sie für jede Suchregel einen zusammengesetzten Schlüssel mit operativem Geltungsbereich.
  • Klassifizieren Sie Verknüpfungen als bestätigt, wahrscheinlich oder nicht korrelierbar; reservieren Sie irreversible Automatisierungen für bestätigte Verknüpfungen.
  • Dokumentieren Sie, welche Referenzen jeder Anbieter zurückgibt und welche in seinen DLRs erscheinen können.

submit_sm_resp, DLR und asynchrone Status: Was verknüpft werden kann

In einem üblichen SMPP-Ablauf sendet das ESME submit_sm und erhält submit_sm_resp. Die message_id der Antwort identifiziert die Nachricht im MC oder SMSC, das geantwortet hat. Wenn über registered_delivery ein Empfangsbericht angefordert wurde und das System einen DLR ausgibt, kann der Bericht über esm_class als MC Delivery Receipt gekennzeichnet sein und die Kennung der empfangenen Nachricht im TLV receipted_message_id übertragen.

Diese Beziehung ermöglicht eine starke Korrelation, wenn die receipted_message_id mit der zuvor gespeicherten message_id übereinstimmt, innerhalb desselben Anbieters, Kontos, derselben Umgebung und Integration. Bewahren Sie dennoch den vollständigen DLR auf: Status, Zeitstempel und verfügbare Felder sind Teil der Belege und können bei Duplikaten oder Ereignissen außerhalb der Reihenfolge erforderlich sein.

In HTTP kann die beim Erstellen einer Ressource zurückgegebene Kennung dazu dienen, ihren späteren Status abzufragen oder Callbacks zu verknüpfen, abhängig vom Vertrag des Anbieters. Ein HTTP-Code für Erstellung oder Annahme zeigt an, dass die Plattform die Anfrage gemäß ihrer Semantik verarbeitet oder in die Warteschlange gestellt hat; er beweist für sich allein keine Zustellung an das Endgerät.

Callbacks können verspätet, mehrfach oder außerhalb der Reihenfolge eintreffen. Verwerfen Sie eine Beobachtung nicht automatisch, nur weil sie im Verhältnis zur Empfangszeit alt ist. Vergleichen Sie den Zeitstempel des Anbieters, den Empfangszeitstempel und die bekannte Reihenfolge; wenden Sie anschließend auditierbare Abschluss- und Abstimmungsregeln an.

  • Speichern Sie submit_sm, submit_sm_resp und DLR als getrennte Phasen.
  • Fordern Sie DLR über registered_delivery an, wenn der SMPP-Vertrag und der Anwendungsfall dies erfordern.
  • Machen Sie aus einem DLR keinen Nachweis menschlicher Lektüre oder allgemeiner Routenqualität.
  • Gehen Sie nicht davon aus, dass ein terminaler Status das spätere Eintreffen widersprüchlicher oder doppelter Belege verhindert.
  • Pflegen Sie eine dokumentierte Richtlinie dafür, welcher abgeleitete Status angezeigt wird, ohne vorherige Status zu löschen.

Routenwechsel, erneute Sendungen und Duplikate: Nach Kontext modellieren

Ein Failover, Wiederholungsversuch oder erneuter Versand kann demselben Geschäftsereignis entsprechen, ist jedoch nicht zwingend dieselbe technische Nachricht. Die praktische Regel lautet, für jede Aussendung an eine konkrete Kombination aus Tenant, Anbieter, Konto, Route, Umgebung und Integration eine neue send_attempt_id zu erstellen.

Fassen Sie DLRs verschiedener Routen nicht als Aktualisierungen desselben Versuchs zusammen. Ein Status einer vorherigen Route darf nicht einer neuen Route zugeordnet werden, nur weil Ziel, Inhalt oder eine externe Referenz ähnlich erscheinen. Die korrekte Beziehung bleibt über die internal_event_id erhalten, während die Belege jedes Anbieters mit ihrem eigenen Versuch verbunden bleiben.

Idempotenz muss vor dem Versand angewendet werden. Bei HTTP-Anfragen ist POST nicht per Definition idempotent; ein Wiederholungsversuch bei unsicherer Antwort kann eine Sendung duplizieren, wenn keine Idempotenzkennung der Anwendung oder keine zuverlässige Bestätigung vorliegt, dass der vorherige Vorgang nicht ausgeführt wurde. Verlassen Sie sich nicht auf eine externe ID, die möglicherweise noch nicht zurückgegeben wurde.

Auch eine absichtliche erneute Sendung muss als solche sichtbar sein. Erfassen Sie die Ursache: Annahme-Timeout, technischer Fehler, Failover-Richtlinie, manuelle Entscheidung oder ein anderer autorisierter Grund. Dadurch lässt sich eine versehentliche Duplizierung von einer zweiten kontrollierten Ausführung unterscheiden.

  • Empfohlener Kontextschlüssel: tenant_id, provider_id, provider_account_id, route_id, environment, external_id_type und external_value_compare.
  • Fügen Sie Zeitfenster nur als zusätzliche Einschränkung hinzu, nicht als alleinigen Identitätsnachweis.
  • Verwenden Sie idempotency_key pro Geschäftsereignis oder Geschäftsabsicht, bevor Sie den Anbieter aufrufen.
  • Speichern Sie retry_sequence, failover_reason und die Beziehung zwischen Ursprungsversuch und Folgeversuch.
  • Vermeiden Sie die Übermittlung unnötig sensibler Inhalte an Logs, Suchwerkzeuge oder URLs.
FAQ

Häufige Fragen

Kann die message_id aus submit_sm_resp als globale Nachrichten-ID verwendet werden?

Nein. Sie ist eine vom antwortenden MC oder SMSC vergebene Referenz und muss innerhalb ihres operativen Geltungsbereichs interpretiert werden. Speichern Sie sie zusammen mit Anbieter, Konto, Umgebung, Integration, Referenztyp und Beobachtungszeitpunkt.

Bestätigt ein HTTP 202 oder eine erfolgreiche API-Antwort die Zustellung der SMS?

Nicht zwingend. Eine Annahme oder Erstellung bestätigt die Verarbeitung der Anfrage gemäß der API, doch die Zustellung erfordert die Beobachtung eines späteren Statusberichts oder, sofern der Anbieter dies erlaubt, die Abfrage der Ressource.

Was soll ich tun, wenn ein DLR vor, nach oder doppelt zu anderen Ereignissen eintrifft?

Speichern Sie jede Beobachtung, ohne sie zu überschreiben. Erfassen Sie die Zeit des Anbieters und die Empfangszeit, wenden Sie eine versionierte Interpretationsregel an und bewahren Sie das Rohereignis für die Abstimmung auf.

Muss ich den SMS-Inhalt speichern, um Nachrichten zu korrelieren?

Das ist nicht in allen Fällen erforderlich. Priorisieren Sie Datenminimierung. Wenn Sie Versuche unterscheiden müssen, ziehen Sie einen sicheren Hash einer kontrollierten Payload-Darstellung in Betracht und schützen Sie Zieldaten sowie zugehörige Metadaten.

Beweist ein Status delivered den Empfang oder das Lesen durch eine Person?

Nein. Er stellt die Zustellbestätigung dar, die der Anbieter von seiner vorgelagerten Kette und, sofern verfügbar, vom Endgerät erhält. Er ist weder ein universeller Nachweis menschlicher Lektüre noch eine unabhängige Garantie für die Routenqualität.

Verwendete Quellen

  1. SMPP v3.4 specificationSMPP Developers Forum
  2. SMPP Delivery Receipt FormatSMPP Developers Forum
  3. SMPP protocol overviewSMPP Developers Forum
  4. Message resourceTwilio
  5. Outbound Message Status in Status CallbacksTwilio
  6. Best Practices for Messaging Delivery Status LoggingTwilio
  7. Operations and Message TrackingTwilio
  8. Delivery Reports - Get - REST APIMicrosoft Learn
  9. Azure Communication Services SMS eventsMicrosoft Learn
  10. SMS logsMicrosoft Learn
  11. ITU-T Recommendation E.164International Telecommunication Union
  12. RFC 9110: HTTP SemanticsIETF / RFC Editor