通过信用卡号码确定信用卡类型?

67

信用卡的种类是否可以仅通过信用卡号码确定?

这样做是否推荐,还是我们应该始终询问客户他们使用的信用卡类型?

我在谷歌上搜索了相关算法,并找到了这个链接:http://cuinl.tripod.com/Tips/o-1.htm ,这可靠吗?


+1 -- 总是想知道Paypal的漂亮的信用卡输入表单是如何工作的。 - Billy ONeal
2
可能是重复的问题:如何根据信用卡号码检测信用卡类型? - Moslem Ben Dhaou
15个回答

32

是的,你提到的网站是正确的。许多网站,包括 Google Checkout,都依赖于卡类型的自动检测。这很方便,使用户界面更简洁(少一个输入框),并节省时间。请继续!


9
为卡类型提供下拉框的唯一原因可能是作为一种错误检查的手段。 - Will Bickford
3
一个下拉菜单或图标列表仍然很有用 - 因为它允许您在输入之前查看公司接受哪些卡类型 - 例如,有些可能不接受美国运通、大来、万事达等。 - Simon_Weaver

21

我听说过一个让客户选择付款方式的好理由(即使你可以自己解决)。这样客户就知道你接受哪些信用卡。


此外,能够进行检查只是一件好事。 - Matt Ball
20
有趣的理由,但我不同意。您可以轻松地使用小图标或文本向用户展示您接受哪些卡,而无需让他们做任何额外的工作。 - EMP

11
作为消费者,我讨厌先选择卡片。我想直接开始输入卡号。
这个问题在Wroblewski的《Web表单设计》第153-154页中有所讨论。它在“不必要的输入”章节的“删除问题”部分中。给出的例子是Paypal,在你输入卡号后会突出显示卡片类型。

如果他们不接受美国运通卡怎么办(这种情况经常发生)?您会列出不接受的信用卡吗? - Brian Agnew
6
Paypal为所有被允许的卡类型提供了图形表示,但是这些图形被虚化显示。当您输入卡号时,匹配的卡会变得更加鲜明可见。 - Nosredna

7

1
http://www.barclaycardbusiness.co.uk/docs/binranges.pdf 是一份包含来自英国银行的卡BIN范围的资料,因此它应该是准确无误的。 - gbjbaanb
@gbjbaanb的评论更新的网址:http://www.barclaycard.co.uk/business/documents/pdfs/bin_rules.pdf - Tao

5

以下是我使用的脚本,适用于当前卡号范围,并对卡号进行有效性检查。

/**
* checks a given string for a valid credit card
* @returns:
*   -1  invalid
*       1   mastercard
*       2   visa
*       3   amex
*       4   diners club
*       5   discover
*       6   enRoute
*       7   jcb
*/
function checkCC(val) {
    String.prototype.startsWith = function (str) {
        return (this.match("^" + str) == str)
    }

    Array.prototype.has=function(v,i){
        for (var j=0;j<this.length;j++){
            if (this[j]==v) return (!i ? true : j);
        }
        return false;
    }

    // get rid of all non-numbers (space etc)
    val = val.replace(/[^0-9]/g, "");

    // now get digits
    var d = new Array();
    var a = 0;
    var len = 0;
    var cval = val;
    while (cval != 0) {
        d[a] = cval%10;
        cval -= d[a];
        cval /= 10;
        a++;
        len++;
    }

    if (len < 13)
        return -1;

    var cType = -1;

    // mastercard
    if (val.startsWith("5")) {
        if (len != 16)
            return -1;
        cType = 1;
    } else
    // visa
    if (val.startsWith("4")) {
        if (len != 16 && len != 13)
            return -1;
        cType = 2;
    } else
    // amex
    if (val.startsWith("34") || val.startsWith("37")) {
        if (len != 15)
            return -1;
        cType = 3;
    } else
    // diners
    if (val.startsWith("36") || val.startsWith("38") || val.startsWith("300") || val.startsWith("301") || val.startsWith("302") || val.startsWith("303") || val.startsWith("304") || val.startsWith("305")) {
        if (len != 14)
        return -1;
        cType = 4;
    } else
    // discover
    if (val.startsWith("6011")) {
        if (len != 15 && len != 16)
            return -1;
        cType = 5;
    } else
    // enRoute
    if (val.startsWith("2014") || val.startsWith("2149")) {
        if (len != 15 && len != 16)
            return -1;
        // any digit check
        return 6;
    } else
    // jcb
    if (val.startsWith("3")) {
        if (len != 16)
        return -1;
        cType = 7;
    } else
    // jcb
    if (val.startsWith("2131") || val.startsWith("1800")) {                                         

        if (len != 15)
        return -1;
        cType = 7;
    } else
    return - 1;
    // invalid cc company

    // lets do some calculation
    var sum = 0;
    var i;
    for (i = 1; i < len; i += 2) {
        var s = d[i] * 2;
        sum += s % 10;
        sum += (s - s%10) /10;
    }

    for (i = 0; i < len; i += 2)
        sum += d[i];

    // musst be %10
    if (sum%10 != 0)
        return - 1;

    return cType;
}

是我的错...我刚想起来使用了那个函数,并且因为客户投诉(一些有效的信用卡号码没有通过)而不得不更新一些异常 - 但实际上是由于长度检查。 - Niko
大多数卡片长度为16#(英国),Maestro卡可以长达19个字符,因此长度检查变得非常麻烦。 - Chris McKee

5

这里是一个关于各种信用卡相关事项的完整C#或VB代码,可以在codeproject上找到。点击此处

  • IsValidNumber(检查信用卡号是否有效)
  • GetCardTypeFromNumber(根据信用卡号获取信用卡类型)
  • GetCardTestNumber(获取信用卡测试号码)
  • PassesLuhnTest(通过Luhn算法验证信用卡号是否正确)

这篇文章已经发布了几年,没有任何负面评论。


4

这是同第一篇帖子提到的算法的PHP版本

<?php
function CreditCardType($CardNo)
{
/*
'*CARD TYPES            *PREFIX           *WIDTH
'American Express       34, 37            15
'Diners Club            300 to 305, 36    14
'Carte Blanche          38                14
'Discover               6011              16
'EnRoute                2014, 2149        15
'JCB                    3                 16
'JCB                    2131, 1800        15
'Master Card            51 to 55          16
'Visa                   4                 13, 16
*/    
//Just in case nothing is found
$CreditCardType = "Unknown";

//Remove all spaces and dashes from the passed string
$CardNo = str_replace("-", "",str_replace(" ", "",$CardNo));

//Check that the minimum length of the string isn't less
//than fourteen characters and -is- numeric
If(strlen($CardNo) < 14 || !is_numeric($CardNo))
    return false;

//Check the first two digits first
switch(substr($CardNo,0, 2))
{
    Case 34: Case 37:
        $CreditCardType = "American Express";
        break;
    Case 36:
        $CreditCardType = "Diners Club";
        break;
    Case 38:
        $CreditCardType = "Carte Blanche";
        break;
    Case 51: Case 52: Case 53: Case 54: Case 55:
        $CreditCardType = "Master Card";
        break;
}

//None of the above - so check the
if($CreditCardType == "Unknown")
{
    //first four digits collectively
    switch(substr($CardNo,0, 4))
    {
        Case 2014:Case 2149:
            $CreditCardType = "EnRoute";
            break;
        Case 2131:Case  1800:
            $CreditCardType = "JCB";
            break;
        Case 6011:
            $CreditCardType = "Discover";
            break;
    }
}

//None of the above - so check the
if($CreditCardType == "Unknown")
{
    //first three digits collectively
    if(substr($CardNo,0, 3) >= 300 && substr($CardNo,0, 3) <= 305)
    {
        $CreditCardType = "American Diners Club";
    }
}

//None of the above -
if($CreditCardType == "Unknown")
{
    //So simply check the first digit
    switch(substr($CardNo,0, 1))
    {
        Case 3:
            $CreditCardType = "JCB";
            break;
        Case 4:
            $CreditCardType = "Visa";
            break;
    }
}

return $CreditCardType;
 }
 ?>

4

维基百科上包含了大部分信用卡前缀的列表。你提供的链接中有一些卡片并未列出。不过,你提供的链接是有效的。

询问信用卡类型的一个原因是为了进行额外的验证,将用户提供的信息与卡号进行比对。


3

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. Stripe博客发布jquery.payment.js
  2. Github代码库

3
你提供的代码中,Discover的BIN/range列表不完整,省略了Diner's Club(现在属于Discover),列出了已经不存在的卡类型,并且应该合并到其他类型(enRoute,Carte Blanche),而且忽略了日益重要的Maestro International卡类型。
正如@Alex所确认的那样,可以从BIN号码确定卡类型,许多公司都这样做,但是要始终准确地做到这一点并不容易:卡品牌不断变化,随着您尝试处理区域性借记卡(爱尔兰的Laser,欧洲的Maestro等),跟踪事物变得更加复杂-我没有找到任何免费和维护良好(正确)的代码或算法。
如@MitMaro所指出,维基百科包含了一个高级别的卡标识符列表,以及一份更具体的BIN号码和范围列表,这是一个很好的起点,正如gbjbaanb所评论的那样,巴克莱银行有一个公开发布的列表(但不知何故似乎没有包括Discover——可能是因为他们不在Discover网络上处理?)
虽然看起来微不足道,但正确的卡片识别算法/方法/函数需要花费时间来维护,因此,除非您的检测程序是非关键性的/信息性的(例如@Simon_Weaver的建议),或者您将付出维护它的努力,否则我建议您跳过自动检测。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接