代码之家  ›  专栏  ›  技术社区  ›  Tom Hawtin - tackline

我如何使用包含空格的信用卡号码?

  •  12
  • Tom Hawtin - tackline  · 技术社区  · 17 年前

    18 回复  |  直到 17 年前
        1
  •  80
  •   cletus    17 年前

    我的观点是,任何拒绝带有空格的信用卡号的Web应用程序都没有发挥作用。当你收到信用卡号码时,很容易做到:

    String ccNumber = ccNumber.replaceAll("[\\s-]+", "");
    

    删除空格和破折号(有些人也使用这些)。然后验证结果。如果你强迫用户删除你可以轻松做到的空格,你只会惹恼他们。

    至于 如何 要验证,这取决于很多因素,比如你使用的是哪个Web框架,你选择了什么验证选项。例如,Struts 1可能会也可能不会使用Apache Commons Validator,而Spring MVC(可能)会使用Spring验证等等。所以我不能确切地告诉你如何验证,但我可以告诉你 什么 以验证。

    不 被拒绝。大多数人会发现:

    4123 0987 8876 2939
    

    许多

    4123098788762939
    

    第二件事是,您以正确的方式显示信用卡号(即使出于安全原因,某些数字被X替换)。我建议你通读一遍 Anatomy of Credit Card Numbers .

    该页面为您提供了数字位数和有效前缀的规则。一个健壮的Web应用程序将实现这些功能 因此,在您尝试使用信用卡号码之前,您可以判断该号码是否无效

    • 15:像个 American Express 卡片即4-6-5,每组之间留有空格;
    • 14:像a Diners Club
    • 13:我从未见过13,但我脑海中浮现的是4-5-4、4-4-5或5-4-4(或可能是3-3-4-3)。

    信用卡号应按照页面中提到的校验和算法进行验证 作为标准验证程序的一部分。该页面具有该例程的Java实现。

    每 绝对极小值 或者,当你的用户中有一部分感到沮丧时,你只是在放弃业务。

    简而言之,有两条简单的规则:

    1. 尽可能宽容用户输入;和
    2. 在提交之前,尽一切可能验证信用卡详细信息。
        2
  •  19
  •   Bill the Lizard    17 年前

    我甚至会去掉所有非数字字符,然后在通过真正的验证运行用户输入之前检查长度是否有效,比如 Luhn's algorithm .

    String ccNumber = input.replaceAll("\\D", "");
    

    从中删除所有非数字 String input .

        3
  •  11
  •   kenj0418    15 年前

    这些人给客户带来不便,仅仅是因为他们(开发人员)懒惰。没有理由不接受信用卡号码、电话号码等任何格式的信息。唯一的限制是理解如何解释值所需的内容。

        4
  •  10
  •   skiphoppy    17 年前

    不幸的是,没有。Java只是无法处理这些要求,因为在x86芯片上模拟Java虚拟机涉及太多的开销,没有空间容纳Perl正则表达式等有用的构造,而Perl正则表达式可以做到这一点:

    $input =~ s/\D//g;
    

        5
  •  8
  •   ChrisW    17 年前

    购物者 以机器喜欢的格式重新输入他们的号码。

    为什么,如果只有一个 可以进行“数据处理”,这样机器本身就可以改变数据格式!或者,如果没有“未经训练”的购物者就好了!唉!

        6
  •  4
  •   user67143    17 年前

    你的问题似乎很奇怪,但我认为它应该像通过验证功能运行用户输入的信用卡号码一样简单,该功能首先会删除所有空格。

    无论是否使用正则表达式,这在任何现代语言中都是相当微不足道的。

        7
  •  4
  •   Pyrolistical    17 年前

    容易的。

    • 您的输入空间是包含所有字符的某个字符集中的字符列表。
    • 您的输出空间是某个仅包含数字的字符集中的字符列表。

    为了解决这个问题,我们创建了一个只包含数字0到9的中间空间。我们可以为这个有限集创建一个新的枚举。我们将称之为我们的手指空间,因为它奇怪地包含与我们手指相同数量的成员。

    1. 将输入空间转换为手指空间
    2. 将手指空间转换为输出空间

    当我们将输入空间缩小到手指空间时,我们只需删除手指空间中找不到的任何字符。从手指空间转换到输出空间更容易。我们只是在输出空间中找到了相同的数字。

    诀窍是让它适用于所有角色集。我还没有弄清楚如何确定某个字符是否与我手指组中的成员匹配。也许我应该把它作为一个问题发布。

        8
  •  2
  •   Robert Greiner    17 年前

    汤姆,

    这个问题在技术上已经解决了,让我们从理论上谈谈。

    这里有两种思想流派。我认为说“如果用户无法理解,那是他们的问题”是不可接受的

    1. 严格遵守用户输入,只接受格式正确的信用卡号码。这需要用户保持在页面上,直到他们把所有事情都做好。

    在我看来,#2是可行的,你可以使用正则表达式(如上所述)从cc#字段中提取所有空格、特殊字符等,并使用户不必再次输入他们的信息。

    无论哪种方式,您都应该通知用户正确的输入表单(即xxxx-xx-xxxxx)

    有关正则表达式的更多提示,请查看正则表达式。信息

    祝你好运,

        9
  •  1
  •   AAA    17 年前

    有很多选择,但最合乎逻辑的似乎是只做一个简单的字符串替换,将所有空格替换为一个封闭字符,即“”。这将把信用卡字符串减少到只有一长串数字。然后就处理掉

        10
  •  1
  •   Jeffrey Hines    17 年前

    本网站上的广告。..只需49.95美元,您就可以拥有与这家在线商店兼容的新特殊键盘。单击此处将新键盘添加到购物车和结账中。退房时,请在指定字段中输入您的信用卡号。请不要在数字之间输入空格,因为我们的商店不知道如何处理数字之间的空格。

        11
  •  1
  •   Orclev    17 年前

    您应该对界面进行建模,以便用户以受控的方式本能地执行输入。简单地说,先问他们要哪种卡,然后在输入表单上输入与卡匹配的格式。例如,假设一张16位的卡,如Visa或万事达卡,显示4个由空格或破折号分隔的输入框,每个输入框限制为4个字符,并在用户键入第四位数字后自动移动到序列中的下一个框。

    卡号:
    [1234] - [1234] - [1234] - [1234]

    卡号:
    [1234] - [123456] - [12345]

        12
  •  1
  •   malcolmm    17 年前

    似乎只有一个人提到了Luhn或mod 10算法

    http://en.wikipedia.org/wiki/Luhn_algorithm

        13
  •  0
  •   Charlie Martin    17 年前

    当然。压缩空间。可能有无数种方法可以做到这一点;我很想使用String.split()在空格上分解它,然后合并得到的四个字符串。或者使用StringBuffer.indexOf()和.delteCharAt()。

    …或者正如Cletus所说,使用replaceAll()。

        14
  •  0
  •   zonkflut    17 年前

    您可以通过以下方式使用javascript验证 onkeypress 事件,检查最后一个字符是否有效,如果不是,则将其删除,甚至可能闪烁一条消息,说明输入了无效字符。这样就永远不会输入无效数字。它还可以以您想要的格式自动输入间隔字符(空格或-)。

        15
  •  0
  •   Community Mohan Dere    6 年前

    早在1998年,我就在一家只允许Visa的商店里写了这对Perl函数(实际上是在Visa)。

    sub mod10_checkdigit
    {
        my($acct) = @_;
        die "invalid account number in BRPS::mod10_checkdigit"
            unless $acct =~ m%^\d+$%;
        my(@digits) = split //, $acct;
        my($len) = scalar(@digits);
        print "# ($len) @digits\n" if ($ENV{PERL_BRPS_DEBUG});
        my($i, $sum, $chk);
        my($mul) = (($len % 2) == 1) ? 1 : 2;
        $len--;
        for ($i = 0; $i < $len; $i++)
        {
            my($val) = $mul * $digits[$i];
            # Note that we need the digital root of the value, but $val is not
            # greater than 18 (because $digits[$i] <= 9 and $mul <= 2).
            $val -= 9 if ($val >= 10);
            $sum += $val;
            print "# $i: $digits[$i] * $mul => $val => $sum\n" if ($ENV{PERL_BRPS_DEBUG});
            $mul = 3 - $mul;
        }
        $chk = 10 - ($sum % 10);
        $chk = 0 if ($chk == 10);
        return $chk;
    }
    
    sub validate_account
    {
        my($acct) = @_;
        # Strip leading and trailing blanks
        $acct =~ s/^\s*(\S.*\S)\s*$/$1/;
        my($clean) = $acct;
        # Check that account number is string of digits, blanks and dashes
        return undef, "account number is not a sequence of digits, blanks and dashes"
            unless $acct =~ m/^[- \d]+$/;
        return undef, "account number is not a Visa account number"
            unless $acct =~ m/^4/;
        # Remove non-digits
        $clean =~ s/\D//g;
        return undef, "account number is neither 13 nor 16 digits"
            unless length($clean) == 16 || length($clean) == 13;
        # Punctuators must be reasonably consistent!
        return undef, "invalid punctuation pattern"
            unless ($acct =~ m/^\d{16}$/o or $acct =~ m/^\d{13}$/o or
                    $acct =~ m/^\d{4}[- ]\d{4}[- ]\d{4}[- ]\d{4}$/o or
                    $acct =~ m/^\d{4}[- ]\d{3}[- ]\d{3}[- ]\d{3}$/o);
        # Determine check digit
        my($chk) = mod10_checkdigit($clean);
        return undef, "check digit on account number is incorrect"
            unless $clean =~ m/$chk$/;
        return $clean, "ok";
    }
    

    允许可信的信用卡号码通过。不难概括处理万事达卡、Discover和美国运通卡。

    咆哮

    不 比如那些坚持让我以内部格式输入数据的网站。Dammit-将数字存储为大整数,并将其作为纯数字字符串发送;这对电脑来说很好。但请允许我输入可识别的人类可读格式,甚至以人类可读格式重新呈现数据。在处理信用卡号码的网站上有太多太多的懒惰。

        16
  •  0
  •   Anthony    17 年前

    如果你指的是javascript,你可以使用“前进到下一个输入”方法:

    这是HTML:

    <form id="ccform" action="cc_submit.php" method="post">
        <fieldset id="ccnumber">
            <input id="firstset" type="text" maxlength="4" />
            <input id="secondset" type="text" maxlength="4" />
            <input id="thirdset" type="text" maxlength="4" />
            <input id="fourthset" type="text" maxlength="4" />
        </fieldset>
    </form>
    

    以下是JS:

    var ccfields;
    
    function moveToNext(e) {
        var field = e.currentTarget;
        var chars = field.value.length;
        var setnumb = Number(field.id.substr(3,1)) - 1;
        if(chars >= 4 && setnumb < 3) {
            ccfields[setnumb + 1].focus();
        }
    }
    
    window.onload = function() {
        ccfields = document.getElementById("ccnumber").getElementsByTagName("input");
        for (var i = 0; i < ccfields.length; i++) {
            ccfields[i].onkeyup = moveToNext;
        }
    };
    

    但一般来说,如果人们看到4个字段,就更容易输入他们的数字,对于那些认为“啊,疯了,我必须用鼠标来输入每个数字”的访问者来说,他们很高兴(或者至少我很高兴)页面足够智能,知道移动到下一个字段。

        17
  •  0
  •   Ritesh M Nayak beny23    17 年前

    解决方案2:使用上述注释中提到的正则表达式。问题是,如果是web应用程序,您将容易受到注入攻击。

        18
  •  0
  •   miku    17 年前

    Java 商标 非常适合服务器端编程,而javascript在客户端可能很有用;例如在验证期间。

    American Express    3400 0100 2000 009
    

    <input ... id="ccid" value="340001002000009">
    <input ... id="ccissuer" value="AMEX">
    

    一旦信用卡信息验证通过验证 在...期间 提交后 .

    在网上可以找到一个简单的javascript函数的例子,它可以对这件事进行一些检查,例如这里 http://www.braemoor.co.uk/software/creditcard.shtml .