Kreditkarten-Eingabemaske mit Alpine.js richtig bauen
AI generated
x-data
Alpine
Alpine.js · Zahlungsdaten · Formulare · Validierung
Kreditkarten-Eingabemaske richtig bauen
Formatierung, Kartentyp und Luhn-Prüfsumme im Zusammenspiel

Eine Kreditkarten-Eingabemaske ist mehr als das Einfügen von Leerzeichen alle vier Ziffern. Kartentyp-Erkennung, unterschiedliche Gruppierungslängen bei American Express, die Luhn-Prüfsumme und ein Cursor, der beim Tippen nicht ständig zurückspringt, machen aus einer simplen Formatierung ein kleines, aber anspruchsvolles Alpine.js Projekt.

16 Min. Lesezeit x-mask · Luhn-Algorithmus · Kartentyp-Erkennung · Cursor-Position Alpine.js 3.x

1. Warum eine Kreditkarten-Eingabemaske mehr als Formatierung ist

Eine unformatierte Zahlenfolge aus sechzehn Ziffern ist für Menschen schwer zu lesen und noch schwerer auf Tippfehler zu prüfen. Eine gute Kreditkarten-Eingabemaske gruppiert die Ziffern visuell, erkennt den Kartentyp anhand der ersten Ziffern und gibt sofortiges Feedback, ob die eingegebene Nummer überhaupt strukturell gültig sein kann, lange bevor eine Zahlung tatsächlich autorisiert wird.

Der naive Ansatz, bei jedem Tastendruck ein Leerzeichen nach jeder vierten Ziffer einzufügen, funktioniert nur für Kartentypen mit einheitlicher Vierergruppierung. American Express nutzt jedoch ein 4-6-5-Muster, was bedeutet, dass eine Kreditkarten-Eingabemaske den erkannten Kartentyp kennen muss, bevor sie überhaupt entscheidet, wo Leerzeichen eingefügt werden.

Der dritte Baustein ist die Luhn-Prüfsumme, ein einfacher mathematischer Algorithmus, der die meisten Tippfehler bei Kreditkartennummern schon vor dem Absenden entdeckt. Zusammen ergeben Kartentyp-Erkennung, korrekte Gruppierung und Luhn-Prüfung eine Kreditkarten-Eingabemaske, die sich wie eine professionelle Zahlungslösung anfühlt, obwohl sie komplett clientseitig mit Alpine.js läuft.

2. Kartentyp live erkennen: Visa, Mastercard, American Express

Jeder Kartenanbieter nutzt ein festes Präfix-Muster für seine Kartennummern: Visa beginnt immer mit einer 4, Mastercard mit 51 bis 55 oder dem neueren Bereich 2221 bis 2720, American Express mit 34 oder 37. Diese Präfixe lassen sich mit einfachen regulären Ausdrücken abgleichen, sobald die ersten ein bis vier Ziffern eingegeben wurden.

Die Kreditkarten-Eingabemaske sollte den erkannten Typ nicht nur intern speichern, sondern auch visuell zurückmelden, etwa durch ein kleines Logo-Icon, das während der Eingabe erscheint. Das gibt dem Nutzer sofortiges Vertrauen, dass die Eingabe korrekt interpretiert wird, und erlaubt es der Maske, ab diesem Zeitpunkt die richtige Gruppierungsregel anzuwenden.


// Card type detection based on IIN (Issuer Identification Number) prefixes
function creditCardField() {
  return {
    rawNumber: '',
    cardType: null,

    detectCardType(digits) {
      if (/^4/.test(digits)) return 'visa';
      if (/^5[1-5]/.test(digits) || /^2(22[1-9]|2[3-9]|[3-6]|7[0-1]|720)/.test(digits)) return 'mastercard';
      if (/^3[47]/.test(digits)) return 'amex';
      return null;
    },

    onInput(event) {
      const digits = event.target.value.replace(/\D/g, '');
      this.rawNumber = digits;
      this.cardType = this.detectCardType(digits);
    },
  };
}

3. Ziffern in Vierergruppen formatieren, mit Sonderfall Amex

Sobald der Kartentyp bekannt ist, entscheidet die Kreditkarten-Eingabemaske über das passende Gruppierungsmuster. Visa und Mastercard folgen dem einfachen 4-4-4-4-Muster für sechzehn Ziffern. American Express hingegen nutzt fünfzehn Ziffern in einem 4-6-5-Muster, was bedeutet, dass ein generischer Vierergruppen-Formatter für Amex-Karten falsch formatierte und damit verwirrende Ausgaben produzieren würde.

Die Formatierungsfunktion sollte deshalb ein Array mit Gruppengrößen entgegennehmen, das je nach erkanntem Kartentyp unterschiedlich aussieht. Diese Trennung von Rohdaten und Anzeigeformat ist wichtig: der interne Zustand speichert immer nur die reinen Ziffern, während die Formatierung erst beim Rendern angewendet wird.


function creditCardField() {
  return {
    rawNumber: '',
    cardType: null,

    // Group sizes differ per card type: Amex uses 4-6-5, others use 4-4-4-4
    groupSizes: {
      visa: [4, 4, 4, 4],
      mastercard: [4, 4, 4, 4],
      amex: [4, 6, 5],
      default: [4, 4, 4, 4],
    },

    get formatted() {
      const sizes = this.groupSizes[this.cardType] ?? this.groupSizes.default;
      const groups = [];
      let position = 0;
      for (const size of sizes) {
        const chunk = this.rawNumber.slice(position, position + size);
        if (!chunk) break;
        groups.push(chunk);
        position += size;
      }
      return groups.join(' ');
    },
  };
}

4. Cursor-Position beim Formatieren nicht verlieren

Sobald Leerzeichen programmatisch in ein Textfeld eingefügt werden, springt der Cursor bei den meisten naiven Implementierungen ans Ende des Felds zurück. Der Nutzer tippt dann mitten in der Kartennummer, sieht aber, wie der Cursor nach jeder Eingabe ans Ende der Kreditkarten-Eingabemaske hüpft, was das Korrigieren einzelner Ziffern praktisch unmöglich macht.

Die Lösung ist, die Cursor-Position vor der Neuformatierung zu merken, die Anzahl der neu eingefügten Leerzeichen bis zur ursprünglichen Position zu zählen, und den Cursor anschließend an die korrigierte Position zu setzen. Das erfordert einen direkten Zugriff auf selectionStart und setSelectionRange() des Input-Elements, was in Alpine über eine Methode auf dem $refs-Objekt erfolgt.


function creditCardField() {
  return {
    rawNumber: '',

    onInput(event) {
      const input = event.target;
      const previousLength = input.value.length;
      const cursorPosition = input.selectionStart;

      this.rawNumber = input.value.replace(/\D/g, '').slice(0, 16);
      const newValue = this.formatted;

      this.$nextTick(() => {
        input.value = newValue;
        // Adjust cursor for inserted spaces before the original position
        const lengthDiff = newValue.length - previousLength;
        const newPosition = Math.max(0, cursorPosition + lengthDiff);
        input.setSelectionRange(newPosition, newPosition);
      });
    },
  };
}

5. Der Luhn-Algorithmus: Prüfsumme ohne Server-Anfrage

Der Luhn-Algorithmus ist eine einfache Prüfsummenformel, die praktisch alle gängigen Kreditkartennummern erfüllen. Er verdoppelt jede zweite Ziffer von rechts, zieht neun ab, wenn das Ergebnis über neun liegt, summiert alle Ziffern und prüft, ob die Summe durch zehn teilbar ist. Diese Prüfung entdeckt zuverlässig einzelne Zifferndreher und die meisten Vertauschungen benachbarter Ziffern, ohne dass eine Netzwerk-Anfrage nötig wäre.

Wichtig ist, dass eine gültige Luhn-Prüfsumme nur bedeutet, dass die Nummer strukturell plausibel ist, nicht dass die Karte tatsächlich existiert oder gedeckt ist. Die Kreditkarten-Eingabemaske nutzt Luhn ausschließlich, um offensichtliche Tippfehler früh abzufangen, während die eigentliche Autorisierung immer beim Zahlungsdienstleister stattfindet.


function creditCardField() {
  return {
    rawNumber: '',

    // Luhn checksum: catches typos before any network request
    isLuhnValid() {
      const digits = this.rawNumber.split('').map(Number).reverse();
      let sum = 0;
      digits.forEach((digit, index) => {
        if (index % 2 === 1) {
          digit *= 2;
          if (digit > 9) digit -= 9;
        }
        sum += digit;
      });
      return this.rawNumber.length >= 13 && sum % 10 === 0;
    },
  };
}

6. Ablaufdatum und Prüfziffer mit passenden Regeln

Neben der Kartennummer gehört zu jeder Kreditkarten-Eingabemaske auch das Ablaufdatum im Format MM/JJ und der CVC-Code auf der Rückseite der Karte. Das Ablaufdatum sollte automatisch einen Schrägstrich nach den ersten zwei Ziffern einfügen und gleichzeitig prüfen, ob der Monat zwischen 01 und 12 liegt und das Datum in der Zukunft liegt, nicht bereits abgelaufen ist.

Die Länge des CVC-Codes hängt ebenfalls vom Kartentyp ab: American Express nutzt vier Ziffern, alle anderen gängigen Anbieter drei. Die Kreditkarten-Eingabemaske sollte deshalb die maximale Eingabelänge des CVC-Feldes dynamisch an den zuvor erkannten Kartentyp anpassen, statt eine feste Länge für alle Karten vorzugeben.

7. Barrierefreie Fehlermeldungen und Autofill-Kompatibilität

Browser-Autofill füllt Kreditkartenfelder oft ohne Leerzeichen oder mit abweichender Formatierung aus. Eine robuste Kreditkarten-Eingabemaske muss deshalb auch beim @input-Ereignis nach einem Autofill dieselbe Bereinigung und Neuformatierung durchlaufen wie bei manueller Eingabe, sonst zeigt das Feld nach dem Autofill eine inkonsistente Darstellung.

Für Screenreader-Nutzer sollte das Kartennummernfeld ein autocomplete="cc-number"-Attribut tragen, das Ablaufdatum autocomplete="cc-exp" und der CVC autocomplete="cc-csc". Diese Standard-Attribute ermöglichen nicht nur Passwort-Manager-Integration, sondern auch, dass assistive Technologien den Zweck jedes Feldes korrekt ankündigen. Ein ungültiges Luhn-Ergebnis sollte über aria-invalid und eine klare Textmeldung kommuniziert werden, nicht nur über eine rote Umrandung.

8. Sicherheitsgrenzen: was die Client-Maske nicht leisten darf

Eine Kreditkarten-Eingabemaske in Alpine.js darf niemals die einzige Sicherheitsgrenze einer Zahlung sein. PCI-DSS-Vorgaben verlangen, dass rohe Kartennummern in den meisten Konfigurationen niemals den eigenen Server erreichen, sondern direkt an einen zertifizierten Zahlungsdienstleister wie Stripe oder Adyen übermittelt werden, meist über ein eingebettetes iFrame-Formularfeld des Anbieters.

Die hier beschriebene Maske eignet sich deshalb primär für die Benutzerführung: Formatierung, Kartentyp-Anzeige und frühe Fehlererkennung. Sobald ein PCI-konformer Zahlungsanbieter im Spiel ist, übernimmt dessen eigenes, isoliertes Formularfeld die tatsächliche Eingabe der sensiblen Daten, während die Alpine-Komponente nur noch für die umgebende Formularlogik zuständig ist.

9. Eingabemasken-Ansätze im Vergleich

Die folgende Tabelle vergleicht typische Fallstricke beim Bau einer Kreditkarten-Eingabemaske mit dem empfohlenen Vorgehen.

Aspekt Fehleranfällig Empfohlene Eingabemaske Vorteil
Gruppierung feste 4-4-4-4 für alle Karten Gruppengröße je Kartentyp korrekt für Amex 4-6-5
Cursor springt nach jeder Eingabe ans Ende Position anhand Längendifferenz korrigieren Korrektur in der Mitte möglich
Plausibilität nur Längenprüfung Luhn-Prüfsumme entdeckt Tippfehler früh
CVC-Länge fest drei Ziffern für alle vier Ziffern für Amex, drei sonst korrekt für alle Kartentypen
Speicherung rohe Nummer an eigenen Server PCI-konformer Zahlungsanbieter keine PCI-DSS-Pflichten für euch

Eine sauber gebaute Kreditkarten-Eingabemaske verbessert die Benutzerführung erheblich, ersetzt aber niemals die eigentliche Sicherheitsarchitektur einer Zahlungsintegration. Beide Ebenen ergänzen sich, wenn sie klar voneinander getrennt bleiben.

Mironsoft

Alpine.js Zahlungsformulare und PCI-konforme Checkout-Integration

Zahlungsformular, das sich unprofessionell anfühlt?

Wir bauen euch eine Kreditkarten-Eingabemaske mit Kartentyp-Erkennung, Luhn-Prüfung und sauberer Integration in PCI-konforme Zahlungsanbieter für euren Magento-Checkout.

Eingabemaske

Formatierung, Kartentyp-Erkennung und Luhn-Prüfung nach Maß

Zahlungsanbieter-Integration

Stripe, Adyen und weitere PCI-konforme Anbieter anbinden

Barrierefreiheit

Autocomplete-Attribute und aria-invalid für Zahlungsfelder

10. Zusammenfassung

Eine gute Kreditkarten-Eingabemaske in Alpine.js kombiniert vier Bausteine: Kartentyp-Erkennung anhand des Präfixes, kartentypabhängige Gruppierung, eine Cursor-Korrektur, die Eingaben in der Mitte der Nummer weiterhin erlaubt, und die Luhn-Prüfsumme als frühe Plausibilitätsprüfung ohne Server-Anfrage. Ablaufdatum und CVC-Länge folgen denselben kartentypabhängigen Regeln.

Wichtig bleibt die klare Grenze: die Maske verbessert die Bedienung, ersetzt aber niemals die PCI-konforme Übertragung sensibler Kartendaten an einen zertifizierten Zahlungsdienstleister. Wer diese Trennung von Anfang an einhält, bekommt eine Kreditkarten-Eingabemaske, die professionell wirkt und gleichzeitig die Sicherheitsanforderungen der Zahlungsindustrie respektiert.

Kreditkarten-Eingabemaske mit Alpine.js — Das Wichtigste auf einen Blick

Kartentyp

Präfix-Erkennung für Visa, Mastercard und Amex steuert Gruppierung und CVC-Länge.

Cursor

Position nach der Neuformatierung anhand der Längendifferenz korrigieren, nicht ans Ende springen.

Luhn

Prüfsumme entdeckt Tippfehler clientseitig, ersetzt aber keine echte Autorisierung.

Sicherheit

Rohe Kartennummern gehören in ein PCI-konformes Anbieter-Formular, nicht auf den eigenen Server.

11. FAQ: Kreditkarten-Eingabemaske mit Alpine.js

1Warum ist feste 4-4-4-4-Gruppierung falsch?
Amex nutzt 4-6-5 mit fünfzehn Ziffern, eine feste Vierergruppierung formatiert das falsch.
2Wie erkennt man den Kartentyp?
Anhand der ersten Ziffern: Visa mit 4, Mastercard mit 51 bis 55, Amex mit 34 oder 37.
3Warum springt der Cursor ans Ende?
Programmatische Wertänderung setzt die Cursor-Position standardmäßig zurück, manuell korrigieren nötig.
4Was macht der Luhn-Algorithmus?
Verdoppelt jede zweite Ziffer von rechts und prüft, ob die Summe durch zehn teilbar ist.
5Bedeutet Luhn-gültig, dass die Karte echt ist?
Nein, nur strukturell plausibel. Echtheit klärt erst die Autorisierung beim Zahlungsdienstleister.
6Wie lang ist der CVC je Kartentyp?
Vier Ziffern bei Amex, drei bei allen anderen gängigen Kartentypen.
7Welche autocomplete-Attribute nötig?
cc-number, cc-exp und cc-csc für Kartennummer, Ablaufdatum und CVC.
8Rohe Nummer an eigenen Server?
In den meisten PCI-DSS-Konfigurationen nein, ein zertifiziertes Anbieter-Formular übernimmt das.
9Was passiert bei Browser-Autofill?
Autofill füllt oft ohne Leerzeichen, dieselbe Bereinigung wie bei manueller Eingabe muss laufen.
10Ersetzt das eine serverseitige Prüfung?
Nein, die Autorisierung findet immer beim Zahlungsdienstleister statt.