Comment détectez-vous le type de carte de crédit en fonction du numéro?

516

J'essaie de comprendre comment détecter le type de carte de crédit uniquement en fonction de son numéro. Quelqu'un connaît-il un moyen définitif et fiable de le trouver?

Andrew Edvalson
la source
3
Utiliser une expression régulière. Consultez ce lien pour plus d'informations.
senfo
3
Les détails sont tous sur Wikipedia: en.wikipedia.org/wiki/Credit_card_numbers
Sten Vesterli
1
Il y a un bon tableau récapitulatif sur Wikipedia, à en.wikipedia.org/wiki/Credit_card_numbers . C'est le premier à six chiffres qui indiquent le type et l'émetteur de la carte.
Alex
3
Je n'utiliserais pas d'expression régulière autre que pour extraire le premier groupe numérique, vous pouvez généralement le dire uniquement à partir des 4 premiers chiffres (aux États-Unis). Avant de prendre la peine de payer pour effacer une charge, exécutez une somme de contrôle Mod 10 sur le numéro de carte pour vous assurer qu'il pourrait être légitime. Algorithme de Luhn
Dan Blair
3
quelqu'un peut-il également dire si ces algorithmes sont bons 'pour toujours' - ou changent-ils périodiquement, comme par exemple l'algorithme pour 'calculer si un numéro de téléphone est en californie'
Simon_Weaver

Réponses:

772

Le numéro de carte de crédit / débit est appelé PAN ou numéro de compte principal . Les six premiers chiffres du PAN proviennent de l' IIN , ou numéro d'identification de l'émetteur , appartenant à la banque émettrice (les IIN étaient auparavant connus sous le nom de BIN - Bank Identification Numbers - de sorte que vous pouvez voir des références à cette terminologie dans certains documents). Ces six chiffres sont soumis à une norme internationale, ISO / IEC 7812 , et peuvent être utilisés pour déterminer le type de carte à partir du numéro.

Malheureusement, la base de données ISO / IEC 7812 n'est pas accessible au public, mais il existe des listes non officielles, à la fois commerciales et gratuites, y compris sur Wikipédia .

Quoi qu'il en soit, pour détecter le type à partir du nombre, vous pouvez utiliser une expression régulière comme celles ci-dessous: Crédit pour les expressions originales

Visa: ^4[0-9]{6,}$ les numéros de carte Visa commencent par un 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,}$ Avant 2016, les numéros MasterCard commencent par les numéros 51 à 55, mais cela ne détectera que les cartes de crédit MasterCard ; il existe d'autres cartes émises à l'aide du système MasterCard qui ne tombent pas dans cette plage IIN. En 2016, ils ajouteront des nombres dans la plage (222100-272099).

American Express: ^3[47][0-9]{5,}$ les numéros de carte American Express commencent par 34 ou 37.

Diners Club: ^3(?:0[0-5]|[68][0-9])[0-9]{4,}$ les numéros de carte Diners Club commencent par 300 à 305, 36 ou 38. Il existe des cartes Diners Club qui commencent par 5 et ont 16 chiffres. Il s'agit d'une joint-venture entre Diners Club et MasterCard et doit être traitée comme une MasterCard.

Découvrir: ^6(?:011|5[0-9]{2})[0-9]{3,}$ les numéros de carte Découvrir commencent par 6011 ou 65.

JCB: les ^(?:2131|1800|35[0-9]{3})[0-9]{3,}$ cartes JCB commencent par 2131, 1800 ou 35.

Malheureusement, il existe un certain nombre de types de cartes traitées avec le système MasterCard qui ne vivent pas dans la plage IIN de MasterCard (nombres commençant de 51 à 55); le cas le plus important est celui des cartes Maestro, dont beaucoup ont été émises à partir des plages IIN d'autres banques et sont donc situées partout dans l'espace numérique. En conséquence, il peut être préférable de supposer que toute carte qui n'est pas d'un autre type que vous acceptez doit être une MasterCard .

Important : la longueur des numéros de carte varie; par exemple, Visa a par le passé émis des cartes avec des PAN à 13 chiffres et des cartes avec des PAN à 16 chiffres. La documentation de Visa indique actuellement qu'elle peut émettre ou peut avoir émis des numéros comprenant entre 12 et 19 chiffres. Par conséquent, vous ne devez pas vérifier la longueur du numéro de carte, sauf pour vérifier qu'il a au moins 7 chiffres (pour un IIN complet plus un chiffre de contrôle, qui doit correspondre à la valeur prédite par l'algorithme de Luhn ).

Un autre conseil: avant de traiter un PAN de titulaire de carte, supprimez les espaces et les caractères de ponctuation de l'entrée . Pourquoi? Parce qu'il est généralement beaucoup plus facile de saisir les chiffres en groupes, de la même façon qu'ils sont affichés au recto d'une véritable carte de crédit, c'est-à-dire

4444 4444 4444 4444

est beaucoup plus facile à saisir correctement que

4444444444444444

Il n'y a vraiment aucun avantage à châtier l'utilisateur car il a entré des caractères auxquels vous ne vous attendez pas ici.

Cela implique également de s'assurer que vos champs de saisie ont de la place pour au moins 24 caractères, sinon les utilisateurs qui entreront des espaces manqueront de place. Je vous recommande de rendre le champ suffisamment large pour afficher 32 caractères et autoriser jusqu'à 64; cela donne beaucoup de marge pour l'expansion.

Voici une image qui donne un peu plus d'informations:

MISE À JOUR (2014): La méthode de la somme de contrôle ne semble plus être un moyen valide de vérifier l'authenticité d'une carte, comme indiqué dans les commentaires sur cette réponse.

MISE À JOUR (2016): Mastercard va implémenter de nouvelles gammes BIN à partir d' Ach Payment .

Vérification de carte de crédit

senfo
la source
7
bon exemple. avez-vous l'expression régulière pour les cartes maestro?
Manikandan
4
Non non Non. Vous ne pouvez pas vous fier à la longueur des numéros de carte; ils peuvent changer à tout moment. La seule partie du numéro de carte sur laquelle vous pouvez compter est l'IIN (qui s'appelait autrefois un BIN) et qui est un préfixe du numéro. De plus, vous ne pouvez pas détecter les cartes Mastercard de la manière que vous suggérez; cela ne ramassera qu'un sous-ensemble des cartes traitées via le système Mastercard (le problème principal étant les cartes Maestro, qui ont une variété de préfixes IIN).
alastair
2
@alastair avez-vous lu les expressions avant de commenter? Ils ont été écrits spécifiquement pour utiliser l'IIN, donc je ne comprends pas ce que vous essayez de dire. De plus, l'IIN peut être utilisé pour identifier l'émetteur de la carte, mais pas pour valider. 5412, par exemple, ne représente pas une MasterCard complète, mais votre suggestion impliquerait que oui. Je n'ai trouvé aucune preuve que les MasterCards sont tout sauf 16 chiffres. N'hésitez pas à fournir une source pour votre réclamation. Cependant, vous avez raison de mentionner qu'une mise à jour doit être effectuée pour les cartes Maestro.
senfo
3
@senfo Vous avez raison, 5412 ne serait pas un numéro Mastercard complet. Les IIN comportent six chiffres, donc un numéro de carte complet doit être composé de 7 chiffres (minimum) et doit passer le contrôle Luhn. Il n'est pas nécessaire de «prouver» que les numéros Mastercard ont autre chose que 16 chiffres; le fait est que, quelle que soit la situation actuelle, à l'avenir, ils pourraient émettre des cartes à 17 ou 18 chiffres, ou d'ailleurs avec 15. Il n'est pas nécessaire de compter sur 16 chiffres et crée un risque de maintenance à long terme.
alastair
3
Je trouve très difficile de croire que certaines cartes valides n'auraient pas un chiffre de contrôle correct selon l'algorithme de Luhn. Il l'utilisait absolument partout pour vérifier les numéros de carte contre les simples fautes de frappe et les tentatives de fraude stupides. Au lieu de cela, j'ai observé que certaines personnes assez intelligentes ne saisissaient tout simplement pas l'algorithme et le calculaient simplement mal.
Rennex
74

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

Test de l'unité:

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]);
            });
        });
    });
});
Anatoliy
la source
1
@ jolly.exe - Votre violon renvoie undefined pour tous les tests. Ne fonctionne pas :(
ShadeTreeDeveloper
@ShadeTreeDeveloper entrez simplement n'importe quelle valeur, par exemple. 372176090165471 pour AMAX dans le champ de texte
Code Spy
@ jolly.exe Je vois ... J'espérais quelque chose qui formaterait pendant que je tape (hors de l'événement keyup). Le violon fonctionne quand j'entre un nombre complet.
ShadeTreeDeveloper
J'ai fini par écrire ce morceau de code pour faire le formatage et la validation d'entrée que je voulais. quercusv.github.io/smartForm
ShadeTreeDeveloper
savez-vous comment détecter les numéros de carte v-pay et bancontact? Merci
Oleksandr IY
38

Mise à jour: 15 juin 2016 (comme solution ultime actuellement)

Veuillez noter que j'abandonne même le vote pour celui qui est le mieux voté, mais pour être clair, ce sont les regexps qui fonctionnent, je l'ai testé avec des milliers de vrais codes BIN. Le plus important est d'utiliser des chaînes de début (^) sinon cela donnera de faux résultats dans le monde réel!

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

American Express ^3[47][0-9]{0,}$ Commencez avec: 34, 37

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

Visa ^4[0-9]{0,}$ Commence par: 4

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

Maestro ^(5[06789]|6)[0-9]{0,}$ Maestro grandit toujours dans la gamme: 60-69 , a commencé avec / pas autre chose, mais le début de 5 doit quand même être encodé en mastercard. Les cartes Maestro doivent être détectées à la fin du code car certaines autres ont entre 60 et 69. Veuillez regarder le code.

Découvrir ^(6011|65|64[4-9]|62212[6-9]|6221[3-9]|622[2-8]|6229[01]|62292[0-5])[0-9]{0,}$ Découvrez assez difficile à coder, commencez par: 6011, 622126-622925, 644-649, 65

En javascript j'utilise cette fonction. C'est bien quand vous l'attribuez à un événement onkeyup et cela donne un résultat dès que possible.

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

Ici, vous pouvez jouer avec:

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

Pour PHP, utilisez cette fonction, cela détecte également certaines sous-cartes VISA / MC:

/**
  * 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
}
Janos Szabo
la source
1
Et veuillez noter que ce n'est que la détection du numéro CC et non la validation. C'est séparé, devrait être un chèque Luhn ...
Janos Szabo
Où se trouve Visa Electron et pourquoi le chèque Maestro retourne-t-il MasterCard dans certains cas? La MasterCard ne devrait-elle pas vérifier cela elle-même?
BadHorsie
Il ne reconnaît pas ce numéro de test JCB comme l'un des types (3088514174175777) et identifie ce numéro de test JCB comme diners_club (3096278649822922). En supposant que cette liste de numéros de carte de test soit valide de toute façon ( freeformatter.com/credit-card-number-generator-validator.html )
Drew
il n'y a aucune documentation que le démarrage de 308 ou 309 pourrait être une carte JCB
Janos Szabo
+1 pour fournir le code de détection de type cc, ce que vous voulez généralement faire pour l'ux - l'expression régulière pour la nouvelle gamme sur MC nécessite un petit tweek: / ^ (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";
}

Voici la fonction pour vérifier le type de carte de crédit à l'aide de Regex, c #

Usman Younas
la source
19

Regarde ça:

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;
}
Rashy
la source
15

récemment, j'avais besoin d'une telle fonctionnalité, je portais le validateur de carte de crédit Zend Framework sur ruby. ruby gem: https://github.com/Fivell/credit_card_validations zend framework: https://github.com/zendframework/zf2/blob/master/library/Zend/Validator/CreditCard.php

Ils utilisent tous les deux des plages INN pour détecter le type. Ici vous pouvez lire sur INN

Selon cela, vous pouvez également détecter la carte de crédit (sans regexps, mais en déclarant certaines règles sur les préfixes et la longueur possible)

Nous avons donc les prochaines règles pour les cartes les plus utilisées

########  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}
    ]

}

Ensuite, en recherchant le préfixe et en comparant la longueur, vous pouvez détecter la marque de carte de crédit. N'oubliez pas non plus de Luhn Algoritm (il est décrit ici http://en.wikipedia.org/wiki/Luhn ).

MISE À JOUR

la liste mise à jour des règles peut être trouvée ici https://raw.githubusercontent.com/Fivell/credit_card_validations/master/lib/data/brands.yaml

Fivell
la source
2
Très illustratif. Les cartes VISA peuvent comporter 13 chiffres.
Herman Kan
@HermanKan, aucun site Web VISA ne dit qu'il devrait avoir une longueur de 16, je pense qu'il y a longtemps, il pourrait être de 13, mais pas de nos jours
Fivell
1
Je pense que c'est un support hérité
Fivell
1
@HermanKan, il y a encore une chose, VISA a des cartes VPay et s'accrédite à wikipedia La marque VPay de Visa peut spécifier des longueurs PAN de 13 à 19 chiffres afin qu'un numéro de carte de plus de 16 chiffres soit maintenant visible.
Fivell
1
@Ethan, vérifiez le dernier lien dans ma réponse mise à jour raw.githubusercontent.com/Fivell/credit_card_validations/master/…
Fivell
13

Voici le code C # ou VB complet pour toutes sortes de choses liées à CC sur codeproject.

  • IsValidNumber
  • GetCardTypeFromNumber
  • GetCardTestNumber
  • PassesLuhnTest

Cet article est disponible depuis quelques années sans commentaires négatifs.

Simon_Weaver
la source
1
@barett - l'a corrigé. on dirait qu'ils l'ont déplacé de la catégorie 'aspnet' à la catégorie 'validation' qui a changé le lien
Simon_Weaver
2
Le lien est rompu. C'est peut-être le même utilitaire? codeproject.com/Articles/20271/…
Josh Noe
Ce code de projet de code date de 2007. Attention, il peut être obsolète.
aron
8

Version javascript compacte

    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;
            }
        }
    };
pseudo
la source
8

Réponse d'Anatoliy en 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;
    }
 }
angelcool.net
la source
7

Voici une fonction de classe php qui renvoie CCtype par CCnumber.
Ce code ne valide pas la carte ou n'exécute pas l'algorithme de Luhn, essayez uniquement de trouver le type de carte de crédit en fonction du tableau de cette page . utilise fondamentalement la longueur CCnumber et le préfixe CCcard pour déterminer le type de carte CC.

<?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;
    }
}
ismail
la source
6

N'essayez pas de détecter le type de carte de crédit dans le cadre du traitement d'un paiement. Vous risquez de refuser des transactions valides.

Si vous devez fournir des informations à votre processeur de paiement (par exemple, l'objet de carte de crédit PayPal nécessite de nommer le type de carte ), alors devinez-le à partir du moins d'informations disponibles, par exemple

$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.');
}

Cette implémentation (en utilisant uniquement les deux premiers chiffres) est suffisante pour identifier tous les principaux schémas de cartes (et dans le cas de PayPal tous les) pris en charge. En fait, vous voudrez peut-être ignorer complètement l'exception et choisir par défaut le type de carte le plus populaire. Laissez la passerelle / le processeur de paiement vous dire s'il y a une erreur de validation en réponse à votre demande.

La réalité est que votre passerelle de paiement ne se soucie pas de la valeur que vous fournissez .

Gajus
la source
1
C'est tout simplement faux. Je connais 3 fournisseurs différents qui exigent que les types de cartes soient transmis, et si vous ne le transmettez pas, la transaction échouera.
Ed DeGagne
3
@EdDeGagne - "ne se soucie pas de la valeur" n'est pas la même chose que "ne se soucie pas s'il est transmis".
Quentin Skousen
Où ai-je précisé non plus? J'ai simplement mentionné qu'il existe des fournisseurs en service qui vous obligent à passer le type CC, rien de plus.
Ed DeGagne
vous ne pouvez pas simplifier ce problème complexe, mais généralement les fournisseurs de paiement ne vous demandent pas de suggérer le type de carte, ils ont leur propre méthode pour détecter
Janos Szabo
6

Les premiers chiffres de la carte de crédit peuvent être utilisés pour rapprocher le vendeur:

  • Visa: 49,44 ou 47
  • Visa électronique: 42, 45, 48, 49
  • MasterCard: 51
  • Amex: 34
  • Diners: 30, 36, 38
  • JCB: 35
Shoban
la source
Ces gammes ont été largement mises à jour, les sociétés de fournisseurs de cartes ont ajouté bien plus de gammes que celles mentionnées dans la publication.
NJInamdar
6

Dans Card Range Recognition (CRR), un inconvénient des algorithmes qui utilisent une série d'expressions régulières ou d'autres plages codées en dur, est que les BIN / IIN changent au fil du temps selon mon expérience. Le co-marquage des cartes est une complication permanente. Différents acquéreurs / marchands de cartes peuvent avoir besoin que vous traitiez la même carte différemment, en fonction, par exemple, de la géolocalisation.

De plus, au cours des dernières années, avec par exemple des cartes UnionPay en circulation plus large, les modèles existants ne font pas face à de nouvelles gammes qui s'entrelacent parfois avec des gammes plus larges qu'elles remplacent.
La connaissance de la géographie que votre système doit couvrir peut être utile, car certaines plages sont limitées à l'utilisation dans certains pays. Par exemple, les gammes 62 incluent certaines sous-gammes AAA aux États-Unis, mais si votre base de marchands est en dehors des États-Unis, vous pourrez peut-être traiter tous les 62 comme UnionPay.
Vous pouvez également être invité à traiter une carte différemment en fonction de l'emplacement du commerçant. Par exemple, pour traiter certaines cartes britanniques comme un débit national, mais comme un crédit international.

Il existe un ensemble très utile de règles maintenues par une grande banque acquéreuse. Par exemple, https://www.barclaycard.co.uk/business/files/BIN-Rules-EIRE.pdf et https://www.barclaycard.co.uk/business/files/BIN-Rules-UK.pdf . (Liens valides à partir de juin 2017, grâce à l'utilisateur qui a fourni un lien vers une référence mise à jour.) Mais sachez que si ces règles CRR peuvent représenter l'univers d'émission de cartes tel qu'il s'applique aux marchands acquis par cette entité, il n'inclut pas par exemple les plages identifiées comme CUP / UPI.

Ces commentaires s'appliquent aux scénarios de bande magnétique (MagStripe) ou PKE (Pan Key Entry). La situation est à nouveau différente dans le monde ICC / EMV.

Mise à jour: Les autres réponses sur cette page (et aussi la page WikiPedia liée) ont JCB comme toujours 16 longues. Cependant, dans mon entreprise, nous avons une équipe dédiée d'ingénieurs qui certifient nos dispositifs de point de vente et nos logiciels dans plusieurs banques et zones géographiques d'acquisition. Le plus récent pack de cartes de certification que JCB a reçu de cette équipe avait un étui pour un PAN de 19 longs.

MikeRoger
la source
Salut @CaiqueOliveira, voir les liens mis à jour. Merci à mac9416 qui a fourni un lien vers la référence mise à jour des règles BIN.
MikeRoger
1
Merci @ mac9416, pour la référence mise à jour des règles BIN.
MikeRoger
5

Version Swift 2.1 de la réponse d'Usman Y. Utilisez une instruction print pour vérifier, appelez par une valeur de chaîne

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

}
Daisy R.
la source
4

Stripe a fourni cette fantastique bibliothèque javascript pour la détection de schémas de cartes. Permettez-moi d'ajouter quelques extraits de code et de vous montrer comment l'utiliser.

Incluez-le d'abord sur votre page Web

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

Deuxièmement, utilisez la fonction cardType pour détecter le schéma de carte.

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

Voici les liens de référence pour plus d'exemples et de démos.

  1. Blog Stripe pour jquery.payment.js
  2. Dépôt Github
NJInamdar
la source
4

Dans swift, vous pouvez créer une énumération pour détecter le type de carte de crédit.

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

Appelez la méthode CreditCardType.cardTypeForCreditCardNumber ("# numéro de carte") qui renvoie la valeur énumérée CreditCardType.

Vidyalaxmi
la source
3

Ma solution avec 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;
}

Si 0 est retourné, le type de carte de crédit n'est pas détecté.

La classe "carte de crédit" doit être ajoutée au champ de saisie de la carte de crédit.

ZurabWeb
la source
1
Variation des réponses existantes.
Gajus
1
Oui, j'ai utilisé le code des réponses ci-dessus, je l'ai AMÉLIORÉ et je l'ai affiché ici. Merci pour le
vote négatif
3
Vous auriez dû (a) suggérer cela comme une amélioration du code existant, (b) écrire les contributions appropriées, ou (c) référencer les sources que vous avez utilisées pour écrire les expressions régulières.
Gajus
1
Gajus, je crois que j'ai aidé la communauté comme je le pouvais à ce moment-là, s'il te plait arrête de me dire que j'aurais dû faire quelque chose pour quelqu'un. J'ai fait ce que je pensais avoir pu être utile.
ZurabWeb du
3

J'ai cherché un peu le formatage des cartes de crédit et le formatage des numéros de téléphone. J'ai trouvé plein de bons conseils, mais rien ne convenait vraiment à mes désirs, j'ai donc créé ce bout de code . Vous l'utilisez comme ceci:

var sf = smartForm.formatCC(myInputString);
var cardType = sf.cardType;
ShadeTreeDeveloper
la source
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
       },
Parvez
la source
La question concerne l' algorithme de vérification d'une carte de crédit, et non une implémentation spécifique. Que fait ce code?
Emil Vikström
2

Juste une petite cuillère à nourrir:

$("#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");

        }

    });
Pincer
la source
2

Voici un exemple de certaines fonctions booléennes écrites en Python qui retournent Truesi la carte est détectée selon le nom de la fonction.

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
radtek
la source
1

Les six premiers chiffres d'un numéro de carte (y compris le chiffre MII initial) sont appelés numéro d'identification de l' émetteur (IIN). Ceux-ci identifient l'institution émettrice de la carte qui a délivré la carte au titulaire de la carte. Le reste du numéro est attribué par l'émetteur de la carte. La longueur du numéro de carte est son nombre de chiffres. De nombreux émetteurs de cartes impriment l'intégralité de l'IIN et du numéro de compte sur leur carte.

Sur la base des faits ci-dessus, je voudrais conserver un extrait de code JAVA pour identifier la marque de la carte.

Exemples de types de cartes

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

Préfixes de carte

// 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"
    };

Vérifiez si le numéro d'entrée a l'un des préfixes donnés.

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

Enfin, la méthode Utility

/**
  * 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;
}

Référence

Anoop M
la source
1

Essayez ceci pour kotlin. Ajoutez Regex et ajoutez à l'instruction when.

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"
        }
    }
OhhhThatVarun
la source
0

Les règles d'expression régulière qui correspondent aux fournisseurs de cartes respectifs :

  • (4\d{12}(?:\d{3})?) pour VISA.
  • (5[1-5]\d{14}) pour MasterCard.
  • (3[47]\d{13}) pour AMEX.
  • ((?:5020|5038|6304|6579|6761)\d{12}(?:\d\d)?) pour Maestro.
  • (3(?:0[0-5]|[68][0-9])[0-9]{11}) pour Diners Club.
  • (6(?:011|5[0-9]{2})[0-9]{12}) pour Découvrir.
  • (35[2-8][89]\d\d\d{10}) pour JCB.
Rajan
la source
Je pense que l'expression régulière pour JCB est incorrecte. Les quatre premiers chiffres compris entre 3528 et 3589 doivent être acceptés, mais 3570 ne l'est pas, par exemple.
Gabe
0

J'utilise https://github.com/bendrucker/creditcards-types/ pour détecter le type de carte de crédit à partir du numéro. Un problème que j'ai rencontré est de découvrir le numéro de test 6011 1111 1111 1117

à partir de https://www.cybersource.com/developers/other_resources/quick_references/test_cc_numbers/ nous pouvons voir que c'est un numéro de découverte car il commence par 6011. Mais le résultat que j'obtiens des types de cartes de crédit est "Maestro". J'ai ouvert le dossier à l'auteur. Il m'a répondu très rapidement et fournit ce doc pdf https://www.discovernetwork.com/downloads/IPP_VAR_Compliance.pdf D'après le doc, nous pouvons voir clairement que 6011 1111 1111 1117 ne fait pas partie de la gamme des cartes de crédit Discover.

yuxiaomin
la source
J'ai le même problème, avez-vous résolu ce problème?
lucasvm1980
@ lucasvm1980 Je pense que le fichier pdf discovernetwork.com est plus fiable. Et le numéro 6011 1111 1111 1117 n'est qu'un numéro de test, aucune vraie carte de crédit n'a ce numéro. Je pense donc que pas besoin de s'inquiéter à ce sujet.
yuxiaomin
Il semble qu'il y ait un bug avec une carte Discover, j'ai essayé un numéro valide et j'obtiens également cette erreur.
lucasvm1980
@ lucasvm1980 pouvez-vous fournir le numéro et soumettre un problème sur github?
yuxiaomin
0

Essayez ceci. Pour rapide.

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
}

Utilisation.

if (self.checkCardValidation(number: "yourNumber") == true) {
     print("Card Number valid")
}else{
     print("Card Number not valid")
}
Dixit Akabari
la source
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) {

            }
        });
gaurav gupta
la source