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

Java 如何使用包含空格的信用卡号?,java,string,usability,Java,String,Usability,一些奇特的网站在检测到未经培训的购物者输入信用卡/借记卡号码时会显示一个错误对话框,因为该号码打印在他们的卡上并带有空格。是否有可能以某种方式编写一个Java web应用程序,用空格处理这些数字,就好像它们是正确的一样?当然。压缩空间。可能有无数种方法可以做到这一点;我会尝试使用String.split()在空格上分解它,然后将得到的四个字符串合并。或者使用StringBuffer.indexOf()和.delteCharAt() …或者正如克莱特斯所说,使用replaceAll()。有很多选择

一些奇特的网站在检测到未经培训的购物者输入信用卡/借记卡号码时会显示一个错误对话框,因为该号码打印在他们的卡上并带有空格。是否有可能以某种方式编写一个Java web应用程序,用空格处理这些数字,就好像它们是正确的一样?

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


…或者正如克莱特斯所说,使用replaceAll()。

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

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

String ccNumber = ccNumber.replaceAll("[\\s-]+", "");
删除空格和破折号(有些人也使用空格和破折号)。然后验证结果。如果你强迫你的用户删除你可以轻松做到的空格,你只会惹恼他们

至于如何验证,这取决于很多因素,比如您使用的是哪种Web框架,以及您选择了哪些验证选项。例如,Struts1可能会也可能不会使用ApacheCommonsValidator,而SpringMVC可能会使用SpringValidation等等。因此,我不能确切地告诉您如何验证,但我可以告诉您要验证的内容

第一件事是带有空格的CC编号不应被拒绝。大多数人会发现:

4123 0987 8876 2939
比以下内容更容易阅读:

4123098788762939
如果用户遗漏或错误输入一个数字,并且需要找出他或她的信用卡号未通过验证的原因,这一点非常重要。本文顶部的replaceAll()介绍了这种情况

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

该页面为您提供了位数和有效前缀的规则。一个健壮的Web应用程序将实现这些,因此您可以在尝试使用信用卡号码之前判断该号码是否无效。向支付网关提交信用卡详细信息可能需要30秒(或更长时间),因此,在您尽可能确定付款将被接受之前,您不应该这样做。否则会提供非常糟糕的用户体验。如果失败1-2次,用户完全有可能放弃,而不是等待

至于显示它们,这取决于数字的多少:

  • 16:4组,每组4个,由一个空间隔开
  • 15:像一张卡片,即4-6-5,每组之间有一个空格
  • 14:像一张卡片,即4-6-4,每组之间有一个空格
  • 13:从来没有见过13,但脑海中浮现出4-5-4或4-4-5或5-4-4(或可能是3-3-3-4)
在作为标准验证例行程序的一部分提交处理之前,应根据页面中提到的校验和算法验证信用卡号。该页面具有该例程的Java实现

每一个接受信用卡支付的网站都应该将上述所有内容作为绝对最低要求来做,否则,当你的用户感到沮丧时,你只是在放弃业务

因此,简短的版本是两条简单的规则:

  • 对用户输入尽可能宽容;及
  • 在提交之前,尽一切可能验证信用卡详细信息

  • 你的问题似乎很奇怪,但我认为这应该很容易,就像通过验证功能运行用户输入的信用卡号一样,首先会删除所有空白


    这在任何使用或不使用regex的现代语言中都是非常微不足道的。

    不幸的是,这就是为什么那些花哨的网站需要向未经培训的购物者显示一个错误对话框:强制购物者以机器喜欢的格式重新输入他们的号码


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

    那些强迫你以特定格式输入信用卡号码(以及类似内容)的网站让我非常恼火

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


    你不必在意我输入的是5555-4444-3333-2222还是5555444433332222,如果你不喜欢破折号,就把它们去掉——空格也是一样。对于电话号码,除非你要自动拨号,否则你可能根本不在乎它是什么格式,所以除非你必须这样做,否则不要打扰你的用户。

    我会尽量去掉所有非数字字符,然后在通过真正的验证运行用户输入之前检查长度是否有效


    字符串输入中去掉所有非数字,不幸的是,没有。Java无法满足这些要求,因为在x86芯片上模拟Java虚拟机涉及的开销太大,没有空间容纳像Perl正则表达式这样的有用构造,它可以这样做:

    $input =~ s/\D//g;
    
    几年前,Java曾尝试添加正则表达式,但它们只在不再使用的PowerPC芯片上运行。问题是所有正则表达式都必须作为字符串包含,而不是作为第一类语言构造,并且
    $input =~ s/\D//g;
    
    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";
    }
    
    <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>
    
    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;
        }
    };
    
    American Express    3400 0100 2000 009
    
    <input ... id="ccid" value="340001002000009">
    <input ... id="ccissuer" value="AMEX">