숫자를 기준으로 신용 카드 유형을 어떻게 감지합니까?


516

번호를 기준으로 신용 카드 유형을 감지하는 방법을 찾으려고합니다. 누구든지 이것을 찾을 수있는 결정적이고 확실한 방법을 알고 있습니까?


3
정규식을 사용합니다. 체크 아웃 이 링크를 자세한 내용은.
senfo

3
자세한 내용은 Wikipedia에 있습니다. en.wikipedia.org/wiki/Credit_card_numbers
Sten Vesterli

1
Wikipedia에는 en.wikipedia.org/wiki/Credit_card_numbers 에 요약표가 있습니다 . 카드의 종류와 발급자를 알려주는 첫 번째 1 ~ 6 자리 숫자입니다.
Alex

3
첫 번째 숫자 그룹을 꺼내는 것 이외의 정규 표현식을 사용하지 않을 것입니다. 일반적으로 처음 4 개 숫자 (미국)를 알 수 있습니다. 또한 요금을 청구하기 위해 비용을 지불하기 전에 카드 번호에 Mod 10 체크섬을 실행하여 합법적 일 수 있는지 확인하십시오. Luhn 알고리즘
Dan Blair

3
또한 이러한 알고리즘이 '항상 유효하다'고 언급 할 수 있습니다. 예를 들어 '전화 번호가 캘리포니아에있을 경우 계산'알고리즘과 같이 주기적으로 변경합니까?
Simon_Weaver

답변:


771

신용 / 직불 카드 번호를 PAN 또는 기본 계정 번호라고 합니다. PAN의 처음 6 자리 숫자 는 발급 은행에 속한 IIN 또는 발급자 식별 번호 에서 가져옵니다 ( IIN 은 이전에 BIN (은행 식별 번호)로 알려 졌으므로 일부 문서에서 해당 용어에 대한 참조를 볼 수 있습니다). 이 6 자리 숫자는 국제 표준 ISO / IEC 7812의 적용을받습니다. 번호에서 카드 유형을 결정하는 데 사용할 수 있습니다.

불행히도 실제 ISO / IEC 7812 데이터베이스는 공개적으로 사용할 수 없지만 Wikipedia를 포함하여 상업용 및 무료의 비공식 목록이 있습니다 .

어쨌든 숫자에서 유형을 감지하려면 다음과 같은 정규 표현식을 사용할 수 있습니다. 원래 표현식에 대한 크레딧

비자 : ^4[0-9]{6,}$ 비자 카드 번호는 4로 시작합니다.

마스터 카드 : ^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,}$ 2016 년 이전에 마스터 카드 번호는 51부터 55까지의 숫자로 시작 하지만 마스터 카드 신용 카드 만 감지합니다 . 이 IIN 범위에 속하지 않는 MasterCard 시스템을 사용하여 발급 된 다른 카드가 있습니다. 2016 년에는 범위 (222100-272099)의 숫자를 추가합니다.

American Express : ^3[47][0-9]{5,}$ American Express 카드 번호는 34 또는 37로 시작합니다.

Diners Club : ^3(?:0[0-5]|[68][0-9])[0-9]{4,}$ Diners Club 카드 번호는 300에서 305, 36 또는 38로 시작합니다. Diners Club 카드는 5로 시작하고 16 자리입니다. Diners Club과 MasterCard의 합작 투자이며 마스터 카드처럼 처리해야합니다.

검색 : ^6(?:011|5[0-9]{2})[0-9]{3,}$ 검색 카드 번호는 6011 또는 65로 시작합니다.

JCB : ^(?:2131|1800|35[0-9]{3})[0-9]{3,}$ JCB 카드는 2131, 1800 또는 35로 시작합니다.

불행하게도, 마스터 카드의 IIN 범위에 속하지 않는 마스터 카드 시스템으로 처리 된 여러 종류의 카드가 있습니다 (번호는 51 ~ 55로 시작). 가장 중요한 경우는 다른 은행의 IIN 범위에서 발행 된 Maestro 카드의 경우이며, 숫자 공간 전체에 있습니다. 결과적으로, 귀하가 수락하는 다른 유형이 아닌 카드는 마스터 카드 여야한다고 가정하는 것이 가장 좋습니다 .

중요 : 카드 번호는 길이가 다릅니다. 예를 들어, Visa는 과거에 13 자리 PAN이있는 카드와 16 자리 PAN이있는 카드를 발행했습니다. Visa의 문서는 현재 12 자리에서 19 자리 사이의 숫자를 발행하거나 발행했을 수 있음을 나타냅니다. 따라서 카드 번호의 길이를 확인하지 말고 카드 번호가 7 자리 이상인지 확인하십시오 (완전한 IIN과 하나의 확인 숫자의 경우 Luhn 알고리즘에 의해 예측 된 값과 일치해야 함 ).

추가 힌트 : 카드 소지자 PAN을 처리하기 전에 입력에서 공백 및 문장 부호 문자를 제거하십시오 . 왜? 일반적으로 실제 신용 카드의 앞면에 표시되는 방식과 유사하게 그룹으로 숫자를 입력하는 것이 훨씬 쉽습니다.

4444 4444 4444 4444

보다 정확하게 입력하는 것이 훨씬 쉽습니다

4444444444444444

사용자가 여기에 예상하지 못한 문자를 입력했기 때문에 사용자를 쫓는 데는 아무런 이점이 없습니다.

이것은 또한 입력 필드 에 최소 24자를 위한 공간이 있어야 함을 의미 합니다. 그렇지 않으면 공백을 입력 한 사용자는 공간이 부족합니다. 32자를 표시하고 최대 64자를 허용 할 수 있도록 필드를 넓게 만드는 것이 좋습니다. 확장을위한 충분한 여유 공간을 제공합니다.

약간 더 통찰력을주는 이미지는 다음과 같습니다.

업데이트 (2014) : 체크섬 방법은 더 이상 이 답변에 대한 의견에 언급 된대로 카드의 진위확인하는 유효한 방법으로 보이지 않습니다 .

업데이트 (2016) : 마스터 카드는 Ach Payment 시작하는 새로운 BIN 범위를 구현 합니다.

신용 카드 확인


7
좋은 예입니다. 마에스트로 카드에 대한 정규식이 있습니까?
마니 칸탄

4
아니, 아니. 카드 번호의 길이에 의존 할 수 없습니다. 그들은 언제든지 바꿀 수 있습니다. 신뢰할 수있는 카드 번호의 유일한 부분은 IIN (BIN이라고 함)이며 번호의 접두사입니다. 또한 제안한 방식으로 마스터 카드를 감지 할 수 없습니다 . 마스터 카드 시스템을 통해 처리되는 카드 중 일부만 선택합니다 (주요 문제는 다양한 IIN 접두사가있는 Maestro 카드입니다).
alastair

2
@alastair 댓글을 달기 전에 표현을 읽었습니까? 그들은 IIN을 사용하기 위해 특별히 작성되었으므로, 당신이 말하려는 것을 이해하지 못합니다. 또한 IIN을 사용하여 카드 발급자를 식별 할 수는 있지만 검증 할 수는 없습니다. 예를 들어, 5412는 완전한 마스터 카드를 나타내지 않지만 귀하의 제안은 그 사실을 암시합니다. 마스터 카드가 16 자리 이외의 것임을 증명하지 못했습니다. 귀하의 주장에 대한 출처를 자유롭게 제공하십시오. 그러나 Maestro 카드에 대한 업데이트가 필요하다는 언급은 정확합니다.
senfo

3
@senfo 맞습니다. 5412는 완전한 마스터 카드 번호가 아닙니다. IIN의 길이는 6 자리이므로 완전한 카드 번호는 7 자리 (최소) 여야하며 Luhn 검사를 통과해야합니다. 마스터 카드 번호에 16 자리 이외의 숫자가 있다는 것을“증거”할 필요는 없습니다. 요점은 오늘날 상황에 관계없이 장래에 17 자리 또는 18 자리의 카드 또는 15 자리에 해당하는 카드를 발급 할 수 있다는 것입니다. 16 자리의 길이에 의존하는 것은 불필요하며 장기적인 유지 관리 위험을 초래합니다.
alastair

3
일부 유효한 카드에는 Luhn 알고리즘에 따라 올바른 확인 숫자가 없을 것이라고 믿기가 매우 어렵습니다. 간단한 오타와 멍청한 사기 시도에 대비하여 카드 번호를 확인하는 데 절대적으로 사용되었습니다. 대신, 나는 꽤 똑똑한 사람들이 단순히 알고리즘을 파악하지 못하고 잘못 계산하는 것을 관찰했습니다.
Rennex

74

자바 스크립트에서 :

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

단위 테스트 :

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-모든 테스트에서 바이올린이 정의되지 않은 상태로 반환됩니다. 작동하지 않습니다 :(
ShadeTreeDeveloper

@ShadeTreeDeveloper는 아무 값이나 입력하십시오. 텍스트 필드에서 AMAX의 경우 372176090165471
Code Spy

@ jolly.exe 알다시피 ... 나는 키 업 이벤트에서 타이핑 할 때 형식을 지정할 것을 기대했습니다. 전체 숫자를 입력하면 바이올린이 작동합니다.
ShadeTreeDeveloper

원하는 입력 형식과 유효성 검사를 수행하기 위해이 코드를 작성했습니다. quercusv.github.io/smartForm
ShadeTreeDeveloper

v-pay 및 bancontact 카드 번호를 감지하는 방법을 알고 있습니까? 감사합니다
Oleksandr IY

38

업데이트 : 2016 년 6 월 15 일 (현재 최고의 솔루션)

나는 심지어 하나의 투표권을 포기하지만, 정규 표현식이 실제로 작동한다는 것을 분명히하기 위해 수천 개의 실제 BIN 코드로 테스트했습니다. 가장 중요한 것은 시작 문자열 (^)을 사용하는 것입니다. 그렇지 않으면 실제 세계에서 잘못된 결과를 줄 것입니다!

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

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

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

비자 ^4[0-9]{0,}$ 시작 : 4

마스터 카드 ^(5[1-5]|222[1-9]|22[3-9]|2[3-6]|27[01]|2720)[0-9]{0,}$ 시작 : 2221-2720, 51-55

Maestro ^(5[06789]|6)[0-9]{0,}$ Maestro는 항상 60-69 범위에서 성장하고 있습니다. 다른 것으로 시작되지는 않았지만 5를 시작하면 어쨌든 마스터 카드로 인코딩되어야합니다. 다른 일부는 60-69 범위에 있기 때문에 Maestro 카드는 코드 끝에서 감지해야합니다. 코드를보십시오.

발견 ^(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

에서 자바 스크립트 나는이 기능을 사용합니다. 이것은 onkeyup 이벤트에 할당 할 때 좋으며 가능한 빨리 결과를 제공합니다.

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

여기서 당신은 그것으로 재생할 수 있습니다 :

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

PHP의 경우이 기능을 사용하면 일부 하위 VISA / MC 카드도 감지됩니다.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    }

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

1
그리고 이것은 CC 번호 감지 일 뿐이며 유효성 검사는 아닙니다. 분리이라고하는 Luhn 체크되어야 ...
야노 자보

Visa Electron은 어디에 있으며 왜 Maestro 수표가 MasterCard를 반환합니까? 마스터 카드가 그 자체를 점검하지 않아야합니까?
BadHorsie

이 JCB 테스트 번호를 임의 유형으로 인식하지 못하고 (3088514174175777)이 테스트 JCB 번호를 diners_club (3096278649822922)으로 식별합니다. 이 테스트 카드 번호 목록이 어쨌든 유효하다고 가정하면 ( freeformatter.com/credit-card-number-generator-validator.html )
Drew

308 또는 309를 시작하는 것은 JCB 카드가 될 수없는 문서가 없습니다
야노스 자보

CC 유형 감지 코드를 제공하는 +1, 일반적으로 ux에 대해 수행하려는 작업-MC의 새 범위에 대한 정규식에는 약간의 tweek가 필요합니다. / ^ (5 [1-5] | 222 [1-9] | 22 [3-9] [0-9] | 2 [3-6] [0-9] {2} | 27 [01] [0-9] | 2720) [0-9] {0,} $ /
kinakuta

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


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

다음은 Regex, c #을 사용하여 신용 카드 유형을 확인하는 기능입니다.


19

이것 좀 봐:

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

최근에 그러한 기능이 필요했습니다. Zend Framework 신용 카드 검사기를 루비로 포팅했습니다. 루비 젬 : https://github.com/Fivell/credit_card_validations 젠드 프레임 워크 : https://github.com/zendframework/zf2/blob/master/library/Zend/Validator/CreditCard.php

둘 다 유형 감지에 INN 범위를 사용합니다. INN에 대해 읽을 수 있습니다

이에 따르면 신용 카드를 다른 방법으로 감지 할 수 있습니다 (정규 표현식없이 접두사와 가능한 길이에 대한 규칙을 선언하십시오)

가장 많이 사용되는 카드에 대한 다음 규칙이 있습니다.

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

}

그런 다음 접두사를 검색하고 길이를 비교하여 신용 카드 브랜드를 감지 할 수 있습니다. 또한 luhn 알고리즘에 대해서도 잊지 마십시오 ( http://en.wikipedia.org/wiki/Luhn에서 설명 ).

최신 정보

업데이트 된 규칙 목록은 https://raw.githubusercontent.com/Fivell/credit_card_validations/master/lib/data/brands.yaml 에서 확인할 수 있습니다.


2
매우 예시 적입니다. VISA 카드의 길이는 13 자리입니다.
허먼 칸

@HermanKan, VISA 웹 사이트는 16 개 길이 여야한다고 말했는데, 오래 전에는 13 일 수 있었지만 요즘은 아닐 수 있습니다.
Fivell

1
레거시 지원이라고 생각합니다
Fivell

1
@HermanKan, VISA에는 VPay 카드가 있으며 위키 백과에 따르면 Visa의 VPay 브랜드는 13 ~ 19 자리의 PAN 길이를 지정할 수 있으므로 16 자리 이상의 카드 번호가 표시됩니다.
Fivell


13

다음 은 codeproject에 대한 모든 CC 관련 사항대한 완전한 C # 또는 VB 코드입니다 .

  • IsValidNumber
  • GetCardTypeFromNumber
  • GetCardTestNumber
  • PassesLuhnTest

이 기사는 몇 년 동안 부정적인 의견이 없었습니다.


1
@ barett-수정했습니다. 링크를 변경 한 'aspnet'카테고리에서 'validation'카테고리로 이동 한 것으로 보입니다.
Simon_Weaver

2
링크가 끊어졌습니다. 어쩌면 이것은 동일한 유틸리티입니까? codeproject.com/Articles/20271/…
Josh Noe

해당 코드 프로젝트 코드는 2007 년입니다. 경고, 오래되었을 수 있습니다.
aron

8

소형 자바 스크립트 버전

    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

PHP에서 Anatoliy의 답변 :

 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

다음은 PHP 클래스 함수가 ​​CCnumber로 CCtype을 반환하는 것입니다.
이 코드는 카드의 유효성을 검사하지 않거나 Luhn 알고리즘을 실행하지 않습니다 . 이 페이지의 표를 기반으로 신용 카드 유형 만 찾으려고 합니다 . 기본적으로 CCnumber 길이와 CCcard 접두사를 사용하여 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

지불 처리의 일부로 신용 카드 유형을 감지하려고 시도하지 마십시오. 유효한 거래가 거부 될 위험이 있습니다.

결제 처리자에게 정보를 제공해야하는 경우 (예 : PayPal 신용 카드 개체는 카드 유형의 이름을 지정해야 함 ) 사용 가능한 최소 정보 (예 :

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

이 구현 (처음 두 자리 만 사용)은 모든 주요 (및 PayPal의 경우 지원되는 모든) 카드 체계를 식별하기에 충분합니다. 실제로 예외를 모두 건너 뛰고 기본적으로 가장 많이 사용되는 카드 유형으로 설정할 수 있습니다. 지불 게이트웨이 / 프로세서가 요청에 대한 응답으로 유효성 검사 오류가 있는지 알려줍니다.

현실은 당신의 지불 게이트웨이 가 당신이 제공하는 가치에 관심이 없다는 것 입니다.


1
이것은 단순히 사실이 아닙니다. DO에 카드 유형을 전달해야하는 3 개의 다른 제공 업체가 있으며이를 전달하지 않으면 거래가 실패합니다.
Ed DeGagne

3
@EdDeGagne- "어떤 가치를 신경 쓰지 않는다"는 "전달 된 경우 신경 쓰지 않는다"와 동일하지 않습니다.
Quentin Skousen

어느 쪽을 지정 했습니까? CC 유형을 전달해야하는 제공자가 더 이상 없다고 간단히 언급했습니다.
Ed DeGagne

이 복잡한 문제를 단순화 할 수는 없지만 일반적으로 지불 제공 업체는 카드 유형을 제안 할 필요가 없습니다. 이들은 자체 감지 방법을 가지고 있습니다.
Janos Szabo

6

신용 카드의 첫 번째 숫자는 공급 업체를 근사화하는 데 사용될 수 있습니다.

  • 비자 : 49,44 또는 47
  • 비자 전자 : 42, 45, 48, 49
  • 마스터 카드 : 51
  • 아멕스 : 34
  • 식당 : 30, 36, 38
  • JCB : 35

이 범위는 주로 업데이트되었으며, 카드 공급 업체 회사는 게시물에서 언급 한 것보다 더 많은 범위를 추가했습니다.
NJInamdar

6

CRR (Card Range Recognition)에서 일련의 정규식 또는 기타 하드 코딩 된 범위를 사용하는 알고리즘의 단점은 BIN / IIN이 내 경험에서 시간이 지남에 따라 변경된다는 것입니다. 카드의 공동 브랜딩은 진행중인 합병증입니다. 다른 카드 취득자 / 상인은 예를 들어 지리적 위치에 따라 동일한 카드를 다르게 취급해야 할 수도 있습니다.

또한, 지난 몇 년간 더 많은 유통량을 가진 UnionPay 카드를 사용하는 기존 모델은 때때로 더 넓은 범위에 인터리브되는 새로운 범위에 대응하지 않습니다.
일부 국가에서는 특정 지역에서만 사용하도록 제한되어 있으므로 시스템에서 다루어야 할 지역을 아는 것이 도움이 될 수 있습니다. 예를 들어, 범위 62에는 미국의 일부 AAA 하위 범위가 포함되지만 판매자 기반이 미국 이외의 지역 인 경우 62를 모두 UnionPay로 취급 할 수 있습니다.
판매자 위치에 따라 카드를 다르게 취급하라는 요청을받을 수도 있습니다. 예를 들어 특정 영국 카드는 국내에서 직불로 취급하지만 국제적으로 신용으로 취급합니다.

하나의 주요 인수 은행이 유지 관리하는 매우 유용한 규칙 세트가 있습니다. 예 : https://www.barclaycard.co.uk/business/files/BIN-Rules-EIRE.pdf https://www.barclaycard.co.uk/business/files/BIN-Rules-UK.pdf . (업데이트 된 참조에 대한 링크를 제공 한 사용자 덕분에 2017 년 6 월 현재 유효한 링크입니다.) 그러나 이러한 CRR 규칙은 해당 엔티티가 획득 한 판매자에게 적용되는 카드 발급 세계를 나타낼 수 있다는 점에 유의하십시오. 예를 들어 CUP / UPI로 식별 된 범위는 포함되지 않습니다.

이 의견은 자기 띠 (MagStripe) 또는 PKE (팬 키 입력) 시나리오에 적용됩니다. ICC / EMV 세계에서는 상황이 다시 다릅니다.

업데이트 :이 페이지 (및 연결된 WikiPedia 페이지)의 다른 답변은 JCB가 항상 16입니다. 그러나 우리 회사에는 여러 인수 은행 및 지역에서 POS 장치 및 소프트웨어를 인증하는 전담 엔지니어 팀이 있습니다. 이 팀이 JCB에서 보유한 가장 최근의 인증 팩 카드에는 19 개의 긴 PAN에 대한 패스 케이스가있었습니다.


@CaiqueOliveira 님, 업데이트 된 링크를 참조하십시오. 업데이트 된 BIN-Rules 참조에 대한 링크를 제공 한 mac9416 덕분입니다.
MikeRoger

1
업데이트 된 BIN-Rules 참조에 대해 @ mac9416에게 감사합니다.
MikeRoger

5

Usman Y의 답변 스위프트 2.1 버전. print 문을 사용하여 문자열 값으로 호출 확인

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는 카드 체계 감지를위한 이 환상적인 자바 스크립트 라이브러리를 제공했습니다 . 몇 가지 코드 스 니펫을 추가하고 사용 방법을 보여 드리겠습니다.

먼저 웹 페이지에 다음과 같이 포함하십시오

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

둘째, 카드 체계를 감지하기 위해 cardType 기능을 사용하십시오.

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

더 많은 예제와 데모에 대한 참조 링크는 다음과 같습니다.

  1. jquery.payment.js에 대한 스트라이프 블로그
  2. Github 리포지토리

4

신속하게 신용 카드 유형을 감지하는 열거 형을 만들 수 있습니다.

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

CreditCardType 열거 형 값을 리턴하는 CreditCardType.cardTypeForCreditCardNumber ( "# card number") 메소드를 호출하십시오.


3

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

0이 반환되면 신용 카드 유형이 감지되지 않습니다.

신용 카드 입력 필드에 "신용 카드"클래스를 추가해야합니다.


1
기존 답변의 변형
Gajus

1
예, 위 답변의 코드를 사용하여 개선하고 여기에 게시했습니다. downvote 주셔서 감사합니다 ...
ZurabWeb 15:09에

3
(a) 기존 코드의 개선으로 이것을 제안했거나 (b) 적절한 기여를 작성했거나 (c) 정규 표현식을 작성하는 데 사용한 소스를 참조해야합니다.
Gajus

1
Gajus, 나는 그 순간 내가 할 수있는 방식으로 커뮤니티를 도왔다 고 생각합니다. 누군가를 위해 무언가를해야한다고 말하지 말아주십시오. 나는 도움이 될 수있는 일을했다.
ZurabWeb

3

나는 신용 카드 형식과 전화 번호 형식에 대해 꽤 많이 검색했습니다. 좋은 팁을 많이 찾았지만 정확한 욕구에 실제로 맞지 않아서이 코드를 만들었습니다 . 당신은 이것을 다음과 같이 사용합니다 :

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

문제는 특정 구현이 아니라 신용 카드를 확인하는 알고리즘 에 관한 것입니다. 이 코드는 무엇을합니까?
Emil Vikström

2

작은 숟가락 먹이기 :

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

다음은 True함수 이름에 따라 카드가 감지되면 반환되는 Python으로 작성된 일부 부울 함수의 예입니다 .

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

카드 번호의 처음 6 자리 숫자 (초기 MII 숫자 포함)를 발급자 식별 번호 (IIN)라고합니다. 이들은 카드 소지자에게 카드를 발급 한 카드 발급 기관을 식별합니다. 나머지 번호는 카드 발급자가 할당합니다. 카드 번호의 길이는 자릿수입니다. 많은 카드 발급 기관이 카드에 전체 IIN 및 계좌 번호를 인쇄합니다.

위의 사실을 바탕으로 카드 브랜드를 식별하기 위해 JAVA 코드를 보관하고 싶습니다 .

샘플 카드 종류

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

카드 접두사

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

입력 번호에 지정된 접두사가 있는지 확인하십시오.

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

마지막으로 유틸리티 방법

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

참고


1

kotlin에 사용해보십시오. 정규식을 추가하고 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

경기 정규 표현식 규칙 각각의 카드 공급 업체 :

  • (4\d{12}(?:\d{3})?) 비자를 위해.
  • (5[1-5]\d{14}) MasterCard를 위해.
  • (3[47]\d{13}) AMEX를 위해.
  • ((?:5020|5038|6304|6579|6761)\d{12}(?:\d\d)?) 마에스트로.
  • (3(?:0[0-5]|[68][0-9])[0-9]{11}) 다이너스 클럽.
  • (6(?:011|5[0-9]{2})[0-9]{12}) 엑스에 대한.
  • (35[2-8][89]\d\d\d{10}) JCB를 위해.

JCB에 대한 정규식이 잘못되었다고 생각합니다. 예를 들어 3528에서 3589 사이의 처음 네 자리를 모두 허용해야하지만 3570은 허용되지 않습니다.
Gabe

0

https://github.com/bendrucker/creditcards-types/ 를 사용 하여 번호에서 신용 카드 유형을 감지합니다. 내가 만난 한 가지 문제는 테스트 번호 6011 1111 1111 1117을 발견하는 것입니다.

https://www.cybersource.com/developers/other_resources/quick_references/test_cc_numbers/ 에서 6011부터 시작하기 때문에 검색 번호임을 알 수 있습니다. 그러나 신용 카드 유형에서 얻은 결과는 "Maestro"입니다. 저자에게 문제를 열었습니다. 그는 곧 나에게 대답하고이 PDF 문서 제공 https://www.discovernetwork.com/downloads/IPP_VAR_Compliance.pdf 우리는 1111 1111 1117 6011이 발견 신용 카드의 범위에 해당하지 않는 명확하게 볼 수있는 문서에서합니다.


같은 문제가 발생했습니다.이 문제가 해결 되었습니까?
lucasvm1980

@ lucasvm1980 discovernetwork.com pdf 파일이 더 안정적이라고 생각합니다. 숫자 6011 1111 1111 1117은 테스트 번호 일 뿐이며 실제 신용 카드에는이 번호가 없습니다. 그래서 나는 이것에 대해 걱정할 필요가 없다고 생각합니다.
yuxiaomin

일부 Discover 카드에 버그가있는 것 같습니다. 유효한 번호를 시도했는데 해당 오류가 발생합니다.
lucasvm1980

@ lucasvm1980 번호를 제공하고 github에 문제를 제출할 수 있습니까?
yuxiaomin

0

이것을 사용해보십시오.

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
}

사용하다.

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

            }
        });
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.