Wie erkennt man den Kreditkartentyp anhand der Nummer?


516

Ich versuche herauszufinden, wie man den Kreditkartentyp nur anhand seiner Nummer erkennt. Kennt jemand einen endgültigen, zuverlässigen Weg, dies zu finden?


3
Verwenden eines regulären Ausdrucks. Weitere Informationen finden Sie unter diesem Link .
Senfo

3
Die Details sind alle auf Wikipedia: en.wikipedia.org/wiki/Credit_card_numbers
Sten Vesterli

1
Es gibt eine gute Übersichtstabelle in Wikipedia unter en.wikipedia.org/wiki/Credit_card_numbers . Es sind die ersten ein bis sechs Ziffern, die den Typ und den Aussteller der Karte angeben.
Alex

3
Ich würde keinen anderen regulären Ausdruck verwenden, als die erste numerische Gruppe herauszuziehen. Dies kann man im Allgemeinen nur anhand der ersten 4 Zahlen (in den USA) erkennen. Bevor Sie sich die Mühe machen, für das Löschen einer Gebühr zu bezahlen, führen Sie eine Mod 10-Prüfsumme für die Kartennummer durch, um sicherzustellen, dass diese legitim ist. Luhn-Algorithmus
Dan Blair

3
kann auch jemand kommentieren, ob diese Algorithmen "für alle Zeiten" gut sind - oder sie ändern sich regelmäßig, wie zum Beispiel der Algorithmus zum "Berechnen, ob eine Telefonnummer in Kalifornien ist"
Simon_Weaver

Antworten:


772

Die Kredit- / Debitkartennummer wird als PAN oder primäre Kontonummer bezeichnet . Die ersten sechs Ziffern der PAN stammen aus der IIN oder Emittentenidentifikationsnummer der ausstellenden Bank (IINs wurden früher als BIN - Bankidentifikationsnummern bezeichnet - daher finden Sie in einigen Dokumenten möglicherweise Verweise auf diese Terminologie). Diese sechs Ziffern unterliegen einer internationalen Norm, ISO / IEC 7812 , und können verwendet werden, um den Kartentyp anhand der Nummer zu bestimmen.

Leider ist die aktuelle ISO / IEC 7812-Datenbank nicht öffentlich verfügbar. Es gibt jedoch inoffizielle kommerzielle und kostenlose Listen, auch auf Wikipedia .

Um den Typ anhand der Nummer zu erkennen, können Sie einen regulären Ausdruck wie den folgenden verwenden: Gutschrift für Originalausdrücke

Visa: ^4[0-9]{6,}$ Visa-Kartennummern beginnen mit einer 4.

MasterCard: ^5[1-5][0-9]{5,}|222[1-9][0-9]{3,}|22[3-9][0-9]{4,}|2[3-6][0-9]{5,}|27[01][0-9]{4,}|2720[0-9]{3,}$ Vor 2016 beginnen MasterCard-Nummern mit den Nummern 51 bis 55, dies erkennt jedoch nur MasterCard-Kreditkarten . Es gibt andere Karten, die mit dem MasterCard-System ausgestellt wurden und nicht in diesen IIN-Bereich fallen. 2016 werden sie Zahlen im Bereich (222100-272099) hinzufügen.

American Express: ^3[47][0-9]{5,}$ American Express-Kartennummern beginnen mit 34 oder 37.

Diners Club: ^3(?:0[0-5]|[68][0-9])[0-9]{4,}$ Diners Club-Kartennummern beginnen mit 300 bis 305, 36 oder 38. Es gibt Diners Club-Karten, die mit 5 beginnen und 16 Ziffern haben. Dies ist ein Joint Venture zwischen Diners Club und MasterCard und sollte wie eine MasterCard verarbeitet werden.

Entdecken: ^6(?:011|5[0-9]{2})[0-9]{3,}$ Entdecken Sie Kartennummern, die mit 6011 oder 65 beginnen.

JCB: ^(?:2131|1800|35[0-9]{3})[0-9]{3,}$ JCB-Karten beginnen mit 2131, 1800 oder 35.

Leider gibt es eine Reihe von Kartentypen, die mit dem MasterCard-System verarbeitet werden und nicht im IIN-Bereich von MasterCard liegen (Nummern ab 51 ... 55). Der wichtigste Fall ist der von Maestro-Karten, von denen viele aus den IIN-Bereichen anderer Banken ausgegeben wurden und sich daher im gesamten Nummernraum befinden. Daher kann es am besten sein anzunehmen, dass jede Karte, die nicht von einem anderen Typ ist, den Sie akzeptieren, eine MasterCard sein muss .

Wichtig : Die Kartennummern variieren in der Länge. Beispielsweise hat Visa in der Vergangenheit Karten mit 13-stelligen PANs und Karten mit 16-stelligen PANs ausgegeben. Aus den Unterlagen von Visa geht derzeit hervor, dass möglicherweise Nummern mit 12 bis 19 Ziffern ausgegeben wurden oder ausgegeben wurden. Daher sollten Sie die Länge der Kartennummer nicht überprüfen, außer um sicherzustellen, dass sie mindestens 7 Ziffern hat (für eine vollständige IIN plus eine Prüfziffer, die mit dem vom Luhn-Algorithmus vorhergesagten Wert übereinstimmen sollte ).

Ein weiterer Hinweis: Entfernen Sie vor der Verarbeitung einer Karteninhaber-PAN Leerzeichen und Satzzeichen aus der Eingabe . Warum? Weil es normalerweise viel einfacher ist, die Ziffern in Gruppen einzugeben, ähnlich wie sie auf der Vorderseite einer tatsächlichen Kreditkarte angezeigt werden, d. H.

4444 4444 4444 4444

ist viel einfacher korrekt einzugeben als

4444444444444444

Es hat wirklich keinen Vorteil, den Benutzer zu züchtigen, da er Zeichen eingegeben hat, die Sie hier nicht erwarten.

Dies bedeutet auch, dass Sie sicherstellen müssen, dass Ihre Eingabefelder Platz für mindestens 24 Zeichen bieten. Andernfalls wird Benutzern, die Leerzeichen eingeben, der Platz ausgehen. Ich würde empfehlen, dass Sie das Feld breit genug machen, um 32 Zeichen anzuzeigen und bis zu 64 zuzulassen. Das gibt viel Spielraum für Erweiterungen.

Hier ist ein Bild, das etwas mehr Einblick gibt:

UPDATE (2014): Die Prüfsummenmethode scheint keine gültige Methode mehr zu sein, um die Echtheit einer Karte zu überprüfen, wie in den Kommentaren zu dieser Antwort angegeben.

UPDATE (2016): Mastercard implementiert neue BIN-Bereiche ab Ach Payment .

Credit Card Verification


7
gutes Beispiel. Hast du den regulären Ausdruck für Maestro-Karten?
Manikandan

4
Nein nein Nein. Sie können sich nicht auf die Länge der Kartennummern verlassen. Sie können sich jederzeit ändern. Der einzige Teil der Kartennummer, auf den Sie sich verlassen können, ist die IIN (die früher als BIN bezeichnet wurde) und ein Präfix der Nummer. Zusätzlich Sie können nicht erkennen , Mastercard - Karten in der Art und Weise Sie vorschlagen; Dadurch wird nur eine Teilmenge der Karten erfasst, die über das Mastercard-System verarbeitet werden (das Hauptproblem sind Maestro-Karten mit verschiedenen IIN-Präfixen).
Alastair

2
@alastair hast du die Ausdrücke vor dem Kommentieren gelesen? Sie wurden speziell für die Verwendung der IIN geschrieben, daher verstehe ich nicht, was Sie sagen wollen. Darüber hinaus kann die IIN verwendet werden, um den Kartenaussteller zu identifizieren, aber nicht zu validieren. 5412 stellt beispielsweise keine vollständige MasterCard dar, aber Ihr Vorschlag würde implizieren, dass dies der Fall ist. Ich habe keinen Beweis dafür gefunden, dass MasterCards alles andere als 16-stellig sind. Bitte geben Sie eine Quelle für Ihren Anspruch an. Sie haben Recht, wenn Sie erwähnen, dass für Maestro-Karten ein Update durchgeführt werden muss.
Senfo

3
@senfo Du hast recht, 5412 wäre keine vollständige Mastercard-Nummer. IINs sind sechsstellig, daher muss eine vollständige Kartennummer mindestens siebenstellig sein und den Luhn-Scheck bestehen. Es ist kein „Beweis“ erforderlich, dass Mastercard-Nummern nicht aus 16 Ziffern bestehen. Der Punkt ist, dass sie unabhängig von der heutigen Situation in Zukunft möglicherweise Karten mit 17 oder 18 Ziffern oder einige mit 15 Ziffern ausgeben. Es ist unnötig, sich darauf zu verlassen, dass sie 16 Ziffern lang sind, und es entsteht ein langfristiges Wartungsrisiko.
Alastair

3
Es fällt mir sehr schwer zu glauben, dass einige gültige Karten nach dem Luhn-Algorithmus keine korrekte Prüfziffer haben würden. Es wurde absolut überall verwendet, um Kartennummern gegen einfache Tippfehler und dumme Betrugsversuche zu überprüfen. Stattdessen habe ich beobachtet, dass einige ziemlich kluge Leute den Algorithmus einfach nicht verstehen und ihn einfach falsch berechnen.
Rennex

74

In Javascript:

function detectCardType(number) {
    var re = {
        electron: /^(4026|417500|4405|4508|4844|4913|4917)\d+$/,
        maestro: /^(5018|5020|5038|5612|5893|6304|6759|6761|6762|6763|0604|6390)\d+$/,
        dankort: /^(5019)\d+$/,
        interpayment: /^(636)\d+$/,
        unionpay: /^(62|88)\d+$/,
        visa: /^4[0-9]{12}(?:[0-9]{3})?$/,
        mastercard: /^5[1-5][0-9]{14}$/,
        amex: /^3[47][0-9]{13}$/,
        diners: /^3(?:0[0-5]|[68][0-9])[0-9]{11}$/,
        discover: /^6(?:011|5[0-9]{2})[0-9]{12}$/,
        jcb: /^(?:2131|1800|35\d{3})\d{11}$/
    }

    for(var key in re) {
        if(re[key].test(number)) {
            return key
        }
    }
}

Gerätetest:

describe('CreditCard', function() {
    describe('#detectCardType', function() {

        var cards = {
            '8800000000000000': 'UNIONPAY',

            '4026000000000000': 'ELECTRON',
            '4175000000000000': 'ELECTRON',
            '4405000000000000': 'ELECTRON',
            '4508000000000000': 'ELECTRON',
            '4844000000000000': 'ELECTRON',
            '4913000000000000': 'ELECTRON',
            '4917000000000000': 'ELECTRON',

            '5019000000000000': 'DANKORT',

            '5018000000000000': 'MAESTRO',
            '5020000000000000': 'MAESTRO',
            '5038000000000000': 'MAESTRO',
            '5612000000000000': 'MAESTRO',
            '5893000000000000': 'MAESTRO',
            '6304000000000000': 'MAESTRO',
            '6759000000000000': 'MAESTRO',
            '6761000000000000': 'MAESTRO',
            '6762000000000000': 'MAESTRO',
            '6763000000000000': 'MAESTRO',
            '0604000000000000': 'MAESTRO',
            '6390000000000000': 'MAESTRO',

            '3528000000000000': 'JCB',
            '3589000000000000': 'JCB',
            '3529000000000000': 'JCB',

            '6360000000000000': 'INTERPAYMENT',

            '4916338506082832': 'VISA',
            '4556015886206505': 'VISA',
            '4539048040151731': 'VISA',
            '4024007198964305': 'VISA',
            '4716175187624512': 'VISA',

            '5280934283171080': 'MASTERCARD',
            '5456060454627409': 'MASTERCARD',
            '5331113404316994': 'MASTERCARD',
            '5259474113320034': 'MASTERCARD',
            '5442179619690834': 'MASTERCARD',

            '6011894492395579': 'DISCOVER',
            '6011388644154687': 'DISCOVER',
            '6011880085013612': 'DISCOVER',
            '6011652795433988': 'DISCOVER',
            '6011375973328347': 'DISCOVER',

            '345936346788903': 'AMEX',
            '377669501013152': 'AMEX',
            '373083634595479': 'AMEX',
            '370710819865268': 'AMEX',
            '371095063560404': 'AMEX'
        };

        Object.keys(cards).forEach(function(number) {
            it('should detect card ' + number + ' as ' + cards[number], function() {
                Basket.detectCardType(number).should.equal(cards[number]);
            });
        });
    });
});

1
@ jolly.exe - Ihre Geige wird für alle Tests undefiniert zurückgegeben. Funktioniert nicht :(
ShadeTreeDeveloper

@ShadeTreeDeveloper geben Sie einfach einen beliebigen Wert ein, z. 372176090165471 für AMAX im Textfeld
Code Spy

@ jolly.exe Ich verstehe ... Ich hatte auf etwas gehofft, das sich während der Eingabe formatieren lässt (außerhalb des Keyup-Ereignisses). Die Geige funktioniert, wenn ich eine vollständige Nummer eingebe.
ShadeTreeDeveloper

Am Ende habe ich diesen Code geschrieben, um die gewünschte Formatierung und Validierung der Eingabe vorzunehmen. quercusv.github.io/smartForm
ShadeTreeDeveloper

Wissen Sie, wie man V-Pay- und Bancontact-Kartennummern erkennt? Vielen Dank
Oleksandr IY

38

Aktualisiert: 15. Juni 2016 (derzeit als ultimative Lösung)

Bitte beachten Sie, dass ich sogar die Stimme für diejenige gebe, die am besten gewählt wurde, aber um klar zu machen, dass dies die regulären Ausdrücke sind, habe ich sie mit Tausenden von echten BIN-Codes getestet. Am wichtigsten ist es, Startzeichenfolgen (^) zu verwenden, da dies sonst in der realen Welt zu falschen Ergebnissen führt!

JCB ^(?:2131|1800|35)[0-9]{0,}$ Beginnen Sie mit: 2131, 1800, 35 (3528-3589)

American Express ^3[47][0-9]{0,}$ Beginnen Sie mit: 34, 37

Diners Club ^3(?:0[0-59]{1}|[689])[0-9]{0,}$ Beginnen Sie mit: 300-305, 309, 36, 38-39

Visum ^4[0-9]{0,}$ Beginnen Sie mit: 4

MasterCard ^(5[1-5]|222[1-9]|22[3-9]|2[3-6]|27[01]|2720)[0-9]{0,}$ Beginnen Sie mit: 2221-2720, 51-55

Maestro ^(5[06789]|6)[0-9]{0,}$ Maestro wächst immer im Bereich: 60-69 , begann mit / nicht mit etwas anderem, aber ab 5 muss trotzdem als Mastercard codiert werden. Maestro-Karten müssen am Ende des Codes erkannt werden, da einige andere im Bereich von 60-69 liegen. Bitte schauen Sie sich den Code an.

Entdecken ^(6011|65|64[4-9]|62212[6-9]|6221[3-9]|622[2-8]|6229[01]|62292[0-5])[0-9]{0,}$ Entdecken Sie ziemlich schwer zu codierende, beginnen Sie mit: 6011, 622126-622925, 644-649, 65

In Javascript benutze ich diese Funktion. Dies ist gut, wenn Sie es einem Onkeyup-Ereignis zuweisen und es so schnell wie möglich ein Ergebnis liefert.

function cc_brand_id(cur_val) {
    // the regular expressions check for possible matches as you type, hence the OR operators based on the number of chars
    // regexp string length {0} provided for soonest detection of beginning of the card numbers this way it could be used for BIN CODE detection also

    //JCB
    jcb_regex = new RegExp('^(?:2131|1800|35)[0-9]{0,}$'); //2131, 1800, 35 (3528-3589)
    // American Express
    amex_regex = new RegExp('^3[47][0-9]{0,}$'); //34, 37
    // Diners Club
    diners_regex = new RegExp('^3(?:0[0-59]{1}|[689])[0-9]{0,}$'); //300-305, 309, 36, 38-39
    // Visa
    visa_regex = new RegExp('^4[0-9]{0,}$'); //4
    // MasterCard
    mastercard_regex = new RegExp('^(5[1-5]|222[1-9]|22[3-9]|2[3-6]|27[01]|2720)[0-9]{0,}$'); //2221-2720, 51-55
    maestro_regex = new RegExp('^(5[06789]|6)[0-9]{0,}$'); //always growing in the range: 60-69, started with / not something else, but starting 5 must be encoded as mastercard anyway
    //Discover
    discover_regex = new RegExp('^(6011|65|64[4-9]|62212[6-9]|6221[3-9]|622[2-8]|6229[01]|62292[0-5])[0-9]{0,}$');
    ////6011, 622126-622925, 644-649, 65


    // get rid of anything but numbers
    cur_val = cur_val.replace(/\D/g, '');

    // checks per each, as their could be multiple hits
    //fix: ordering matter in detection, otherwise can give false results in rare cases
    var sel_brand = "unknown";
    if (cur_val.match(jcb_regex)) {
        sel_brand = "jcb";
    } else if (cur_val.match(amex_regex)) {
        sel_brand = "amex";
    } else if (cur_val.match(diners_regex)) {
        sel_brand = "diners_club";
    } else if (cur_val.match(visa_regex)) {
        sel_brand = "visa";
    } else if (cur_val.match(mastercard_regex)) {
        sel_brand = "mastercard";
    } else if (cur_val.match(discover_regex)) {
        sel_brand = "discover";
    } else if (cur_val.match(maestro_regex)) {
        if (cur_val[0] == '5') { //started 5 must be mastercard
            sel_brand = "mastercard";
        } else {
            sel_brand = "maestro"; //maestro is all 60-69 which is not something else, thats why this condition in the end
        }
    }

    return sel_brand;
}

Hier können Sie damit spielen:

http://jsfiddle.net/upN3L/69/

Wenn PHP diese Funktion verwendet, werden auch einige Sub-VISA / MC-Karten erkannt:

/**
  * Obtain a brand constant from a PAN
  *
  * @param string $pan               Credit card number
  * @param bool   $include_sub_types Include detection of sub visa brands
  * @return string
  */
public static function getCardBrand($pan, $include_sub_types = false)
{
    //maximum length is not fixed now, there are growing number of CCs has more numbers in length, limiting can give false negatives atm

    //these regexps accept not whole cc numbers too
    //visa
    $visa_regex = "/^4[0-9]{0,}$/";
    $vpreca_regex = "/^428485[0-9]{0,}$/";
    $postepay_regex = "/^(402360|402361|403035|417631|529948){0,}$/";
    $cartasi_regex = "/^(432917|432930|453998)[0-9]{0,}$/";
    $entropay_regex = "/^(406742|410162|431380|459061|533844|522093)[0-9]{0,}$/";
    $o2money_regex = "/^(422793|475743)[0-9]{0,}$/";

    // MasterCard
    $mastercard_regex = "/^(5[1-5]|222[1-9]|22[3-9]|2[3-6]|27[01]|2720)[0-9]{0,}$/";
    $maestro_regex = "/^(5[06789]|6)[0-9]{0,}$/";
    $kukuruza_regex = "/^525477[0-9]{0,}$/";
    $yunacard_regex = "/^541275[0-9]{0,}$/";

    // American Express
    $amex_regex = "/^3[47][0-9]{0,}$/";

    // Diners Club
    $diners_regex = "/^3(?:0[0-59]{1}|[689])[0-9]{0,}$/";

    //Discover
    $discover_regex = "/^(6011|65|64[4-9]|62212[6-9]|6221[3-9]|622[2-8]|6229[01]|62292[0-5])[0-9]{0,}$/";

    //JCB
    $jcb_regex = "/^(?:2131|1800|35)[0-9]{0,}$/";

    //ordering matter in detection, otherwise can give false results in rare cases
    if (preg_match($jcb_regex, $pan)) {
        return "jcb";
    }

    if (preg_match($amex_regex, $pan)) {
        return "amex";
    }

    if (preg_match($diners_regex, $pan)) {
        return "diners_club";
    }

    //sub visa/mastercard cards
    if ($include_sub_types) {
        if (preg_match($vpreca_regex, $pan)) {
            return "v-preca";
        }
        if (preg_match($postepay_regex, $pan)) {
            return "postepay";
        }
        if (preg_match($cartasi_regex, $pan)) {
            return "cartasi";
        }
        if (preg_match($entropay_regex, $pan)) {
            return "entropay";
        }
        if (preg_match($o2money_regex, $pan)) {
            return "o2money";
        }
        if (preg_match($kukuruza_regex, $pan)) {
            return "kukuruza";
        }
        if (preg_match($yunacard_regex, $pan)) {
            return "yunacard";
        }
    }

    if (preg_match($visa_regex, $pan)) {
        return "visa";
    }

    if (preg_match($mastercard_regex, $pan)) {
        return "mastercard";
    }

    if (preg_match($discover_regex, $pan)) {
        return "discover";
    }

    if (preg_match($maestro_regex, $pan)) {
        if ($pan[0] == '5') { //started 5 must be mastercard
            return "mastercard";
        }
        return "maestro"; //maestro is all 60-69 which is not something else, thats why this condition in the end

    }

    return "unknown"; //unknown for this system
}

1
Und bitte beachten Sie, dass dies nur die Erkennung von CC-Nummern und keine Validierung ist. Das ist getrennt, sollte ein Luhn-Scheck sein ...
Janos Szabo

Wo ist Visa Electron und warum gibt der Maestro-Scheck in einigen Fällen MasterCard zurück? Sollte die MasterCard das nicht selbst überprüfen?
BadHorsie

Diese JCB-Testnummer wird nicht als einer der Typen erkannt (3088514174175777), und diese Test-JCB-Nummer wird als diners_club (3096278649822922) identifiziert. Angenommen, diese Liste der Testkartennummern ist trotzdem gültig ( freeformatter.com/credit-card-number-generator-validator.html )
Drew,

Es gibt keine Dokumentation, dass das Starten von 308 oder 309 eine JCB-Karte sein könnte
Janos Szabo

+1 für die Bereitstellung des CC-Typ-Erkennungscodes, wie Sie es normalerweise für den UX tun möchten - der reguläre Ausdruck für den neuen Bereich auf dem MC benötigt eine kleine Woche: / ^ (5 [1-5] | 222 [1-9] | 22 [3-9] [0-9] | 2 [3-6] [0-9] {2} | 27 [01] [0-9] | 2720) [0-9] {0,} $ /
Kinakuta

21
public string GetCreditCardType(string CreditCardNumber)
{
    Regex regVisa = new Regex("^4[0-9]{12}(?:[0-9]{3})?$");
    Regex regMaster = new Regex("^5[1-5][0-9]{14}$");
    Regex regExpress = new Regex("^3[47][0-9]{13}$");
    Regex regDiners = new Regex("^3(?:0[0-5]|[68][0-9])[0-9]{11}$");
    Regex regDiscover = new Regex("^6(?:011|5[0-9]{2})[0-9]{12}$");
    Regex regJCB = new Regex("^(?:2131|1800|35\\d{3})\\d{11}$");


    if (regVisa.IsMatch(CreditCardNumber))
        return "VISA";
    else if (regMaster.IsMatch(CreditCardNumber))
        return "MASTER";
    else  if (regExpress.IsMatch(CreditCardNumber))
        return "AEXPRESS";
    else if (regDiners.IsMatch(CreditCardNumber))
        return "DINERS";
    else if (regDiscover.IsMatch(CreditCardNumber))
        return "DISCOVERS";
    else if (regJCB.IsMatch(CreditCardNumber))
        return "JCB";
    else
        return "invalid";
}

Hier ist die Funktion zum Überprüfen des Kreditkartentyps mit Regex, c #


19

Überprüfen Sie dies heraus:

http://www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256CC70060A01B

function isValidCreditCard(type, ccnum) {
    /* Visa: length 16, prefix 4, dashes optional.
    Mastercard: length 16, prefix 51-55, dashes optional.
    Discover: length 16, prefix 6011, dashes optional.
    American Express: length 15, prefix 34 or 37.
    Diners: length 14, prefix 30, 36, or 38. */

    var re = new Regex({
        "visa": "/^4\d{3}-?\d{4}-?\d{4}-?\d",
        "mc": "/^5[1-5]\d{2}-?\d{4}-?\d{4}-?\d{4}$/",
        "disc": "/^6011-?\d{4}-?\d{4}-?\d{4}$/",
        "amex": "/^3[47]\d{13}$/",
        "diners": "/^3[068]\d{12}$/"
    }[type.toLowerCase()])

    if (!re.test(ccnum)) return false;
    // Remove all dashes for the checksum checks to eliminate negative numbers
    ccnum = ccnum.split("-").join("");
    // Checksum ("Mod 10")
    // Add even digits in even length strings or odd digits in odd length strings.
    var checksum = 0;
    for (var i = (2 - (ccnum.length % 2)); i <= ccnum.length; i += 2) {
        checksum += parseInt(ccnum.charAt(i - 1));
    }
    // Analyze odd digits in even length strings or even digits in odd length strings.
    for (var i = (ccnum.length % 2) + 1; i < ccnum.length; i += 2) {
        var digit = parseInt(ccnum.charAt(i - 1)) * 2;
        if (digit < 10) { checksum += digit; } else { checksum += (digit - 9); }
    }
    if ((checksum % 10) == 0) return true;
    else return false;
}

15

Vor kurzem brauchte ich solche Funktionen, ich portierte Zend Framework Credit Card Validator auf Ruby. Ruby Gem: https://github.com/Fivell/credit_card_validations Zend Framework: https://github.com/zendframework/zf2/blob/master/library/Zend/Validator/CreditCard.php

Beide verwenden INN-Bereiche zur Erkennung des Typs. Hier können Sie über INN lesen

Demnach können Sie alternativ eine Kreditkarte erkennen (ohne reguläre Ausdrücke, aber unter Angabe einiger Regeln zu Präfixen und möglicher Länge)

Wir haben also die nächsten Regeln für die meisten verwendeten Karten

########  most used brands #########

    visa: [
        {length: [13, 16], prefixes: ['4']}
    ],
    mastercard: [
        {length: [16], prefixes: ['51', '52', '53', '54', '55']}
    ],

    amex: [
        {length: [15], prefixes: ['34', '37']}
    ],
    ######## other brands ########
    diners: [
        {length: [14], prefixes: ['300', '301', '302', '303', '304', '305', '36', '38']},
    ],

    #There are Diners Club (North America) cards that begin with 5. These are a joint venture between Diners Club and MasterCard, and are processed like a MasterCard
    # will be removed in next major version

    diners_us: [
        {length: [16], prefixes: ['54', '55']}
    ],

    discover: [
        {length: [16], prefixes: ['6011', '644', '645', '646', '647', '648',
                                  '649', '65']}
    ],

    jcb: [
        {length: [16], prefixes: ['3528', '3529', '353', '354', '355', '356', '357', '358', '1800', '2131']}
    ],


    laser: [
        {length: [16, 17, 18, 19], prefixes: ['6304', '6706', '6771']}
    ],

    solo: [
        {length: [16, 18, 19], prefixes: ['6334', '6767']}
    ],

    switch: [
        {length: [16, 18, 19], prefixes: ['633110', '633312', '633304', '633303', '633301', '633300']}

    ],

    maestro: [
        {length: [12, 13, 14, 15, 16, 17, 18, 19], prefixes: ['5010', '5011', '5012', '5013', '5014', '5015', '5016', '5017', '5018',
                                                              '502', '503', '504', '505', '506', '507', '508',
                                                              '6012', '6013', '6014', '6015', '6016', '6017', '6018', '6019',
                                                              '602', '603', '604', '605', '6060',
                                                              '677', '675', '674', '673', '672', '671', '670',
                                                              '6760', '6761', '6762', '6763', '6764', '6765', '6766', '6768', '6769']}
    ],

    # Luhn validation are skipped for union pay cards because they have unknown generation algoritm
    unionpay: [
        {length: [16, 17, 18, 19], prefixes: ['622', '624', '625', '626', '628'], skip_luhn: true}
    ],

    dankrot: [
        {length: [16], prefixes: ['5019']}
    ],

    rupay: [
        {length: [16], prefixes: ['6061', '6062', '6063', '6064', '6065', '6066', '6067', '6068', '6069', '607', '608'], skip_luhn: true}
    ]

}

Durch Suchen des Präfixes und Vergleichen der Länge können Sie dann die Kreditkartenmarke erkennen. Vergessen Sie auch nicht den Luhn-Algorithmus (er wird hier beschrieben http://en.wikipedia.org/wiki/Luhn ).

AKTUALISIEREN

Eine aktualisierte Liste der Regeln finden Sie hier https://raw.githubusercontent.com/Fivell/credit_card_validations/master/lib/data/brands.yaml


2
Sehr anschaulich. VISA-Karten können 13-stellig sein.
Herman Kan

@HermanKan, keine VISA-Website sagt, dass es 16 Länge sein sollte, ich denke vor langer Zeit könnte es 13 sein, aber heutzutage nicht
Fivell

1
Ich denke, es ist Legacy-Unterstützung
Fivell

1
@HermanKan, es gibt noch eine Sache: VISA hat VPay-Karten und gemäß der Marke VPay von Wikipedia Visa können PAN-Längen von 13 bis 19 Stellen angegeben werden, sodass jetzt eine Kartennummer von mehr als 16 Stellen angezeigt wird.
Fivell

1
@Ethan, überprüfen Sie den letzten Link in meiner aktualisierten Antwort raw.githubusercontent.com/Fivell/credit_card_validations/master/…
Fivell

13

Hier ist der vollständige C # - oder VB-Code für alle Arten von CC-bezogenen Dingen im Codeprojekt.

  • IsValidNumber
  • GetCardTypeFromNumber
  • GetCardTestNumber
  • PassesLuhnTest

Dieser Artikel ist seit ein paar Jahren ohne negative Kommentare.


1
@barett - behoben. Es sieht so aus, als hätten sie es von der Kategorie "Aspnet" in die Kategorie "Validierung" verschoben, wodurch der Link geändert wurde
Simon_Weaver

2
Link ist unterbrochen. Vielleicht ist dies das gleiche Dienstprogramm? codeproject.com/Articles/20271/…
Josh Noe

Dieser Code für das Codeprojekt stammt aus dem Jahr 2007. Warnung: Möglicherweise ist er veraltet.
Aron

8

Kompakte Javascript-Version

    var getCardType = function (number) {
        var cards = {
            visa: /^4[0-9]{12}(?:[0-9]{3})?$/,
            mastercard: /^5[1-5][0-9]{14}$/,
            amex: /^3[47][0-9]{13}$/,
            diners: /^3(?:0[0-5]|[68][0-9])[0-9]{11}$/,
            discover: /^6(?:011|5[0-9]{2})[0-9]{12}$/,
            jcb: /^(?:2131|1800|35\d{3})\d{11}$/
        };
        for (var card in cards) {
            if (cards[card].test(number)) {
                return card;
            }
        }
    };

8

Anatoliy Antwort in PHP:

 public static function detectCardType($num)
 {
    $re = array(
        "visa"       => "/^4[0-9]{12}(?:[0-9]{3})?$/",
        "mastercard" => "/^5[1-5][0-9]{14}$/",
        "amex"       => "/^3[47][0-9]{13}$/",
        "discover"   => "/^6(?:011|5[0-9]{2})[0-9]{12}$/",
    );

    if (preg_match($re['visa'],$num))
    {
        return 'visa';
    }
    else if (preg_match($re['mastercard'],$num))
    {
        return 'mastercard';
    }
    else if (preg_match($re['amex'],$num))
    {
        return 'amex';
    }
    else if (preg_match($re['discover'],$num))
    {
        return 'discover';
    }
    else
    {
        return false;
    }
 }

7

Hier ist eine PHP-Klassenfunktion, die CCtype by CCnumber zurückgibt.
Dieser Code validiert die Karte nicht oder führt den Luhn-Algorithmus nicht aus. Versuchen Sie nur, den Kreditkartentyp anhand der Tabelle auf dieser Seite zu ermitteln . Verwendet grundsätzlich die CC-Nummernlänge und das CC-Kartenpräfix, um den CC-Kartentyp zu bestimmen.

<?php
class CreditcardType
{
    public static $creditcardTypes = [
        [
            'Name' => 'American Express',
            'cardLength' => [15],
            'cardPrefix' => ['34', '37'],
        ], [
            'Name' => 'Maestro',
            'cardLength' => [12, 13, 14, 15, 16, 17, 18, 19],
            'cardPrefix' => ['5018', '5020', '5038', '6304', '6759', '6761', '6763'],
        ], [
            'Name' => 'Mastercard',
            'cardLength' => [16],
            'cardPrefix' => ['51', '52', '53', '54', '55'],
        ], [
            'Name' => 'Visa',
            'cardLength' => [13, 16],
            'cardPrefix' => ['4'],
        ], [
            'Name' => 'JCB',
            'cardLength' => [16],
            'cardPrefix' => ['3528', '3529', '353', '354', '355', '356', '357', '358'],
        ], [
            'Name' => 'Discover',
            'cardLength' => [16],
            'cardPrefix' => ['6011', '622126', '622127', '622128', '622129', '62213','62214', '62215', '62216', '62217', '62218', '62219','6222', '6223', '6224', '6225', '6226', '6227', '6228','62290', '62291', '622920', '622921', '622922', '622923','622924', '622925', '644', '645', '646', '647', '648','649', '65'],
        ], [
            'Name' => 'Solo',
            'cardLength' => [16, 18, 19],
            'cardPrefix' => ['6334', '6767'],
        ], [
            'Name' => 'Unionpay',
            'cardLength' => [16, 17, 18, 19],
            'cardPrefix' => ['622126', '622127', '622128', '622129', '62213', '62214','62215', '62216', '62217', '62218', '62219', '6222', '6223','6224', '6225', '6226', '6227', '6228', '62290', '62291','622920', '622921', '622922', '622923', '622924', '622925'],
        ], [
            'Name' => 'Diners Club',
            'cardLength' => [14],
            'cardPrefix' => ['300', '301', '302', '303', '304', '305', '36'],
        ], [
            'Name' => 'Diners Club US',
            'cardLength' => [16],
            'cardPrefix' => ['54', '55'],
        ], [
            'Name' => 'Diners Club Carte Blanche',
            'cardLength' => [14],
            'cardPrefix' => ['300', '305'],
        ], [
            'Name' => 'Laser',
            'cardLength' => [16, 17, 18, 19],
            'cardPrefix' => ['6304', '6706', '6771', '6709'],
        ],
    ];

    public static function getType($CCNumber)
    {
        $CCNumber = trim($CCNumber);
        $type = 'Unknown';
        foreach (CreditcardType::$creditcardTypes as $card) {
            if (! in_array(strlen($CCNumber), $card['cardLength'])) {
                continue;
            }
            $prefixes = '/^(' . implode('|', $card['cardPrefix']) . ')/';
            if (preg_match($prefixes, $CCNumber) == 1) {
                $type = $card['Name'];
                break;
            }
        }
        return $type;
    }
}

6

Versuchen Sie nicht, den Kreditkartentyp im Rahmen der Zahlungsabwicklung zu ermitteln. Sie riskieren, gültige Transaktionen abzulehnen.

Wenn Sie Informationen zu Ihrem Zahlungsprozessor zur Verfügung stellen müssen (zB PayPal Kreditkarte Objekt erfordert das nennen Kartenart ), dann rät von der geringsten verfügbaren Informationen, zB

$credit_card['pan'] = preg_replace('/[^0-9]/', '', $credit_card['pan']);
$inn = (int) mb_substr($credit_card['pan'], 0, 2);

// @see http://en.wikipedia.org/wiki/List_of_Bank_Identification_Numbers#Overview
if ($inn >= 40 && $inn <= 49) {
    $type = 'visa';
} else if ($inn >= 51 && $inn <= 55) {
    $type = 'mastercard';
} else if ($inn >= 60 && $inn <= 65) {
    $type = 'discover';
} else if ($inn >= 34 && $inn <= 37) {
    $type = 'amex';
} else {
    throw new \UnexpectedValueException('Unsupported card type.');
}

Diese Implementierung (nur mit den ersten beiden Ziffern) reicht aus, um alle wichtigen (und im Fall von PayPal alle unterstützten) Kartenschemata zu identifizieren. Möglicherweise möchten Sie die Ausnahme sogar ganz überspringen und standardmäßig den beliebtesten Kartentyp verwenden. Lassen Sie sich vom Zahlungsgateway / -prozessor mitteilen, ob als Antwort auf Ihre Anfrage ein Validierungsfehler vorliegt.

Die Realität ist, dass Ihr Zahlungsgateway sich nicht um den von Ihnen bereitgestellten Wert kümmert .


1
Das ist einfach falsch. Ich kenne 3 verschiedene Anbieter, bei denen die Übergabe von Kartentypen erforderlich ist. Wenn Sie diese nicht weitergeben, schlägt die Transaktion fehl.
Ed DeGagne

3
@EdDeGagne - "ist egal, welcher Wert" ist nicht dasselbe wie "ist egal, ob übergeben".
Quentin Skousen

Wo habe ich auch angegeben? Ich habe nur erwähnt, dass es Anbieter gibt, bei denen SIE den CC-Typ übergeben müssen, nicht mehr.
Ed DeGagne

Sie können dieses komplexe Problem nicht vereinfachen, aber normalerweise müssen Zahlungsanbieter nicht den Kartentyp vorschlagen. Sie haben ihre eigene Methode, um dies zu erkennen
Janos Szabo,

6

Die ersten Nummern der Kreditkarte können verwendet werden, um den Anbieter zu approximieren:

  • Visum: 49,44 oder 47
  • Visa Elektron: 42, 45, 48, 49
  • MasterCard: 51
  • Amex: 34
  • Diners: 30, 36, 38
  • JCB: 35

Diese Bereiche wurden größtenteils aktualisiert. Unternehmen von Kartenanbietern haben weit mehr Bereiche hinzugefügt, als in der Veröffentlichung erwähnt.
NJInamdar

6

Bei der Kartenbereichserkennung (CRR) besteht ein Nachteil bei Algorithmen, die eine Reihe von regulären Ausdrücken oder anderen fest codierten Bereichen verwenden, darin, dass sich die BINs / IINs meiner Erfahrung nach im Laufe der Zeit ändern. Das Co-Branding von Karten ist eine ständige Komplikation. Unterschiedliche Kartenerwerber / -händler müssen möglicherweise dieselbe Karte unterschiedlich behandeln, abhängig von der geografischen Lage.

Darüber hinaus haben bestehende Modelle in den letzten Jahren mit z. B. UnionPay-Karten in größerem Umlauf keine neuen Bereiche bewältigt, die manchmal mit größeren Bereichen verschachteln, die sie ersetzen.
Die Kenntnis der Geografie, die Ihr System abdecken muss, kann hilfreich sein, da einige Bereiche nur in bestimmten Ländern verwendet werden dürfen. Beispielsweise umfassen die Bereiche 62 einige AAA-Unterbereiche in den USA. Wenn sich Ihre Händlerbasis jedoch außerhalb der USA befindet, können Sie möglicherweise alle 62 als UnionPay behandeln.
Möglicherweise werden Sie auch gebeten, eine Karte je nach Händlerstandort unterschiedlich zu behandeln. ZB bestimmte UK-Karten im Inland als Lastschrift, im Ausland jedoch als Gutschrift zu behandeln.

Es gibt sehr nützliche Regeln, die von einer großen übernehmenden Bank gepflegt werden. ZB https://www.barclaycard.co.uk/business/files/BIN-Rules-EIRE.pdf und https://www.barclaycard.co.uk/business/files/BIN-Rules-UK.pdf . (Gültige Links ab Juni 2017, danke an den Benutzer, der einen Link zu einer aktualisierten Referenz bereitgestellt hat.) Beachten Sie jedoch die Einschränkung, dass diese CRR-Regeln zwar das Universum der Kartenausgabe darstellen können, wie es für die von dieser Entität erworbenen Händler gilt. Es enthält keine zB als CUP / UPI identifizierten Bereiche.

Diese Kommentare gelten für Magnetstreifen- (MagStripe) oder PKE-Szenarien (Pan Key Entry). In der ICC / EMV-Welt ist die Situation wieder anders.

Update: Andere Antworten auf dieser Seite (und auch auf der verlinkten WikiPedia-Seite) haben JCB wie immer 16 lang. In meinem Unternehmen verfügen wir jedoch über ein engagiertes Team von Ingenieuren, die unsere POS-Geräte und -Software für mehrere übernehmende Banken und Regionen zertifizieren. Das neueste Zertifizierungspaket mit Karten, das dieses Team von JCB hat, hatte einen Pass für eine 19-lange PAN.


Hallo @CaiqueOliveira, siehe aktualisierte Links. Vielen Dank an mac9416, der einen Link zur aktualisierten BIN-Rules-Referenz bereitgestellt hat.
MikeRoger

1
Vielen Dank an mac9416 für die aktualisierte Referenz zu den BIN-Regeln.
MikeRoger

5

Swift 2.1 Version der Antwort von Usman Y. Verwenden Sie eine print-Anweisung, um zu überprüfen, ob der Aufruf durch einen Zeichenfolgenwert erfolgt

print(self.validateCardType(self.creditCardField.text!))

func validateCardType(testCard: String) -> String {

    let regVisa = "^4[0-9]{12}(?:[0-9]{3})?$"
    let regMaster = "^5[1-5][0-9]{14}$"
    let regExpress = "^3[47][0-9]{13}$"
    let regDiners = "^3(?:0[0-5]|[68][0-9])[0-9]{11}$"
    let regDiscover = "^6(?:011|5[0-9]{2})[0-9]{12}$"
    let regJCB = "^(?:2131|1800|35\\d{3})\\d{11}$"


    let regVisaTest = NSPredicate(format: "SELF MATCHES %@", regVisa)
    let regMasterTest = NSPredicate(format: "SELF MATCHES %@", regMaster)
    let regExpressTest = NSPredicate(format: "SELF MATCHES %@", regExpress)
    let regDinersTest = NSPredicate(format: "SELF MATCHES %@", regDiners)
    let regDiscoverTest = NSPredicate(format: "SELF MATCHES %@", regDiscover)
    let regJCBTest = NSPredicate(format: "SELF MATCHES %@", regJCB)


    if regVisaTest.evaluateWithObject(testCard){
        return "Visa"
    }
    else if regMasterTest.evaluateWithObject(testCard){
        return "MasterCard"
    }

    else if regExpressTest.evaluateWithObject(testCard){
        return "American Express"
    }

    else if regDinersTest.evaluateWithObject(testCard){
        return "Diners Club"
    }

    else if regDiscoverTest.evaluateWithObject(testCard){
        return "Discover"
    }

    else if regJCBTest.evaluateWithObject(testCard){
        return "JCB"
    }

    return ""

}

4

Stripe hat diese fantastische Javascript- Bibliothek zur Erkennung von Kartenschemata bereitgestellt . Lassen Sie mich einige Codefragmente hinzufügen und Ihnen zeigen, wie Sie es verwenden.

Fügen Sie es zunächst Ihrer Webseite als hinzu

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.payment/1.2.3/jquery.payment.js " ></script>

Verwenden Sie zweitens die Funktion cardType, um das Kartenschema zu erkennen.

$(document).ready(function() {              
            var type = $.payment.cardType("4242 4242 4242 4242"); //test card number
            console.log(type);                                   
}); 

Hier finden Sie die Referenzlinks für weitere Beispiele und Demos.

  1. Streifenblog für jquery.payment.js
  2. Github-Repository

4

In Swift können Sie eine Aufzählung erstellen, um den Kreditkartentyp zu ermitteln.

enum CreditCardType: Int { // Enum which encapsulates different card types and method to find the type of card.

case Visa
case Master
case Amex
case Discover

func validationRegex() -> String {
    var regex = ""
    switch self {
    case .Visa:
        regex = "^4[0-9]{6,}$"

    case .Master:
        regex = "^5[1-5][0-9]{5,}$"

    case .Amex:
        regex = "^3[47][0-9]{13}$"

    case .Discover:
        regex = "^6(?:011|5[0-9]{2})[0-9]{12}$"
    }

    return regex
}

func validate(cardNumber: String) -> Bool {
    let predicate = NSPredicate(format: "SELF MATCHES %@", validationRegex())
    return predicate.evaluateWithObject(cardNumber)
}

// Method returns the credit card type for given card number
static func cardTypeForCreditCardNumber(cardNumber: String) -> CreditCardType?  {
    var creditCardType: CreditCardType?

    var index = 0
    while let cardType = CreditCardType(rawValue: index) {
        if cardType.validate(cardNumber) {
            creditCardType = cardType
            break
        } else {
            index++
        }
    }
    return creditCardType
  }
}

Rufen Sie die Methode CreditCardType.cardTypeForCreditCardNumber ("# card number") auf, die den Enum-Wert von CreditCardType zurückgibt.


3

Meine Lösung mit jQuery:

function detectCreditCardType() {
    var type = new Array;
    type[1] = '^4[0-9]{12}(?:[0-9]{3})?$';      // visa
    type[2] = '^5[1-5][0-9]{14}$';              // mastercard
    type[3] = '^6(?:011|5[0-9]{2})[0-9]{12}$';  // discover
    type[4] = '^3[47][0-9]{13}$';               // amex

    var ccnum = $('.creditcard').val().replace(/[^\d.]/g, '');
    var returntype = 0;

    $.each(type, function(idx, re) {
        var regex = new RegExp(re);
        if(regex.test(ccnum) && idx>0) {
            returntype = idx;
        }
    });

    return returntype;
}

Wenn 0 zurückgegeben wird, wird der Kreditkartentyp nicht erkannt.

Die Klasse "Kreditkarte" sollte dem Eingabefeld für die Kreditkarte hinzugefügt werden.


1
Variation bestehender Antworten.
Gajus

1
Ja, ich habe den Code aus den obigen Antworten verwendet, ihn VERBESSERT und hier veröffentlicht. Danke für die Ablehnung ...
ZurabWeb

3
Sie sollten (a) dies als Verbesserung des vorhandenen Codes vorgeschlagen haben, (b) die entsprechenden Beiträge geschrieben haben oder (c) auf die Quellen verweisen, die Sie zum Schreiben der regulären Ausdrücke verwendet haben.
Gajus

1
Gajus, ich glaube, ich habe der Gemeinde so geholfen, wie ich es in diesem Moment konnte. Bitte hör auf, mir zu sagen, ich hätte etwas für jemanden tun sollen. Ich habe getan, was ich hätte helfen können.
ZurabWeb

3

Ich habe ziemlich viel nach Kreditkarten- und Telefonnummernformatierung gesucht. Ich habe viele gute Tipps gefunden, aber nichts entsprach genau meinen Wünschen, also habe ich dieses Stück Code erstellt . Sie verwenden es so:

var sf = smartForm.formatCC(myInputString);
var cardType = sf.cardType;

2
// abobjects.com, parvez ahmad ab bulk mailer
use below script

function isValidCreditCard2(type, ccnum) {
       if (type == "Visa") {
          // Visa: length 16, prefix 4, dashes optional.
          var re = /^4\d{3}?\d{4}?\d{4}?\d{4}$/;
       } else if (type == "MasterCard") {
          // Mastercard: length 16, prefix 51-55, dashes optional.
          var re = /^5[1-5]\d{2}?\d{4}?\d{4}?\d{4}$/;
       } else if (type == "Discover") {
          // Discover: length 16, prefix 6011, dashes optional.
          var re = /^6011?\d{4}?\d{4}?\d{4}$/;
       } else if (type == "AmEx") {
          // American Express: length 15, prefix 34 or 37.
          var re = /^3[4,7]\d{13}$/;
       } else if (type == "Diners") {
          // Diners: length 14, prefix 30, 36, or 38.
          var re = /^3[0,6,8]\d{12}$/;
       }
       if (!re.test(ccnum)) return false;
       return true;
       /*
       // Remove all dashes for the checksum checks to eliminate negative numbers
       ccnum = ccnum.split("-").join("");
       // Checksum ("Mod 10")
       // Add even digits in even length strings or odd digits in odd length strings.
       var checksum = 0;
       for (var i=(2-(ccnum.length % 2)); i<=ccnum.length; i+=2) {
          checksum += parseInt(ccnum.charAt(i-1));
       }
       // Analyze odd digits in even length strings or even digits in odd length strings.
       for (var i=(ccnum.length % 2) + 1; i<ccnum.length; i+=2) {
          var digit = parseInt(ccnum.charAt(i-1)) * 2;
          if (digit < 10) { checksum += digit; } else { checksum += (digit-9); }
       }
       if ((checksum % 10) == 0) return true; else return false;
       */

    }
jQuery.validator.addMethod("isValidCreditCard", function(postalcode, element) { 
    return isValidCreditCard2($("#cardType").val(), $("#cardNum").val()); 

}, "<br>credit card is invalid");


     Type</td>
                                          <td class="text">&nbsp; <form:select path="cardType" cssclass="fields" style="border: 1px solid #D5D5D5;padding: 0px 0px 0px 0px;width: 130px;height: 22px;">
                                              <option value="SELECT">SELECT</option>
                                              <option value="MasterCard">Mastercard</option>
                                              <option value="Visa">Visa</option>
                                               <option value="AmEx">American Express</option>
                                              <option value="Discover">Discover</option>
                                            </form:select> <font color="#FF0000">*</font> 

$("#signupForm").validate({

    rules:{
       companyName:{required: true},
       address1:{required: true},
       city:{required: true},
       state:{required: true},
       zip:{required: true},
       country:{required: true},
       chkAgree:{required: true},
       confPassword:{required: true},
       lastName:{required: true},
       firstName:{required: true},
       ccAddress1:{required: true},
       ccZip:{         
           postalcode : true
       },
       phone:{required: true},
       email:{
           required: true,
           email: true
           },
       userName:{
           required: true,
           minlength: 6
           },
       password:{
           required: true,
           minlength: 6
           },          
       cardNum:{           
            isValidCreditCard : true
       },

Die Frage bezieht sich auf den Algorithmus zum Überprüfen einer Kreditkarte, nicht auf eine bestimmte Implementierung. Was macht dieser Code?
Emil Vikström

2

Nur ein kleiner Löffel Fütterung:

$("#CreditCardNumber").focusout(function () {


        var regVisa = /^4[0-9]{12}(?:[0-9]{3})?$/;
        var regMasterCard = /^5[1-5][0-9]{14}$/;
        var regAmex = /^3[47][0-9]{13}$/;
        var regDiscover = /^6(?:011|5[0-9]{2})[0-9]{12}$/;

        if (regVisa.test($(this).val())) {
            $("#CCImage").html("<img height='40px' src='@Url.Content("~/images/visa.png")'>");          

        }

        else if (regMasterCard.test($(this).val())) {
        $("#CCImage").html("<img height='40px' src='@Url.Content("~/images/mastercard.png")'>");

        }

        else if (regAmex.test($(this).val())) {

           $("#CCImage").html("<img height='40px' src='@Url.Content("~/images/amex.png")'>");

        }
         else if (regDiscover.test($(this).val())) {

           $("#CCImage").html("<img height='40px' src='@Url.Content("~/images/discover.png")'>");

        }
        else {
        $("#CCImage").html("NA");

        }

    });

2

Hier ist ein Beispiel für einige in Python geschriebene boolesche Funktionen, die zurückgegeben werden, Truewenn die Karte gemäß dem Funktionsnamen erkannt wird.

def is_american_express(cc_number):
    """Checks if the card is an american express. If us billing address country code, & is_amex, use vpos
    https://en.wikipedia.org/wiki/Bank_card_number#cite_note-GenCardFeatures-3
    :param cc_number: unicode card number
    """
    return bool(re.match(r'^3[47][0-9]{13}$', cc_number))


def is_visa(cc_number):
    """Checks if the card is a visa, begins with 4 and 12 or 15 additional digits.
    :param cc_number: unicode card number
    """

    # Standard Visa is 13 or 16, debit can be 19
    if bool(re.match(r'^4', cc_number)) and len(cc_number) in [13, 16, 19]:
        return True

    return False


def is_mastercard(cc_number):
    """Checks if the card is a mastercard. Begins with 51-55 or 2221-2720 and 16 in length.
    :param cc_number: unicode card number
    """
    if len(cc_number) == 16 and cc_number.isdigit():  # Check digit, before cast to int
        return bool(re.match(r'^5[1-5]', cc_number)) or int(cc_number[:4]) in range(2221, 2721)
    return False


def is_discover(cc_number):
    """Checks if the card is discover, re would be too hard to maintain. Not a supported card.
    :param cc_number: unicode card number
    """
    if len(cc_number) == 16:
        try:
            # return bool(cc_number[:4] == '6011' or cc_number[:2] == '65' or cc_number[:6] in range(622126, 622926))
            return bool(cc_number[:4] == '6011' or cc_number[:2] == '65' or 622126 <= int(cc_number[:6]) <= 622925)
        except ValueError:
            return False
    return False


def is_jcb(cc_number):
    """Checks if the card is a jcb. Not a supported card.
    :param cc_number: unicode card number
    """
    # return bool(re.match(r'^(?:2131|1800|35\d{3})\d{11}$', cc_number))  # wikipedia
    return bool(re.match(r'^35(2[89]|[3-8][0-9])[0-9]{12}$', cc_number))  # PawelDecowski


def is_diners_club(cc_number):
    """Checks if the card is a diners club. Not a supported card.
    :param cc_number: unicode card number
    """
    return bool(re.match(r'^3(?:0[0-6]|[68][0-9])[0-9]{11}$', cc_number))  # 0-5 = carte blance, 6 = international


def is_laser(cc_number):
    """Checks if the card is laser. Not a supported card.
    :param cc_number: unicode card number
    """
    return bool(re.match(r'^(6304|670[69]|6771)', cc_number))


def is_maestro(cc_number):
    """Checks if the card is maestro. Not a supported card.
    :param cc_number: unicode card number
    """
    possible_lengths = [12, 13, 14, 15, 16, 17, 18, 19]
    return bool(re.match(r'^(50|5[6-9]|6[0-9])', cc_number)) and len(cc_number) in possible_lengths


# Child cards

def is_visa_electron(cc_number):
    """Child of visa. Checks if the card is a visa electron. Not a supported card.
    :param cc_number: unicode card number
    """
    return bool(re.match(r'^(4026|417500|4508|4844|491(3|7))', cc_number)) and len(cc_number) == 16


def is_total_rewards_visa(cc_number):
    """Child of visa. Checks if the card is a Total Rewards Visa. Not a supported card.
    :param cc_number: unicode card number
    """
    return bool(re.match(r'^41277777[0-9]{8}$', cc_number))


def is_diners_club_carte_blanche(cc_number):
    """Child card of diners. Checks if the card is a diners club carte blance. Not a supported card.
    :param cc_number: unicode card number
    """
    return bool(re.match(r'^30[0-5][0-9]{11}$', cc_number))  # github PawelDecowski, jquery-creditcardvalidator


def is_diners_club_carte_international(cc_number):
    """Child card of diners. Checks if the card is a diners club international. Not a supported card.
    :param cc_number: unicode card number
    """
    return bool(re.match(r'^36[0-9]{12}$', cc_number))  # jquery-creditcardvalidator

1

Die ersten sechs Ziffern einer Kartennummer (einschließlich der anfänglichen MII-Ziffer) werden als Ausstelleridentifikationsnummer (IIN) bezeichnet. Diese identifizieren die kartenausgebende Institution, die die Karte an den Karteninhaber ausgegeben hat. Der Rest der Nummer wird vom Kartenaussteller vergeben. Die Länge der Kartennummer entspricht der Anzahl der Ziffern. Viele Kartenaussteller drucken die gesamte IIN und Kontonummer auf ihre Karte.

Aufgrund der oben genannten Fakten möchte ich einen Ausschnitt des JAVA- Codes aufbewahren, um die Kartenmarke zu identifizieren.

Beispielkartentypen

public static final String AMERICAN_EXPRESS = "American Express";
public static final String DISCOVER = "Discover";
public static final String JCB = "JCB";
public static final String DINERS_CLUB = "Diners Club";
public static final String VISA = "Visa";
public static final String MASTERCARD = "MasterCard";
public static final String UNKNOWN = "Unknown";

Kartenpräfixe

// Based on http://en.wikipedia.org/wiki/Bank_card_number#Issuer_identification_number_.28IIN.29
public static final String[] PREFIXES_AMERICAN_EXPRESS = {"34", "37"};
public static final String[] PREFIXES_DISCOVER = {"60", "62", "64", "65"};
public static final String[] PREFIXES_JCB = {"35"};
public static final String[] PREFIXES_DINERS_CLUB = {"300", "301", "302", "303", "304", "305", "309", "36", "38", "39"};
public static final String[] PREFIXES_VISA = {"4"};
public static final String[] PREFIXES_MASTERCARD = {
        "2221", "2222", "2223", "2224", "2225", "2226", "2227", "2228", "2229",
        "223", "224", "225", "226", "227", "228", "229",
        "23", "24", "25", "26",
        "270", "271", "2720",
        "50", "51", "52", "53", "54", "55"
    };

Überprüfen Sie, ob die eingegebene Nummer eines der angegebenen Präfixe hat.

public String getBrand(String number) {

String evaluatedType;
if (StripeTextUtils.hasAnyPrefix(number, PREFIXES_AMERICAN_EXPRESS)) {
    evaluatedType = AMERICAN_EXPRESS;
} else if (StripeTextUtils.hasAnyPrefix(number, PREFIXES_DISCOVER)) {
    evaluatedType = DISCOVER;
} else if (StripeTextUtils.hasAnyPrefix(number, PREFIXES_JCB)) {
    evaluatedType = JCB;
} else if (StripeTextUtils.hasAnyPrefix(number, PREFIXES_DINERS_CLUB)) {
    evaluatedType = DINERS_CLUB;
} else if (StripeTextUtils.hasAnyPrefix(number, PREFIXES_VISA)) {
    evaluatedType = VISA;
} else if (StripeTextUtils.hasAnyPrefix(number, PREFIXES_MASTERCARD)) {
    evaluatedType = MASTERCARD;
} else {
    evaluatedType = UNKNOWN;
}
    return evaluatedType;
}

Schließlich die Utility-Methode

/**
  * Check to see if the input number has any of the given prefixes.
  *
  * @param number the number to test
  * @param prefixes the prefixes to test against
  * @return {@code true} if number begins with any of the input prefixes
*/

public static boolean hasAnyPrefix(String number, String... prefixes) {
  if (number == null) {
       return false;
  }
   for (String prefix : prefixes) {
       if (number.startsWith(prefix)) {
       return true;
    }
  }
     return false;
}

Referenz


1

Versuchen Sie dies für Kotlin. Fügen Sie Regex hinzu und fügen Sie der when-Anweisung hinzu.

private fun getCardType(number: String): String {

        val visa = Regex("^4[0-9]{12}(?:[0-9]{3})?$")
        val mastercard = Regex("^5[1-5][0-9]{14}$")
        val amx = Regex("^3[47][0-9]{13}$")

        return when {
            visa.matches(number) -> "Visa"
            mastercard.matches(number) -> "Mastercard"
            amx.matches(number) -> "American Express"
            else -> "Unknown"
        }
    }

0

Die Regeln für reguläre Ausdrücke, die den jeweiligen Kartenanbietern entsprechen :

  • (4\d{12}(?:\d{3})?) für VISA.
  • (5[1-5]\d{14}) für MasterCard.
  • (3[47]\d{13}) für AMEX.
  • ((?:5020|5038|6304|6579|6761)\d{12}(?:\d\d)?) für Maestro.
  • (3(?:0[0-5]|[68][0-9])[0-9]{11}) für Diners Club.
  • (6(?:011|5[0-9]{2})[0-9]{12}) zum Entdecken.
  • (35[2-8][89]\d\d\d{10}) für JCB.

Ich denke, dass Regex für JCB falsch ist. Alle ersten vier Ziffern zwischen 3528 und 3589 sollten akzeptiert werden, 3570 jedoch nicht.
Gabe

0

Ich verwende https://github.com/bendrucker/creditcards-types/ , um den Kreditkartentyp anhand der Nummer zu ermitteln. Ein Problem, auf das ich gestoßen bin, ist die Ermittlung der Testnummer 6011 1111 1111 1117

Unter https://www.cybersource.com/developers/other_resources/quick_references/test_cc_numbers/ können wir sehen, dass es sich um eine Entdeckungsnummer handelt, da sie mit 6011 beginnt. Aber das Ergebnis, das ich von den Kreditkartentypen erhalte, ist "Maestro". Ich habe die Ausgabe für den Autor geöffnet. Er antwortete mir sehr bald und stellte dieses PDF-Dokument zur Verfügung: https://www.discovernetwork.com/downloads/IPP_VAR_Compliance.pdf Aus dem Dokument geht klar hervor, dass 6011 1111 1111 1117 nicht in den Bereich der Entdeckungskreditkarte fällt.


Ich habe das gleiche Problem, hast du das behoben?
lucasvm1980

@ lucasvm1980 Ich denke, die PDF-Datei removenetwork.com ist zuverlässiger. Und die Nummer 6011 1111 1111 1117 ist nur eine Testnummer, keine echte Kreditkarte hat diese Nummer. Ich denke, ich brauche mir darüber keine Sorgen zu machen.
Yuxiaomin

Es sieht so aus, als ob es einen Fehler mit einer Discover-Karte gibt. Ich habe eine gültige Nummer ausprobiert und erhalte auch diesen Fehler.
Lucasvm1980

@ lucasvm1980 kannst du die nummer angeben und ein problem auf github einreichen?
Yuxiaomin

0

Versuchen Sie dies. Für schnell.

func checkCardValidation(number : String) -> Bool
{
    let reversedInts = number.characters.reversed().map { Int(String($0)) }
        return reversedInts.enumerated().reduce(0, {(sum, val) in
            let odd = val.offset % 2 == 1
            return sum + (odd ? (val.element! == 9 ? 9 : (val.element! * 2) % 9) : val.element!)
        }) % 10 == 0
}

Verwenden.

if (self.checkCardValidation(number: "yourNumber") == true) {
     print("Card Number valid")
}else{
     print("Card Number not valid")
}

0
follow Luhn’s algorithm

 private  boolean validateCreditCardNumber(String str) {

        int[] ints = new int[str.length()];
        for (int i = 0; i < str.length(); i++) {
            ints[i] = Integer.parseInt(str.substring(i, i + 1));
        }
        for (int i = ints.length - 2; i >= 0; i = i - 2) {
            int j = ints[i];
            j = j * 2;
            if (j > 9) {
                j = j % 10 + 1;
            }
            ints[i] = j;
        }
        int sum = 0;
        for (int i = 0; i < ints.length; i++) {
            sum += ints[i];
        }
        if (sum % 10 == 0) {
           return true;
        } else {
            return false;
        }


    }

then call this method

Edittext mCreditCardNumberEt;

 mCreditCardNumberEt.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

             int cardcount=   s.toString().length();
                 if(cardcount>=16) {
                    boolean cardnumbervalid=   validateCreditCardNumber(s.toString());
                    if(cardnumbervalid) {
                        cardvalidtesting.setText("Valid Card");
                        cardvalidtesting.setTextColor(ContextCompat.getColor(context,R.color.green));
                    }
                    else {
                        cardvalidtesting.setText("Invalid Card");
                        cardvalidtesting.setTextColor(ContextCompat.getColor(context,R.color.red));
                    }
                }
               else if(cardcount>0 &&cardcount<16) {
                     cardvalidtesting.setText("Invalid Card");
                     cardvalidtesting.setTextColor(ContextCompat.getColor(context,R.color.red));
                }

                else {
                    cardvalidtesting.setText("");

                }


                }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.