Как вы определяете тип кредитной карты по номеру? - PullRequest
494 голосов
/ 16 сентября 2008

Я пытаюсь выяснить, как определить тип кредитной карты, основываясь исключительно на ее номере. Кто-нибудь знает точный, надежный способ найти это?

Ответы [ 26 ]

5 голосов
/ 22 декабря 2014

В распознавании диапазонов карт (CRR), недостатком алгоритмов, использующих ряд регулярных выражений или других жестко закодированных диапазонов, является то, что в моем опыте со временем меняются 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 года, благодаря пользователю, предоставившему ссылку на обновленную ссылку.) Но учтите, что, хотя эти правила CRR могут представлять карту Выпуск юниверса, поскольку он применяется к торговцам, приобретенным этой организацией, он не включает, например, диапазоны, обозначенные как CUP / UPI.

Эти комментарии относятся к сценариям с магнитной полосой (MagStripe) или PKE (Pan Key Entry). Ситуация снова в мире ICC / EMV.

Обновление: другие ответы на этой странице (а также связанная страница WikiPedia) имеют JCB как всегда 16 длинных. Однако в моей компании есть специальная команда инженеров, которая сертифицирует наши POS-устройства и программное обеспечение в нескольких банках-эквайерах и географических регионах. Самый последний пакет сертификации, полученный этой командой от JCB, имел пропускную коробку для 19-часового PAN.

5 голосов
/ 16 сентября 2008

Первые цифры кредитной карты можно использовать для приблизительного определения поставщика:

  • Виза: 49,44 или 47
  • Визовый электрон: 42, 45, 48, 49
  • MasterCard: 51
  • Amex: 34
  • Diners: 30, 36, 38
  • JCB: 35
5 голосов
/ 26 февраля 2014

Не пытайтесь определить тип кредитной карты как часть обработки платежа. Вы рискуете отклонить действительные транзакции.

Если вам необходимо предоставить информацию обработчику платежей (например, объекту кредитной карты 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 все поддерживаемые) схемы карт. На самом деле, вы можете вообще пропустить исключение и использовать по умолчанию самый популярный тип карт. Пусть платежный шлюз / процессор сообщит вам, если в ответ на ваш запрос произошла ошибка проверки.

Реальность такова, что ваш платежный шлюз не заботится о стоимости, которую вы предоставляете .

3 голосов
/ 07 апреля 2016

Swift 2.1 Версия ответа Усмана Y. Используйте оператор 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 ""

}
3 голосов
/ 07 июля 2014

Мое решение с помощью 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 тип кредитной карты не обнаруживается.

класс «кредитная карта» должен быть добавлен в поле ввода кредитной карты.

2 голосов
/ 01 июня 2016

В swift вы можете создать перечисление для определения типа кредитной карты.

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.cardTypeForCreditCardNumber ("# номер карты"), который возвращает значение перечисления CreditCardType.

2 голосов
/ 31 июля 2015

Я довольно долго искал форматирование кредитной карты и номера телефона. Нашел много хороших советов, но ничто не соответствовало моим точным желаниям, поэтому я создал этот бит кода . Вы используете это так:

var sf = smartForm.formatCC(myInputString);
var cardType = sf.cardType;
2 голосов
/ 29 апреля 2015

Stripe предоставил эту фантастическую библиотеку javascript для определения схемы карты. Позвольте мне добавить несколько фрагментов кода и показать, как его использовать.

Сначала включите его на свою веб-страницу как

<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 хранилище
1 голос
/ 27 апреля 2016

Вот пример некоторых булевых функций, написанных на Python, которые возвращают True, если карта обнаружена согласно имени функции.

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 голос
/ 31 января 2014

Просто маленькая ложка кормления:

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

        }

    });
...