Bagaimana Anda mendeteksi jenis kartu kredit berdasarkan nomor?

516

Saya mencoba mencari cara untuk mendeteksi jenis kartu kredit berdasarkan pada nomornya. Adakah yang tahu cara pasti dan andal untuk menemukan ini?

Andrew Edvalson
sumber
3
Menggunakan ekspresi reguler. Lihat tautan ini untuk informasi lebih lanjut.
senfo
3
Detailnya
1
Ada tabel ringkasan yang bagus di Wikipedia, di en.wikipedia.org/wiki/Credit_card_numbers . Ini adalah digit pertama hingga enam yang memberi tahu jenis dan penerbit kartu.
Alex
3
Saya tidak akan menggunakan regex selain untuk mengeluarkan grup numerik pertama, Anda biasanya dapat mengetahui hanya dari 4 angka pertama (di AS). Juga sebelum repot-repot membayar untuk membersihkan biaya menjalankan Mod 10 checksum pada nomor kartu untuk memastikan itu bisa sah. Algoritma Luhn
Dan Blair
3
siapa pun dapat berkomentar apakah algoritma ini baik 'untuk semua waktu' - atau apakah mereka berubah secara berkala, seperti misalnya algoritma untuk 'menghitung jika nomor telepon di california'
Simon_Weaver

Jawaban:

772

Nomor kartu kredit / debit disebut sebagai PAN , atau Nomor Akun Utama . Enam digit pertama PAN diambil dari IIN , atau Nomor Identifikasi Penerbit , milik bank penerbit (IIN sebelumnya dikenal sebagai BIN - Nomor Identifikasi Bank - sehingga Anda dapat melihat referensi terminologi itu dalam beberapa dokumen). Keenam digit ini tunduk pada standar internasional, ISO / IEC 7812 , dan dapat digunakan untuk menentukan jenis kartu dari nomor tersebut.

Sayangnya basis data ISO / IEC 7812 yang sebenarnya tidak tersedia untuk umum, namun, ada daftar tidak resmi, baik komersial maupun gratis, termasuk di Wikipedia .

Pokoknya, untuk mendeteksi jenis dari angka, Anda dapat menggunakan ekspresi reguler seperti yang di bawah ini: Kredit untuk ekspresi asli

Visa: ^4[0-9]{6,}$ Nomor kartu Visa dimulai dengan angka 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,}$ Sebelum 2016, nomor MasterCard mulai dengan angka 51 hingga 55, tetapi ini hanya akan mendeteksi kartu kredit MasterCard ; ada kartu lain yang dikeluarkan menggunakan sistem MasterCard yang tidak termasuk dalam rentang IIN ini. Pada 2016, mereka akan menambahkan angka dalam kisaran (222100-272099).

American Express: ^3[47][0-9]{5,}$ Nomor kartu American Express dimulai dengan 34 atau 37.

Diners Club: ^3(?:0[0-5]|[68][0-9])[0-9]{4,}$ Nomor kartu Diners Club dimulai dengan 300 hingga 305, 36 atau 38. Ada kartu Diners Club yang dimulai dengan 5 dan memiliki 16 digit. Ini adalah usaha patungan antara Diners Club dan MasterCard dan harus diproses seperti MasterCard.

Temukan: ^6(?:011|5[0-9]{2})[0-9]{3,}$ Temukan nomor kartu dimulai dengan 6011 atau 65.

JCB: ^(?:2131|1800|35[0-9]{3})[0-9]{3,}$ Kartu JCB dimulai dengan 2131, 1800 atau 35.

Sayangnya, ada sejumlah jenis kartu yang diproses dengan sistem MasterCard yang tidak hidup dalam kisaran IIN MasterCard (angka mulai 51 ... 55); kasus yang paling penting adalah kartu Maestro, banyak di antaranya telah dikeluarkan dari rentang IIN bank lain dan berlokasi di seluruh ruang angka. Sebagai akibatnya, mungkin lebih baik untuk mengasumsikan bahwa kartu apa pun yang bukan dari jenis lain yang Anda terima haruslah MasterCard .

Penting : panjang nomor kartu bervariasi; misalnya, Visa memiliki kartu yang dikeluarkan di masa lalu dengan 13 digit PAN dan kartu dengan 16 digit PAN. Dokumentasi Visa saat ini menunjukkan bahwa ia mungkin mengeluarkan atau mungkin telah mengeluarkan angka dengan antara 12 dan 19 digit. Oleh karena itu, Anda tidak boleh memeriksa panjang nomor kartu, selain untuk memverifikasi bahwa ia memiliki setidaknya 7 digit (untuk IIN lengkap ditambah satu digit periksa, yang harus sesuai dengan nilai yang diprediksi oleh algoritma Luhn ).

Satu petunjuk lebih lanjut: sebelum memproses PAN pemegang kartu, lepaskan karakter spasi dan tanda baca apa pun dari input . Mengapa? Karena biasanya lebih mudah untuk memasukkan angka dalam grup, mirip dengan bagaimana mereka ditampilkan di bagian depan kartu kredit yang sebenarnya, yaitu

4444 4444 4444 4444

jauh lebih mudah untuk masuk dengan benar daripada

4444444444444444

Benar-benar tidak ada manfaat dalam menghukum pengguna karena mereka telah memasukkan karakter yang tidak Anda harapkan di sini.

Ini juga menyiratkan memastikan bahwa bidang entri Anda memiliki ruang untuk setidaknya 24 karakter, jika tidak, pengguna yang memasukkan spasi akan kehabisan ruang. Saya sarankan Anda membuat bidang cukup lebar untuk menampilkan 32 karakter dan memungkinkan hingga 64; yang memberi banyak ruang kepala untuk ekspansi.

Berikut adalah gambar yang memberi sedikit lebih banyak wawasan:

UPDATE (2014): Metode checksum tampaknya tidak lagi menjadi cara yang valid untuk memverifikasi keaslian kartu seperti yang tercantum dalam komentar pada jawaban ini.

UPDATE (2016): Mastercard akan menerapkan rentang BIN baru mulai Pembayaran Ach .

verifikasi kartu kredit

senfo
sumber
7
contoh yang bagus. apakah Anda memiliki ekspresi reguler untuk kartu maestro?
Manikandan
4
Tidak tidak Tidak. Anda tidak dapat mengandalkan panjangnya nomor kartu; mereka dapat berubah kapan saja. Satu-satunya bagian dari nomor kartu yang dapat Anda andalkan adalah IIN (yang dulu disebut BIN) dan yang merupakan awalan dari nomor tersebut. Selain itu, Anda tidak dapat mendeteksi kartu Mastercard dengan cara yang Anda sarankan; yang hanya akan mengambil subset kartu yang diproses melalui sistem Mastercard (masalah utama adalah kartu Maestro, yang memiliki berbagai awalan IIN).
alastair
2
@alastair apakah Anda membaca ekspresi sebelum berkomentar? Mereka ditulis khusus untuk menggunakan IIN, jadi saya tidak mengerti apa yang ingin Anda katakan. Selain itu, IIN dapat digunakan untuk mengidentifikasi penerbit kartu, tetapi tidak valid. 5412, misalnya, tidak mewakili MasterCard lengkap, tetapi saran Anda menyiratkan itu. Saya tidak menemukan bukti bahwa MasterCard adalah 16 digit. Silakan berikan sumber untuk klaim Anda. Anda benar dalam menyebutkan pembaruan yang perlu dibuat untuk kartu Maestro.
senfo
3
@senfo Anda benar, 5412 tidak akan menjadi nomor Mastercard lengkap. IIN panjangnya enam digit, jadi nomor kartu yang lengkap harus 7 digit (minimum) dan harus lulus pemeriksaan Luhn. Tidak perlu "bukti" bahwa nomor Mastercard memiliki apa pun selain 16 digit; intinya adalah bahwa, terlepas dari situasi saat ini, di masa depan mereka mungkin mengeluarkan kartu dengan 17 atau 18 digit, atau dalam hal ini beberapa dengan 15. Bergantung pada mereka yang panjangnya 16 digit tidak diperlukan dan menciptakan risiko pemeliharaan jangka panjang.
alastair
3
Saya merasa sangat sulit untuk percaya bahwa beberapa kartu yang valid tidak akan memiliki digit periksa yang benar sesuai dengan algoritma Luhn. Itu digunakan benar-benar di mana-mana untuk memeriksa nomor kartu terhadap kesalahan ketik sederhana dan upaya penipuan bodoh. Sebagai gantinya, saya telah mengamati beberapa orang yang cukup pintar tidak memahami algoritma, dan mereka hanya salah menghitungnya.
Rennex
74

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

Tes 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
sumber
1
@ jolly.exe - biola Anda kembali tidak ditentukan untuk semua tes. Tidak bekerja :(
ShadeTreeDeveloper
@ShadeTreeDeveloper cukup masukkan nilai apa pun misalnya. 372176090165471 untuk AMAX di bidang teks
Code Spy
@ jolly.exe Saya melihat ... Saya berharap untuk sesuatu yang akan memformat saat saya mengetik (dari acara keyup). Biola bekerja ketika saya memasukkan angka penuh.
ShadeTreeDeveloper
Saya akhirnya menulis sedikit kode ini untuk melakukan pemformatan input dan validasi yang saya inginkan. quercusv.github.io/smartForm
ShadeTreeDeveloper
Anda tahu cara mendeteksi nomor kartu v-pay dan bancontact? Terima kasih
Oleksandr IY
38

Diperbarui: 15 Juni 2016 (sebagai solusi akhir saat ini)

Harap dicatat bahwa saya bahkan memberikan suara untuk salah satu yang terpilih, tetapi untuk membuatnya jelas ini adalah regexps benar-benar berfungsi saya mengujinya dengan ribuan kode BIN nyata. Yang paling penting adalah menggunakan string awal (^) kalau tidak akan memberikan hasil yang salah di dunia nyata!

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

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

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

Visa ^4[0-9]{0,}$ Mulai dengan: 4

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

Maestro ^(5[06789]|6)[0-9]{0,}$ Maestro selalu berkembang dalam kisaran: 60-69 , dimulai dengan / bukan sesuatu yang lain, tetapi mulai 5 harus dikodekan sebagai mastercard. Kartu maestro harus dideteksi di akhir kode karena sebagian yang lain memiliki kisaran 60-69. Silakan lihat kodenya.

Temukan ^(6011|65|64[4-9]|62212[6-9]|6221[3-9]|622[2-8]|6229[01]|62292[0-5])[0-9]{0,}$ Temukan yang cukup sulit untuk dikodekan, mulai dengan: 6011, 622126-622925, 644-649, 65

Dalam javascript saya menggunakan fungsi ini. Ini bagus ketika Anda menugaskannya ke acara onkeyup dan itu memberikan hasil sesegera mungkin.

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

Di sini Anda dapat bermain dengannya:

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

Untuk PHP menggunakan fungsi ini, ini mendeteksi beberapa sub kartu VISA / MC juga:

/**
  * 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
sumber
1
Dan harap dicatat, bahwa ini hanya deteksi nomor CC dan bukan validasi. Itu terpisah, harus menjadi cek Luhn ...
Janos Szabo
Di mana Visa Electron, dan mengapa Maestro memeriksa kembali MasterCard dalam beberapa kasus? Bukankah seharusnya MasterCard memeriksa itu sendiri?
BadHorsie
Gagal mengenali nomor tes JCB ini sebagai salah satu tipe (3088514174175777), dan mengidentifikasi nomor tes JCB ini sebagai diners_club (3096278649822922). Dengan asumsi daftar nomor kartu tes ini tetap valid ( freeformatter.com/credit-card-number-generator-validator.html )
Drew
tidak ada dokumentasi bahwa mulai 308 atau 309 bisa menjadi kartu JCB
Janos Szabo
+1 untuk menyediakan kode deteksi tipe cc, yang biasanya ingin Anda lakukan untuk ux - regex untuk rentang baru pada MC membutuhkan tweek kecil: / ^ (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";
}

Berikut adalah fungsi untuk memeriksa jenis kartu kredit menggunakan Regex, c #

Usman Younas
sumber
19

Lihat ini:

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
sumber
15

Baru-baru ini saya membutuhkan fungsionalitas seperti itu, saya memindahkan Validator Kartu Kredit Zend Framework ke ruby. ruby gem: https://github.com/Fivell/credit_card_validations kerangka zend: https://github.com/zendframework/zf2/blob/master/library/Zend/Validator/CreditCard.php

Keduanya menggunakan rentang INN untuk mendeteksi tipe. Di sini Anda dapat membaca tentang INN

Menurut ini, Anda dapat mendeteksi kartu kredit sebagai alternatif (tanpa regexps, tetapi mendeklarasikan beberapa aturan tentang awalan dan kemungkinan panjang)

Jadi kita memiliki aturan selanjutnya untuk kartu yang paling sering digunakan

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

}

Kemudian dengan mencari awalan dan membandingkan panjang Anda dapat mendeteksi merek kartu kredit. Juga jangan lupa tentang algoritme luhn (itu dideskripsikan di sini http://en.wikipedia.org/wiki/Luhn ).

MEMPERBARUI

daftar peraturan terbaru dapat ditemukan di sini https://raw.githubusercontent.com/Fivell/credit_card_validations/master/lib/data/brands.yaml

Fivell
sumber
2
Sangat ilustratif. Panjang kartu VISA mungkin 13 digit.
Herman Kan
@HermanKan, tidak ada situs web VISA yang mengatakan panjangnya harus 16, saya pikir dulu mungkin 13, tapi tidak sekarang
Fivell
1
Saya pikir ini adalah dukungan warisan
Fivell
1
@HermanKan, ada satu hal lagi, VISA memiliki kartu VPay dan menyetujui wikipedia. Visa VPay merek dapat menentukan panjang PAN dari 13 hingga 19 digit sehingga jumlah kartu lebih dari 16 digit sekarang terlihat.
Fivell
1
@Ethan, periksa tautan terakhir di jawaban saya yang diperbarui raw.githubusercontent.com/Fivell/credit_card_validations/master/…
Fivell
13

Berikut kode C # atau VB Lengkap untuk semua jenis hal terkait CC pada proyek codep.

  • IsValidNumber
  • DapatkanCardTypeFromNumber
  • GetCardTestNumber
  • PassesLuhnTest

Artikel ini telah terbit selama beberapa tahun tanpa komentar negatif.

Simon_Weaver
sumber
1
@barett - memperbaikinya. sepertinya mereka memindahkannya dari kategori 'aspnet' ke kategori 'validasi' yang mengubah tautan
Simon_Weaver
2
Tautan rusak. Mungkin ini utilitas yang sama? codeproject.com/Articles/20271/…
Josh Noe
Itu kode proyek kode dari 2007. Peringatan, Ini mungkin sudah ketinggalan zaman.
aron
8

Versi javascript ringkas

    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;
            }
        }
    };
Nick
sumber
8

Jawaban Anatoliy dalam 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
sumber
7

Berikut adalah fungsi kelas php mengembalikan CCtype oleh CCnumber.
Kode ini tidak memvalidasi kartu atau tidak menjalankan algoritma Luhn hanya mencoba menemukan jenis kartu kredit berdasarkan tabel di halaman ini . pada dasarnya menggunakan panjang CCnumber dan awalan CCcard untuk menentukan jenis 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;
    }
}
ismail
sumber
6

Jangan mencoba mendeteksi jenis kartu kredit sebagai bagian dari pemrosesan pembayaran. Anda berisiko kehilangan transaksi yang valid.

Jika Anda perlu memberikan informasi kepada pemroses pembayaran Anda (mis. Objek kartu kredit PayPal harus menyebutkan jenis kartu ), maka tebaklah dari informasi yang paling sedikit tersedia, mis.

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

Implementasi ini (hanya menggunakan dua digit pertama) sudah cukup untuk mengidentifikasi semua skema kartu utama (dan dalam kasus PayPal semua yang didukung). Bahkan, Anda mungkin ingin melewatkan pengecualian sama sekali dan default ke jenis kartu paling populer. Biarkan gateway pembayaran / prosesor memberi tahu Anda jika ada kesalahan validasi dalam menanggapi permintaan Anda.

Kenyataannya adalah gateway pembayaran Anda tidak peduli dengan nilai yang Anda berikan .

Gajus
sumber
1
Ini tidak benar. Saya tahu 3 penyedia berbeda yang DO mengharuskan jenis kartu untuk diteruskan, dan jika Anda tidak meneruskannya, transaksi akan gagal.
Ed DeGagne
3
@ EdDeGagne - "tidak peduli apa nilai" tidak sama dengan "tidak peduli jika diteruskan"
Quentin Skousen
Di mana saya menentukan? Saya hanya menyebutkan bahwa ada penyedia yang membutuhkan ANDA untuk lulus dalam tipe CC, tidak lebih.
Ed DeGagne
Anda tidak dapat menyederhanakan masalah yang rumit ini, tetapi biasanya penyedia pembayaran tidak mengharuskan Anda untuk menyarankan jenis kartu, mereka memiliki metode sendiri untuk mendeteksi
Janos Szabo
6

Angka pertama kartu kredit dapat digunakan untuk memperkirakan vendor:

  • Visa: 49,44 atau 47
  • Visa elektron: 42, 45, 48, 49
  • MasterCard: 51
  • Amex: 34
  • Pengunjung: 30, 36, 38
  • JCB: 35
Shoban
sumber
Rentang ini telah diperbarui secara utama, perusahaan vendor Kartu telah menambahkan rentang yang jauh lebih banyak daripada yang disebutkan dalam pos.
NJInamdar
6

Dalam Card Range Recognition (CRR), kelemahan dengan algoritma yang menggunakan serangkaian regex atau rentang hard-coded lainnya, adalah bahwa BIN / IIN berubah seiring waktu dalam pengalaman saya. Co-branding kartu merupakan komplikasi yang berkelanjutan. Pengakuisisi Kartu yang berbeda / pedagang mungkin perlu Anda memperlakukan kartu yang sama secara berbeda, tergantung pada misalnya geolokasi.

Selain itu, dalam beberapa tahun terakhir dengan kartu UnionPay misalnya dalam sirkulasi yang lebih luas, model yang ada tidak mengatasi rentang baru yang kadang-kadang interleave dengan rentang yang lebih luas yang mereka gantikan.
Mengetahui geografi yang perlu dicakup sistem Anda dapat membantu, karena beberapa rentang terbatas untuk digunakan di negara-negara tertentu. Misalnya, rentang 62 mencakup beberapa sub-rentang AAA di AS, tetapi jika basis pedagang Anda di luar AS, Anda mungkin dapat memperlakukan semua 62 sebagai UnionPay.
Anda mungkin juga diminta untuk memperlakukan kartu secara berbeda berdasarkan lokasi pedagang. Misalnya memperlakukan kartu UK tertentu sebagai debit di dalam negeri, tetapi sebagai kredit internasional.

Ada seperangkat aturan yang sangat berguna yang dikelola oleh satu Bank Pengakuisisi besar. Misalnya https://www.barclaycard.co.uk/business/files/BIN-Rules-EIRE.pdf dan https://www.barclaycard.co.uk/business/files/BIN-Rules-UK.pdf . (Tautan yang valid per Juni 2017, terima kasih kepada pengguna yang memberikan tautan ke referensi yang diperbarui.) Namun perlu diperhatikan bahwa, sementara aturan CRR ini dapat mewakili alam semesta Penerbit Kartu sebagaimana berlaku untuk pedagang yang diperoleh oleh entitas itu, itu tidak termasuk mis. rentang yang diidentifikasi sebagai CUP / UPI.

Komentar ini berlaku untuk skenario magnetic stripe (MagStripe) atau PKE (Pan Key Entry). Situasinya berbeda lagi di dunia ICC / EMV.

Pembaruan: Jawaban lain pada halaman ini (dan juga halaman WikiPedia yang ditautkan) memiliki JCB seperti biasanya sepanjang 16. Namun, di perusahaan saya, kami memiliki tim insinyur khusus yang mengesahkan perangkat POS dan perangkat lunak kami di beberapa bank dan geografi yang mengakuisisi. Paket Sertifikasi kartu terakhir yang dimiliki tim ini dari JCB, memiliki kasus lulus untuk PAN yang panjang 19.

MikeRoger
sumber
Hai @CaiqueOliveira, lihat tautan yang diperbarui. Terima kasih kepada mac9416 yang menyediakan tautan ke referensi Peraturan BIN yang diperbarui.
MikeRoger
1
Terima kasih @ mac9416, untuk referensi Aturan BIN yang diperbarui.
MikeRoger
5

Swift 2.1 Versi dari jawaban Usman Y. Gunakan pernyataan cetak untuk memverifikasi sehingga panggilan dengan beberapa nilai string

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.
sumber
4

Stripe telah menyediakan perpustakaan javascript yang fantastis ini untuk deteksi skema kartu. Izinkan saya menambahkan beberapa cuplikan kode dan menunjukkan kepada Anda cara menggunakannya.

Pertama Sertakan ke halaman web Anda sebagai

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

Kedua, gunakan cardType fungsi untuk mendeteksi skema kartu.

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

Berikut ini tautan referensi untuk lebih banyak contoh dan demo.

  1. Stripe blog untuk jquery.payment.js
  2. Repositori Github
NJInamdar
sumber
4

Dengan cepat Anda dapat membuat enum untuk mendeteksi jenis kartu kredit.

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

Panggil metode CreditCardType.cardTypeForCreditCardNumber ("# nomor kartu") yang mengembalikan nilai enum CreditCardType.

Vidyalaxmi
sumber
3

Solusi saya dengan 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;
}

Jika 0 dikembalikan, jenis kartu kredit tidak terdeteksi.

kelas "kartu kredit" harus ditambahkan ke bidang input kartu kredit.

ZurabWeb
sumber
1
Variasi jawaban yang ada.
Gajus
1
Ya, saya menggunakan kode dari jawaban di atas, MENINGKATKAN dan mempostingnya di sini. Terima kasih atas
suaranya
3
Anda harus (a) menyarankan ini sebagai peningkatan pada kode yang ada, (b) menulis kontribusi yang sesuai, atau (c) referensi sumber yang telah Anda gunakan untuk menulis ekspresi reguler.
Gajus
1
Gajus, saya percaya saya telah membantu komunitas dengan cara yang saya bisa saat itu, tolong berhenti memberi tahu saya bahwa saya harus melakukan sesuatu untuk seseorang. Saya melakukan apa yang saya pikir bisa membantu.
ZurabWeb
3

Saya mencari di sekitar sedikit untuk pemformatan kartu kredit dan pemformatan nomor telepon. Menemukan banyak tips bagus tetapi tidak ada yang benar-benar cocok dengan keinginan saya, jadi saya membuat sedikit kode ini . Anda menggunakannya seperti ini:

var sf = smartForm.formatCC(myInputString);
var cardType = sf.cardType;
ShadeTreeDeveloper
sumber
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
sumber
Pertanyaannya adalah tentang algoritma untuk memeriksa kartu kredit, bukan implementasi spesifik. Apa yang dilakukan kode ini?
Emil Vikström
2

Sedikit saja pemberian sendok:

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

        }

    });
Mencubit
sumber
2

Berikut adalah contoh beberapa fungsi boolean yang ditulis dengan Python yang kembali Truejika kartu terdeteksi sesuai nama fungsi.

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
sumber
1

Enam digit pertama nomor kartu (termasuk digit MII awal) dikenal sebagai nomor identifikasi penerbit (IIN). Ini mengidentifikasi institusi penerbit kartu yang mengeluarkan kartu kepada pemegang kartu. Sisa nomor dialokasikan oleh penerbit kartu. Panjang nomor kartu adalah jumlah digitnya. Banyak penerbit kartu mencetak seluruh IIN dan nomor rekening pada kartu mereka.

Berdasarkan fakta di atas saya ingin menyimpan potongan kode JAVA untuk mengidentifikasi merek kartu.

Jenis kartu sampel

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

Awalan Kartu

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

Periksa untuk melihat apakah nomor input memiliki salah satu dari awalan yang diberikan.

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

Akhirnya, metode Utilitas

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

Referensi

Anoop M
sumber
1

Coba ini untuk kotlin. Tambahkan Regex dan tambahkan ke pernyataan 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"
        }
    }
Ohhh, Itu Varun
sumber
0

Aturan persamaan reguler yang cocok dengan masing - masing vendor kartu :

  • (4\d{12}(?:\d{3})?) untuk VISA.
  • (5[1-5]\d{14}) untuk MasterCard.
  • (3[47]\d{13}) untuk AMEX.
  • ((?:5020|5038|6304|6579|6761)\d{12}(?:\d\d)?) untuk Maestro.
  • (3(?:0[0-5]|[68][0-9])[0-9]{11}) untuk Diners Club.
  • (6(?:011|5[0-9]{2})[0-9]{12}) untuk Discover.
  • (35[2-8][89]\d\d\d{10}) untuk JCB.
rajan
sumber
Saya pikir regex untuk JCB salah. Keempat digit pertama antara 3528 dan 3589 harus diterima, tetapi 3570 tidak, misalnya.
Gabe
0

Saya menggunakan https://github.com/bendrucker/creditcards-types/ untuk mendeteksi jenis kartu kredit dari nomor. Satu masalah yang saya temui adalah menemukan nomor tes 6011 1111 1111 1117

dari https://www.cybersource.com/developers/other_resources/quick_references/test_cc_numbers/ kita bisa melihat ini adalah nomor penemuan karena dimulai oleh 6011. Tetapi hasil yang saya dapatkan dari kartu kredit adalah "Maestro". Saya membuka masalah kepada penulis. Dia segera menjawab saya dan memberikan dokumen pdf ini https://www.discovernetwork.com/downloads/IPP_VAR_Compliance.pdf Dari dokumen tersebut kita dapat melihat dengan jelas bahwa 6011 1111 1111 1117 tidak termasuk dalam jajaran kartu kredit temukan.

yuxiaomin
sumber
Saya memiliki masalah yang sama, apakah Anda sudah memperbaikinya?
lucasvm1980
@ lucasvm1980 Saya pikir file pdf discovernetwork.com lebih dapat diandalkan. Dan nomor 6011 1111 1111 1117 hanyalah nomor tes, tidak ada kartu kredit nyata yang memiliki nomor ini. Jadi saya pikir tidak perlu khawatir tentang ini.
yuxiaomin
Sepertinya ada beberapa bug dengan beberapa kartu Discover, saya telah mencoba nomor yang valid dan saya mendapatkan kesalahan itu juga.
lucasvm1980
@ lucasvm1980 dapatkah Anda memberikan nomornya dan mengirimkan masalah di github?
yuxiaomin
0

Coba ini. Untuk cepat.

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
}

Menggunakan.

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