Come si rileva il tipo di carta di credito in base al numero?


516

Sto cercando di capire come rilevare il tipo di carta di credito basato esclusivamente sul suo numero. Qualcuno conosce un modo definitivo e affidabile per trovarlo?


3
Usando un'espressione regolare. Dai un'occhiata a questo link per ulteriori informazioni.
senfo,

3
I dettagli sono tutti su Wikipedia: en.wikipedia.org/wiki/Credit_card_numbers
Sten Vesterli

1
C'è una buona tabella riassuntiva in Wikipedia, su en.wikipedia.org/wiki/Credit_card_numbers . Sono le prime da una a sei cifre che indicano il tipo e l'emittente della carta.
Alex,

3
Non userei una regex se non quella di estrarre il primo gruppo numerico, in genere si può dire solo dai primi 4 numeri (negli Stati Uniti). Inoltre, prima di preoccuparsi di pagare per compensare un addebito, eseguire un checksum Mod 10 sul numero della carta per assicurarsi che possa essere legittimo. Algoritmo Luhn
Dan Blair,

3
chiunque può anche commentare se questi algoritmi sono validi "per sempre" o cambiano periodicamente, come ad esempio l'algoritmo per "calcolare se un numero di telefono è in California"
Simon_Weaver

Risposte:


772

Il numero della carta di credito / debito è indicato come PAN , o numero di conto primario . Le prime sei cifre del PAN sono prese dallo IIN , o Numero di identificazione dell'emittente , appartenente alla banca emittente (gli IIN erano precedentemente noti come BIN - Numeri di identificazione della banca - quindi in alcuni documenti è possibile vedere riferimenti a tale terminologia). Queste sei cifre sono soggette a uno standard internazionale, ISO / IEC 7812 , e possono essere utilizzate per determinare il tipo di carta dal numero.

Purtroppo l'attuale database ISO / IEC 7812 non è pubblicamente disponibile, tuttavia ci sono elenchi non ufficiali, sia commerciali che gratuiti, anche su Wikipedia .

Ad ogni modo, per rilevare il tipo dal numero, puoi usare un'espressione regolare come quelle qui sotto: credito per le espressioni originali

Visa: ^4[0-9]{6,}$ i numeri delle carte Visa iniziano con 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,}$ prima del 2016, i numeri MasterCard iniziano con i numeri da 51 a 55, ma questo rileverà solo le carte di credito MasterCard ; ci sono altre carte emesse utilizzando il sistema MasterCard che non rientrano in questo intervallo IIN. Nel 2016, aggiungeranno numeri nell'intervallo (222100-272099).

American Express: ^3[47][0-9]{5,}$ i numeri delle carte American Express iniziano con 34 o 37.

Diners Club: ^3(?:0[0-5]|[68][0-9])[0-9]{4,}$ i numeri delle carte Diners Club iniziano da 300 a 305, 36 o 38. Ci sono carte Diners Club che iniziano con 5 e hanno 16 cifre. Si tratta di una joint venture tra Diners Club e MasterCard e devono essere elaborate come una MasterCard.

Scopri: ^6(?:011|5[0-9]{2})[0-9]{3,}$ i numeri delle carte scoperte iniziano con 6011 o 65.

JCB: le ^(?:2131|1800|35[0-9]{3})[0-9]{3,}$ carte JCB iniziano con 2131, 1800 o 35.

Sfortunatamente, ci sono un certo numero di tipi di carte elaborati con il sistema MasterCard che non vivono nell'intervallo IIN di MasterCard (numeri che iniziano 51 ... 55); il caso più importante è quello delle carte Maestro, molte delle quali sono state emesse dalle gamme IIN di altre banche e quindi si trovano in tutto lo spazio numerico. Di conseguenza, potrebbe essere meglio supporre che qualsiasi carta che non sia di un altro tipo accettato sia una MasterCard .

Importante : i numeri delle carte variano in lunghezza; ad esempio, Visa ha in passato emesso carte con PAN a 13 cifre e carte con PAN a 16 cifre. La documentazione di Visa indica attualmente che potrebbe emettere o che potrebbe aver emesso numeri tra 12 e 19 cifre. Pertanto, non dovresti controllare la lunghezza del numero della carta, se non per verificare che abbia almeno 7 cifre (per un IIN completo più una cifra di controllo, che dovrebbe corrispondere al valore previsto dall'algoritmo Luhn ).

Un ulteriore suggerimento: prima di elaborare un PAN del titolare della carta, rimuovere eventuali spazi bianchi e segni di punteggiatura dall'input . Perché? Perché in genere è molto più facile inserire le cifre in gruppi, in modo simile a come sono visualizzate sulla parte anteriore di una carta di credito reale, ad es

4444 4444 4444 4444

è molto più facile inserire correttamente di

4444444444444444

Non c'è davvero alcun vantaggio nel castigare l'utente perché hanno inserito caratteri che non ti aspetti qui.

Ciò implica anche assicurarsi che i campi di immissione abbiano spazio per almeno 24 caratteri, altrimenti gli utenti che entrano negli spazi rimarranno a corto di spazio. Ti consiglierei di allargare il campo abbastanza da visualizzare 32 caratteri e consentirne fino a 64; che offre molto spazio per l'espansione.

Ecco un'immagine che fornisce un po 'più di comprensione:

AGGIORNAMENTO (2014): il metodo di checksum non sembra più essere un modo valido per verificare l'autenticità di una carta, come indicato nei commenti su questa risposta.

AGGIORNAMENTO (2016): Mastercard implementerà nuove gamme BIN a partire da Ach Payment .

Verifica della carta di credito


7
ottimo esempio. hai l'espressione regolare per le carte maestro?
Manikandan,

4
NO, no, no. Non puoi fare affidamento sulla lunghezza dei numeri delle carte; possono cambiare in qualsiasi momento. L'unica parte del numero di carta su cui puoi fare affidamento è l'IIN (che un tempo si chiamava BIN) e che è un prefisso del numero. Inoltre, non è possibile rilevare le carte Mastercard nel modo suggerito; che raccoglierà solo un sottoinsieme delle carte che vengono elaborate tramite il sistema Mastercard (il problema principale sono le carte Maestro, che hanno una varietà di prefissi IIN).
alastair,

2
@alastair hai letto le espressioni prima di commentare? Sono stati scritti appositamente per usare l'IIN, quindi non capisco cosa stai cercando di dire. Inoltre, l'IIN può essere utilizzato per identificare l'emittente della carta, ma non convalidarlo. 5412, ad esempio, non rappresenta una MasterCard completa, ma il tuo suggerimento implicherebbe che lo sia. Non ho trovato alcuna prova che le MasterCard siano altro che 16 cifre. Non esitate a fornire una fonte per il vostro reclamo. Hai ragione nel dire che è necessario effettuare un aggiornamento per le carte Maestro.
senfo,

3
@senfo Hai ragione, 5412 non sarebbe un numero Mastercard completo. Le IIN sono lunghe sei cifre, quindi un numero di carta completo deve essere di 7 cifre (minimo) e deve superare il controllo Luhn. Non c'è bisogno di "prova" che i numeri di Mastercard abbiano qualcosa di diverso da 16 cifre; il punto è che, indipendentemente dalla situazione odierna, in futuro potrebbero emettere carte con 17 o 18 cifre, o del resto alcune con 15. Basandosi su di esse lunghe 16 cifre non è necessario e crea un rischio di manutenzione a lungo termine.
alastair,

3
Trovo molto difficile credere che alcune carte valide non abbiano una cifra di controllo corretta secondo l'algoritmo Luhn. Ha usato assolutamente ovunque per controllare i numeri delle carte contro semplici errori di battitura e stupidi tentativi di frode. Invece, ho osservato che alcune persone piuttosto intelligenti semplicemente non capiscono l'algoritmo e lo calcolano semplicemente in modo errato.
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
        }
    }
}

Test unitario:

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 - Il violino ritorna indefinito per tutti i test. Non funziona :(
ShadeTreeDeveloper

@ShadeTreeDeveloper basta inserire qualsiasi valore ad es. 372176090165471 per AMAX nel campo di testo
Codice spia

@ jolly.exe Capisco ... Speravo in qualcosa da formattare durante la digitazione (fuori dall'evento keyup). Il violino funziona quando inserisco un numero completo.
ShadeTreeDeveloper

Ho finito per scrivere questo bit di codice per eseguire la formattazione e la convalida dell'input che desideravo. quercusv.github.io/smartForm
ShadeTreeDeveloper

sai come rilevare i numeri delle carte v-pay e bancontact? Grazie
Oleksandr IY,

38

Aggiornato: 15 giugno 2016 (attualmente come soluzione definitiva)

Si prega di notare che ho anche dato il voto per quello con il voto più alto, ma per chiarire che questi sono i regexps effettivamente funzionanti l'ho testato con migliaia di codici BIN reali. Il più importante è usare le stringhe di inizio (^) altrimenti darà risultati falsi nel mondo reale!

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

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

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

Visto ^4[0-9]{0,}$ Inizia con: 4

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

Maestro ^(5[06789]|6)[0-9]{0,}$ Maestro sempre in crescita nell'intervallo: 60-69 , iniziato con / non qualcos'altro, ma a partire da 5 deve essere comunque codificato come mastercard. Le carte Maestro devono essere rilevate alla fine del codice perché alcune hanno un intervallo compreso tra 60 e 69. Si prega di guardare il codice.

Scopri ^(6011|65|64[4-9]|62212[6-9]|6221[3-9]|622[2-8]|6229[01]|62292[0-5])[0-9]{0,}$ Scopri abbastanza difficile da programmare, inizia con: 6011, 622126-622925, 644-649, 65

In JavaScript utilizzo questa funzione. Questo è utile quando lo si assegna a un evento onkeyup e dà il risultato il prima possibile.

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

Qui puoi giocare con esso:

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

Per PHP utilizzare questa funzione, questo rileva anche alcune schede VISA / MC secondarie:

/**
  * 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
E tieni presente che si tratta solo del rilevamento del numero CC e non della convalida. Questo è separato, dovrebbe essere un controllo di Luhn ...
Janos Szabo,

Dov'è Visa Electron, e perché il controllo Maestro restituisce MasterCard in alcuni casi? La MasterCard non dovrebbe controllarlo?
BadHorsie,

Non riconosce questo numero di test JCB come uno dei tipi (3088514174175777) e identifica questo numero di test JCB come diners_club (3096278649822922). Supponendo che questo elenco di numeri delle carte di prova sia valido comunque ( freeformatter.com/credit-card-number-generator-validator.html )
Estratto il

non ci sono documenti che a partire dal 308 o 309 potrebbero essere una JCB card
Janos Szabo,

+1 per fornire il codice di rilevamento del tipo cc, che è ciò che in genere si desidera fare per l'UX: la regex per la nuova gamma su MC richiede una piccola modifica: / ^ (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";
}

Ecco la funzione per controllare il tipo di carta di credito utilizzando Regex, c #


19

Controllalo:

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

recentemente ho avuto bisogno di tale funzionalità, stavo portando su Ruby il validatore di carte di credito Zend Framework. gemma rubino: https://github.com/Fivell/credit_card_validations zend framework: https://github.com/zendframework/zf2/blob/master/library/Zend/Validator/CreditCard.php

Entrambi utilizzano le gamme INN per rilevare il tipo. Qui puoi leggere di INN

In base a ciò è possibile rilevare la carta di credito in alternativa (senza regexps, ma dichiarando alcune regole sui prefissi e sulla possibile lunghezza)

Quindi abbiamo le prossime regole per le carte più usate

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

}

Quindi, cercando il prefisso e confrontando la lunghezza, è possibile rilevare la marca della carta di credito. Inoltre, non dimenticare di luhn algoritm (è descritto qui http://en.wikipedia.org/wiki/Luhn ).

AGGIORNARE

l'elenco aggiornato delle regole è disponibile qui https://raw.githubusercontent.com/Fivell/credit_card_validations/master/lib/data/brands.yaml


2
Molto illustrativo. Le carte VISA possono essere lunghe 13 cifre.
Herman Kan,

@HermanKan, nessun sito web VISA dice che dovrebbe essere lungo 16, penso che molto tempo fa potrebbe essere 13, ma non oggi
Fivell

1
Penso che sia un supporto legacy
Fivell

1
@HermanKan, c'è un'altra cosa, VISA ha carte VPay e accedendo a wikipedia Il marchio VPay di Visa può specificare lunghezze PAN da 13 a 19 cifre, quindi un numero di carta di oltre 16 cifre è ora visibile.
Fivell,

1
@Ethan, controlla l'ultimo link nella mia risposta aggiornata raw.githubusercontent.com/Fivell/credit_card_validations/master/…
Fivell

13

Ecco il codice C # o VB completo per tutti i tipi di cose relative a CC su codeproject.

  • IsValidNumber
  • GetCardTypeFromNumber
  • GetCardTestNumber
  • PassesLuhnTest

Questo articolo è stato pubblicato per un paio d'anni senza commenti negativi.


1
@barett: risolto il problema. sembra che lo abbiano spostato dalla categoria 'aspnet' alla categoria 'validation' che ha cambiato il link
Simon_Weaver

2
Il collegamento è interrotto. Forse questa è la stessa utilità? codeproject.com/Articles/20271/…
Josh Noe,

Quel codice codeproject è del 2007. Attenzione, potrebbe non essere aggiornato.
Aron,

8

Versione javascript compatta

    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

La risposta di Anatoliy 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

Ecco una funzione di classe php che restituisce CCtype di CCnumber.
Questo codice non convalida la carta o non esegue l'algoritmo Luhn cerca solo di trovare il tipo di carta di credito in base alla tabella in questa pagina . utilizza fondamentalmente lunghezza CCnumber e prefisso CCcard per determinare il tipo di CCcard.

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

Non tentare di rilevare il tipo di carta di credito durante l'elaborazione di un pagamento. Stai rischiando di rifiutare transazioni valide.

Se devi fornire informazioni al tuo processore di pagamento (ad es. L'oggetto della carta di credito PayPal richiede di nominare il tipo di carta ), indovinalo dalla minima informazione disponibile, ad es.

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

Questa implementazione (utilizzando solo le prime due cifre) è sufficiente per identificare tutti i principali (e nel caso di PayPal tutti gli schemi di carte supportati). In effetti, potresti voler saltare del tutto l'eccezione e passare automaticamente al tipo di carta più popolare. Lascia che il gateway / processore di pagamento ti informi se c'è un errore di convalida in risposta alla tua richiesta.

La realtà è che il tuo gateway di pagamento non si preoccupa del valore fornito .


1
Questo è semplicemente falso. Conosco 3 diversi provider che richiedono la trasmissione dei tipi di carta e, se non la passate, la transazione fallirà.
Ed DeGagne,

3
@EdDeGagne - "non importa quale valore" non è lo stesso di "non importa se passato".
Quentin Skousen,

Dove ho specificato uno dei due? Ho semplicemente detto che ci sono provider in uso che richiedono di passare il tipo CC, niente di più.
Ed DeGagne,

non puoi semplificare questo problema complesso, ma di solito i fornitori di servizi di pagamento non richiedono che tu suggerisca il tipo di carta, hanno il loro metodo per rilevare
Janos Szabo,

6

I primi numeri della carta di credito possono essere utilizzati per approssimare il fornitore:

  • Visto: 49,44 o 47
  • Elettrone Visa: 42, 45, 48, 49
  • MasterCard: 51
  • Amex: 34
  • Diners: 30, 36, 38
  • JCB: 35

Queste gamme sono state aggiornate principalmente, le società venditrici di carte hanno aggiunto molte più gamme di quelle menzionate nel post.
NJInamdar,

6

In Card Range Recognition (CRR), uno svantaggio con algoritmi che utilizzano una serie di regex o altri intervalli hardcoded, è che i BIN / IIN cambiano nel tempo nella mia esperienza. Il co-branding delle carte è una complicazione in corso. Acquirenti / commercianti di carte diversi potrebbero aver bisogno di trattare la stessa carta in modo diverso, a seconda, ad esempio, della geolocalizzazione.

Inoltre, negli ultimi anni, ad esempio con le carte UnionPay in circolazione più ampia, i modelli esistenti non sono in grado di far fronte a nuove gamme che a volte si alternano a gamme più ampie che sostituiscono.
Conoscere la geografia che il sistema deve coprire può essere d'aiuto, poiché alcune gamme sono limitate all'uso in determinati paesi. Ad esempio, gli intervalli 62 includono alcuni sotto-intervalli AAA negli Stati Uniti, ma se la tua base commerciale è al di fuori degli Stati Uniti, potresti essere in grado di trattare tutti i 62 come UnionPay.
È possibile che ti venga chiesto di trattare una carta in modo diverso in base alla posizione del commerciante. Ad esempio, per trattare alcune carte del Regno Unito come debito nazionale, ma come credito internazionale.

Esistono serie di regole molto utili gestite da una delle principali banche acquirenti. Ad esempio https://www.barclaycard.co.uk/business/files/BIN-Rules-EIRE.pdf e https://www.barclaycard.co.uk/business/files/BIN-Rules-UK.pdf . (Link validi a partire da giugno 2017, grazie all'utente che ha fornito un link al riferimento aggiornato.) Ma fai attenzione al avvertimento che, mentre queste regole CRR possono rappresentare l'universo di emissione della carta in quanto si applica ai commercianti acquisiti da tale entità, non include ad esempio intervalli identificati come CUP / UPI.

Questi commenti si applicano agli scenari con banda magnetica (MagStripe) o PKE (Pan Key Entry). La situazione è di nuovo diversa nel mondo ICC / EMV.

Aggiornamento: Altre risposte su questa pagina (e anche la pagina WikiPedia collegata) hanno JCB come sempre lungo 16. Tuttavia, nella mia azienda abbiamo un team dedicato di ingegneri che certificano i nostri dispositivi POS e software attraverso più banche e aree geografiche acquisenti. Il più recente mazzo di carte di certificazione che questa squadra possiede da JCB, aveva una valigetta per un PAN da 19.


Ciao @CaiqueOliveira, vedi i link aggiornati. Grazie a mac9416 che ha fornito un collegamento al riferimento aggiornato alle Regole BIN.
MikeRoger,

1
Grazie @ mac9416, per il riferimento aggiornato alle regole BIN.
MikeRoger,

5

Swift 2.1 Versione della risposta di Usman Y. Utilizzare un'istruzione print per verificare quindi chiamare con un valore di stringa

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 ha fornito questa fantastica libreria javascript per il rilevamento di schemi di carte. Consentitemi di aggiungere alcuni frammenti di codice e mostrarvi come usarlo.

Per prima cosa includilo nella tua pagina web come

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

In secondo luogo, utilizzare la funzione cardType per rilevare lo schema delle carte.

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

Ecco i link di riferimento per ulteriori esempi e demo.

  1. Blog a strisce per jquery.payment.js
  2. Repository Github

4

In breve tempo puoi creare un enum per rilevare il tipo di carta di credito.

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

Chiamare il metodo CreditCardType.cardTypeForCreditCardNumber ("# numero carta") che restituisce il valore enum CreditCardType.


3

La mia soluzione con 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;
}

Nel caso in cui venga restituito 0, il tipo di carta di credito non viene rilevato.

La classe "carta di credito" deve essere aggiunta al campo di inserimento della carta di credito.


1
Variazione delle risposte esistenti.
Gajus,

1
Sì, ho usato il codice dalle risposte sopra, l'ho MIGLIORATO e l'ho pubblicato qui. Grazie per il downvote ...
ZurabWeb

3
Avresti dovuto (a) suggerirlo come un miglioramento del codice esistente, (b) scrivere i contributi appropriati o (c) fare riferimento alle fonti che hai usato per scrivere le espressioni regolari.
Gajus

1
Gajus, credo di aver aiutato la comunità come avrei potuto in quel momento, per favore smettila di dirmi che avrei dovuto fare qualcosa per qualcuno. Ho fatto quello che avrei potuto essere utile.
ZurabWeb

3

Ho cercato un po 'in giro per la formattazione della carta di credito e la formattazione del numero di telefono. Ho trovato un sacco di buoni consigli, ma nulla si adattava perfettamente ai miei desideri esatti, quindi ho creato questo codice . Lo usi in questo modo:

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

La domanda riguarda l' algoritmo per verificare una carta di credito, non un'implementazione specifica. Cosa fa questo codice?
Emil Vikström,

2

Solo un cucchiaino da mangiare:

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

Ecco un esempio di alcune funzioni booleane scritte in Python che ritornano Truese la scheda viene rilevata secondo il nome della funzione.

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

Le prime sei cifre di un numero di carta (compresa la cifra MII iniziale) sono note come numero di identificazione dell'emittente (IIN). Questi identificano l'istituto emittente della carta che ha emesso la carta al titolare della carta. Il resto del numero è assegnato dall'emittente della carta. La lunghezza del numero di carta corrisponde al numero di cifre. Molti emittenti di carte stampano l'intero IIN e il numero di conto sulla propria carta.

Sulla base di quanto sopra, vorrei conservare un frammento di codice JAVA per identificare il marchio della carta.

Tipi di carte campione

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

Prefissi delle 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"
    };

Verificare se il numero di input ha uno dei prefissi indicati.

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

Infine, il metodo 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;
}

Riferimento


1

Prova questo per kotlin. Aggiungi Regex e aggiungi all'istruzione 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"
        }
    }

0

Le regole delle espressioni regolari che corrispondono ai rispettivi fornitori di carte :

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

Penso che regex per JCB sia errato. Tutte le prime quattro cifre tra 3528 e 3589 dovrebbero essere accettate, ma 3570 non lo è, per esempio.
Gabe,

0

Uso https://github.com/bendrucker/creditcards-types/ per rilevare il tipo di carta di credito dal numero. Un problema che ho riscontrato è scoprire il numero di prova 6011 1111 1111 1117

da https://www.cybersource.com/developers/other_resources/quick_references/test_cc_numbers/ possiamo vedere che è un numero di scoperta perché inizia da 6011. Ma il risultato che ottengo dai tipi di carte di credito è "Maestro". Ho aperto il problema all'autore. Mi ha risposto molto presto e ha fornito questo documento pdf https://www.discovernetwork.com/downloads/IPP_VAR_Compliance.pdf Dal documento possiamo vedere chiaramente che 6011 1111 1111 1117 non rientra nel campo di scoperta della carta di credito.


Sto avendo lo stesso problema, hai risolto il problema?
lucasvm1980,

@ lucasvm1980 Penso che il file pdf discovernetwork.com sia più affidabile. E il numero 6011 1111 1111 1117 è solo un numero di prova, nessuna vera carta di credito ha questo numero. Quindi penso che non sia necessario preoccuparsi di questo.
yuxiaomin,

Sembra che ci sia qualche bug con alcune carte Discover, ho provato un numero valido e ho riscontrato anche quell'errore.
lucasvm1980,

@ lucasvm1980 puoi fornire il numero e inviare un problema su github?
yuxiaomin,

0

Prova questo. Per una rapida.

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
}

Uso.

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) {

            }
        });
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.