← Knowledge-Base · Code-Snippets

UID-Feld im WooCommerce-Checkout: Snippet, Prüfung und die Fehler, die es teuer machen

Aktualisiert 20.08.2026 · 9 Min Lesezeit

Ein UID-Feld im Checkout ist in zehn Zeilen gebaut. Der Grund, warum es trotzdem so oft nicht funktioniert: Die meisten Anleitungen speichern den Wert mit update_post_meta – und das greift bei modernen WooCommerce-Installationen ins Leere. Dazu kommt der teurere Denkfehler, aus einer Formatprüfung eine Steuerbefreiung abzuleiten.

Dieser Artikel zeigt den vollständigen Weg: Feld anlegen, Eingabe normalisieren, HPOS-sicher speichern, in Bestellung und E-Mail sichtbar machen. Und danach die Punkte, die der Code allein nicht löst.

Wofür du das Feld eigentlich brauchst

Die Umsatzsteuer ist nur einer von vier Gründen, und in der Praxis nicht der häufigste:

  • Rechnungsstellung. Bei Reverse-Charge-Rechnungen gehört die UID des Empfängers auf die Rechnung. Steht sie nicht in der Bestellung, tippt sie jemand händisch nach.
  • Buchhaltung und Schnittstellen. Wer Bestellungen an sevDesk, BMD oder einen Steuerberater übergibt, braucht die UID im Datensatz, nicht in einer Bemerkung.
  • Erkennbarkeit als B2B-Shop. Ein UID-Feld ist eines der Merkmale, an denen sich zeigt, dass ein Shop sich an Unternehmer richtet – und davon hängt ab, ob du dich auf den Ausschluss des Widerrufsrechts im B2B berufen kannst.
  • Steuerbefreiung bei innergemeinschaftlichen Lieferungen. Der bekannteste Grund – und der, bei dem das Snippet allein nicht reicht. Dazu unten mehr.

Erste Frage: Brauchst du überhaupt Code?

Wenn du Germanized Pro einsetzt, bringt es UID-Feld und Prüfung samt Steuerlogik bereits mit. Dasselbe gilt für die gängigen B2B-Erweiterungen. In dem Fall ist eigener Code die schlechtere Lösung: Du baust etwas nach, das gepflegt wird, und musst es bei jedem Update selbst nachziehen.

Eigener Code lohnt, wenn du das Feld nur zur Erfassung brauchst – für Rechnung, Buchhaltung und Nachweis –, die Steuerlogik aber ohnehin anders löst oder gar nicht brauchst, weil du im Inland verkaufst.

Schritt 1: Das Feld anlegen

add_filter('woocommerce_checkout_fields', function ($fields) {
    $fields['billing']['billing_uid'] = [
        'label'       => 'UID-Nummer',
        'placeholder' => 'z. B. ATU12345678',
        'required'    => false,
        'class'       => ['form-row-wide'],
        'clear'       => true,
        'priority'    => 35,
    ];
    return $fields;
});

priority steuert die Position: Der Firmenname liegt bei 30, das Land bei 40. Mit 35 steht die UID direkt unter der Firma, wo sie hingehört.

required lassen wir bewusst auf false. Warum, steht unten bei den häufigen Fehlern.

Schritt 2: Eingabe normalisieren und prüfen

Kunden tippen ATU 123 456 78, atu12345678 oder ATU-12345678. Alles dasselbe, aber nur eine Schreibweise ist für Rechnung und Schnittstelle brauchbar.

function shop_uid_normalisieren($roh) {
    // Alles ausser Buchstaben und Ziffern entfernen, dann Grossschreibung
    return strtoupper(preg_replace('/[^A-Za-z0-9]/', '', (string) $roh));
}

function shop_uid_plausibel($uid) {
    // Achtung: Das ist eine FORMATpruefung, keine Gueltigkeitspruefung.
    if (strlen($uid) < 8) {
        return false;
    }
    $land = substr($uid, 0, 2);
    if (!preg_match('/^[A-Z]{2}$/', $land)) {
        return false;
    }
    // Genauere Regeln fuer die beiden Hauptmaerkte
    if ($land === 'AT') {
        return (bool) preg_match('/^ATU[0-9]{8}$/', $uid);
    }
    if ($land === 'DE') {
        return (bool) preg_match('/^DE[0-9]{9}$/', $uid);
    }
    // Uebrige EU-Laender: nur grobe Plausibilitaet
    return (bool) preg_match('/^[A-Z]{2}[A-Z0-9]{6,12}$/', $uid);
}

Und die Prüfung im Checkout – sie greift nur, wenn überhaupt etwas eingegeben wurde:

add_action('woocommerce_after_checkout_validation', function ($daten, $fehler) {
    if (empty($daten['billing_uid'])) {
        return; // Feld ist optional
    }
    $uid = shop_uid_normalisieren($daten['billing_uid']);
    if (!shop_uid_plausibel($uid)) {
        $fehler->add(
            'billing_uid',
            'Die UID-Nummer sieht nicht wie eine gültige EU-UID aus. Beispiel: ATU12345678'
        );
    }
}, 10, 2);

Schritt 3: Speichern – und zwar HPOS-sicher

Das ist die Stelle, an der die meisten Anleitungen veraltet sind. Man liest fast überall:

// VERALTET - bitte nicht verwenden
update_post_meta($order_id, '_billing_uid', $uid);

Das funktionierte, solange Bestellungen als WordPress-Beiträge gespeichert wurden. Mit HPOS – dem eigenen Tabellenspeicher für Bestellungen, der bei neueren Installationen standardmäßig aktiv ist – sind Bestellungen keine Beiträge mehr. Der Aufruf läuft dann ins Leere: kein Fehler, keine Meldung, nur ein Feld, das leer bleibt.

Der Weg, der in beiden Welten funktioniert, geht über das Bestellobjekt. Die letzten drei Zeilen sind optional – sie hinterlegen die UID zusätzlich am Kundenkonto. Wichtig ist, dass das im selben Durchgang passiert und nicht in einem zweiten Hook: Der müsste die Bestellung erneut laden und sieht bei aktivem Objekt-Cache den eben gespeicherten Wert unter Umständen noch nicht.

add_action('woocommerce_checkout_update_order_meta', function ($order_id) {
    if (empty($_POST['billing_uid'])) {
        return;
    }
    $order = wc_get_order($order_id);
    if (!$order) {
        return;
    }
    $uid = shop_uid_normalisieren(wp_unslash($_POST['billing_uid']));

    $order->update_meta_data('_billing_uid', $uid);
    $order->save();

    // Gleicher Durchgang: am Kundenkonto hinterlegen
    $kunde = $order->get_customer_id();
    if ($kunde) {
        update_user_meta($kunde, 'billing_uid', $uid);
    }
});

Ob WooCommerce das Feld beim nächsten Kauf von selbst vorausfüllt, hängt vom Setup ab – probier es mit einem Testkonto aus, bevor du es deinen Kunden versprichst.

Schritt 4: Sichtbar machen

Ein gespeichertes Feld, das niemand sieht, ist so gut wie keins. Zwei Stellen fehlen fast immer.

In der Bestellübersicht im Backend:

add_action('woocommerce_admin_order_data_after_billing_address', function ($order) {
    $uid = $order->get_meta('_billing_uid');
    if ($uid) {
        echo '<p><strong>UID-Nummer:</strong> ' . esc_html($uid) . '</p>';
    }
});

In den Bestell-E-Mails:

add_filter('woocommerce_email_order_meta_fields', function ($felder, $an_admin, $order) {
    $uid = $order->get_meta('_billing_uid');
    if ($uid) {
        $felder['billing_uid'] = [
            'label' => 'UID-Nummer',
            'value' => $uid,
        ];
    }
    return $felder;
}, 10, 3);

Ob die UID in der Bestellbestätigung stehen soll, ist eine Entscheidung: Für den Kunden ist sie eine Bestätigung, dass die Angabe angekommen ist. Zur rechtlichen Einordnung dieser Mail siehe unsere Vorlagen für Shop-E-Mails.

Wohin der Code gehört – nicht in die functions.php

Fast jede Anleitung sagt „ab in die functions.php“. Das ist der schlechteste verfügbare Ort:

  • Beim nächsten Theme-Wechsel ist alles weg – und mit dem Code auch die Anzeige des Felds, während die Daten in alten Bestellungen liegenbleiben.
  • Ohne Child-Theme überschreibt schon das nächste Theme-Update die Datei.
  • Ein Syntaxfehler dort legt die komplette Seite lahm, inklusive Backend.

Leg stattdessen ein Mini-Plugin an. Neue Datei uid-feld.php im Ordner /wp-content/plugins/uid-feld/, oben dieser Kopf, darunter der Code von oben:

<?php
/**
 * Plugin Name: UID-Feld im Checkout
 * Description: Ergaenzt den WooCommerce-Checkout um ein UID-Feld inkl. Formatpruefung.
 * Version:     1.0.0
 * Author:      Dein Shop
 */

if (!defined('ABSPATH')) {
    exit; // Direktaufruf verhindern
}

// ... hier der Code aus den Schritten 1 bis 4

Danach unter Plugins aktivieren. Der Code überlebt jeden Theme-Wechsel, lässt sich mit einem Klick abschalten, wenn etwas klemmt, und du siehst auf einen Blick, dass er überhaupt existiert.

Die Alternative ist ein Code-Snippets-Plugin. Auch gut – nur solltest du dich für einen der beiden Wege entscheiden und nicht Schnipsel an drei Orten verteilen.

Wenn du das Präfix shop_uid_ änderst, änder es überall. Zwei Funktionen gleichen Namens sind ein sofortiger Fatal Error.

Was dieses Snippet nicht tut

Der wichtigste Abschnitt, weil hier das Geld liegt.

Es prüft nicht, ob die UID gültig ist

ATU99999999 hat ein einwandfreies Format und existiert trotzdem nicht. Die Formatprüfung fängt Tippfehler ab, mehr nicht.

Eine echte Prüfung läuft gegen das MIAS/VIES-System der EU-Kommission, das die nationalen Register abfragt. Wer die Steuerbefreiung darauf stützt, braucht außerdem einen Nachweis, den er aufbewahren kann – in Deutschland die qualifizierte Bestätigungsabfrage beim Bundeszentralamt für Steuern, in Österreich die Stufe-2-Abfrage über FinanzOnline. Beide bestätigen zusätzlich Name und Anschrift und liefern ein Protokoll.

Es macht keine Steuerbefreiung

Ein ausgefülltes UID-Feld ändert an der Steuerberechnung in WooCommerce nichts. Reverse Charge setzt mehrere Dinge gleichzeitig voraus: Der Kunde sitzt in einem anderen EU-Mitgliedstaat, seine UID ist zum Zeitpunkt der Lieferung gültig, und du kannst das nachweisen.

Wer allein aufgrund einer ausgefüllten Textbox keine Umsatzsteuer berechnet, trägt das Risiko selbst. Stellt sich die UID später als ungültig heraus, schuldest du die Steuer – und holst sie beim Kunden erfahrungsgemäß nicht mehr rein.

Es greift nicht im Block-Checkout

Der Filter woocommerce_checkout_fields gehört zum klassischen Checkout über den Shortcode. Setzt dein Shop den block-basierten Checkout ein, wird das Feld dort nicht erscheinen – ohne Fehlermeldung, es passiert schlicht nichts.

Wenn du unsicher bist, welchen du hast: Schau in der Checkout-Seite im Editor nach. Steht dort ein einzelner Block „Checkout“, ist es der neue. Steht dort [woocommerce_checkout], ist es der klassische, und der Code oben passt.

Häufige Fehler

  • Das Feld als Pflichtfeld für alle. Verkaufst du auch an Verbraucher, sperrst du sie damit aus – oder erziehst sie dazu, Fantasienummern einzutippen, was schlimmer ist als ein leeres Feld. Wenn Pflicht, dann abhängig davon, ob ein Firmenname eingetragen wurde.
  • Speichern mit update_post_meta. Der Klassiker aus alten Anleitungen. Mit HPOS bleibt das Feld leer, ohne dass irgendwo ein Fehler auftaucht.
  • Feld im Checkout, aber nicht in Rechnung und Export. Die UID liegt dann in der Bestellung und kommt trotzdem nicht dort an, wo sie gebraucht wird. Prüf dein Rechnungs-Plugin und deine Buchhaltungsschnittstelle einzeln.
  • Eingabe ungeprüft übernehmen. Ohne Normalisierung liegen in der Datenbank fünf Schreibweisen derselben Nummer, und keine Schnittstelle kommt damit klar.
  • Eine VIES-Abfrage den Checkout blockieren lassen. Der Dienst hat Ausfälle, einzelne Länder sind zeitweise nicht erreichbar. Wer bei Zeitüberschreitung die Bestellung abbricht, verliert Umsatz wegen eines fremden Servers. Besser: Bestellung annehmen, Prüfung vermerken, im Zweifel Steuer berechnen und nachträglich klären.
  • Die eigene UID vergessen. Reverse Charge greift nur zwischen verschiedenen Mitgliedstaaten. Ein österreichischer Kunde mit österreichischer UID bekommt eine ganz normale Rechnung mit Umsatzsteuer.

Was du nach dem Einbau testen solltest

  1. Testbestellung mit ausgefülltem Feld: Steht die UID in der Bestellung im Backend?
  2. Dieselbe Bestellung: Steht sie in der Bestell-E-Mail und auf der Rechnung?
  3. Testbestellung mit leerem Feld: Läuft sie durch, ohne dass eine Fehlermeldung erscheint?
  4. Testbestellung mit Unsinn im Feld: Kommt die Fehlermeldung – und bleibt der Rest des Formulars ausgefüllt?
  5. Eingabe mit Leerzeichen (ATU 123 456 78): Steht sie danach normalisiert in der Bestellung?
  6. Falls du eine Buchhaltungsschnittstelle nutzt: Kommt das Feld dort an?

Passt dein Shop insgesamt zu B2B?

Das UID-Feld ist ein Baustein von mehreren. Ob dein Shop nach außen eindeutig als B2B- oder B2C-Shop auftritt, zeigt der kostenlose B2B-Shop-Check: Er ruft deine Startseite auf, sucht AGB, Impressum und Widerrufsseite und benennt Widersprüche. Kein Konto, keine E-Mail-Adresse.

B2B-Shop-Check starten →

Weiterlesen

Der Code ist für den klassischen WooCommerce-Checkout geschrieben. Test ihn auf einer Staging-Umgebung, bevor er in den Live-Shop geht. Steuerliche Aussagen in diesem Artikel sind eine Einordnung aus der Shop-Praxis und ersetzen keine Steuerberatung – ob und wann du Reverse Charge anwenden darfst, klärst du mit deinem Steuerberater. Stand: August 2026.

Hat dir dieser Artikel weitergeholfen?

Dann weißt du jetzt, wie wir arbeiten: ehrlich, direkt und ohne Abkürzungen. Wenn dich das überzeugt, freuen wir uns riesig über eine kurze Google-Bewertung. Das dauert keine Minute und hilft uns enorm.

Jetzt auf Google bewerten

Ehrlich verdient statt manipuliert - so muss das.

War diese Anleitung hilfreich?

Fehlt dir etwas oder können wir den Artikel verbessern? Sag es uns.