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

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

我的观点是,任何拒绝带有空格的信用卡号的Web应用程序都无法正常工作。 当您收到信用卡号码时,很容易做到:

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

删除空格和破折号(有些也使用它们)。 然后validation结果。 如果您强制他们删除您可以轻松删除的空间,您只会烦扰您的用户。

至于如何validation,这取决于很多事情,例如您正在使用的Web框架以及您选择的validation选项。 例如Struts 1可能会也可能不会使用Apache Commons Validator,而Spring MVC(可能)会使用Springvalidation等等。 所以我不能确切地告诉你如何validation,但我可以告诉你要validation什么

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

 4123 0987 8876 2939 

比以下更容易阅读:

 4123098788762939 

如果用户错过或错误输入数字并且需要找到他或她的信用卡号码validation失败的原因,那么这一点非常重要。 这篇文章顶部的replaceAll()涵盖了这种情况。

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

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

至于显示它们,取决于数字位数:

  • 16:4组由空格隔开;
  • 15:像美国运通卡一样,即4-6-5,每组之间有空格;
  • 14:像大莱卡一样,即4-6-4,每组之间有空格;
  • 13:从未见过13,但4-5-4或4-4-5或5-4-4(或可能是3-3-3-4)让人想起。

在提交处理作为标准validation例程的一部分之前,应根据页面中提到的校验和算法validation信用卡号。 该页面具有该例程的Java实现。

每个接受信用卡付款的网站都应该将上述所有内容作为绝对最低限度,或者只是丢失业务,因为一部分用户会感到沮丧。

所以简短版本是两个简单的规则:

  1. 用户输入尽可能宽容; 和
  2. 在提交之前,尽一切可能validation信用卡详细信息。

我会去除所有非数字字符,然后在通过像Luhn算法这样的真实validation运行用户输入之前检查长度是否有效。

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

String input删除所有非数字。

网站强迫您以特定格式输入信用卡号(和类似的东西) – 严重惹恼我。

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

您不应该关心我是否输入5555-4444-3333-2222或5555444433332222,如果您不喜欢它们,只需删除破折号 – 与空格相同。 使用电话号码,除非您要自动拨号,否则您可能根本不关心它的格式,因此除非必须,否则不要惹恼您的用户。

很不幸的是,不行。 Java只是无法处理这些要求,因为在x86芯片上模拟Java虚拟机涉及很多开销,没有留下像Perl的正则表达式这样的有用构造的空间,因此可以这样做:

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

Java几年前尝试添加正则表达式,但它们只运行在不再使用的PowerPC芯片上。 问题是所有正则表达式都必须作为字符串包含而不是作为第一类语言构造,因此需要加倍反斜杠,但是每个人都知道反斜杠在x86架构的主操作系统上意味着不同的东西。

我的建议是升级到Perl。 Scheme也被称为能够处理这种情况,并且比竞争对手具有巨大的优势,但Scheme仅在LISP机器上运行。

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

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

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

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

简单。

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

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

然后我们编写两个函数。

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

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

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

汤姆,

问题在技术上得到解决,让我们从理论上谈谈它。

这里有两种思想流派。 我不认为说“如果用户无法弄清楚这是他们的问题”是一个可以接受的答案。

  1. 坚定您的用户输入,只接受格式正确的信用卡号码。 这需要将用户保持在页面上,直到他们完成所有操作。
  2. 通过假设他们的意图并为他们调整输入来更宽容(只需确保给他们一个确认屏幕以validation新输入)。

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

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

根据经验,我倾向于欣赏那些处理用户输入方式更优雅的网站。

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

祝你好运,

– 罗伯特·

有许多选项,但最合乎逻辑的似乎是只做一个简单的字符串替换,用一个封闭的字符替换所有空格即”。 这会将信用卡字符串减少到只有一长串数字……然后就可以了

这个网站上的广告…只需49.95美元,你就可以拥有一个与这个在线商店兼容的新特殊键盘。 点击此处在购物车中添加新键盘并结帐。 退房时,请在指定栏位中输入您的信用卡号码。 请不要输入数字之间的空格,因为我们的商店不知道如何处理数字之间的空格。

我会假设这是一个真正的问题,即使它看起来像某种巨魔或笑话。

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

它应该看起来像页面上的以下内容:

卡号:
[1234] – [1234] – [1234] – [1234]

要么

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

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

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

当然。 压缩空间。 可能有很多方法可以做到; 我很想使用String.split()在空格上分解它,然后连接四个字符串。 或者使用StringBuffer.indexOf()和.delteCharAt()。

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

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

我在一家商店里写了这对Perlfunction,那里只允许Visa(……在Visa,实际上……),1998年。

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

允许合理的信用卡号码通过。 要概括处理Mastercard,Discover,American Express也不难。

胡言乱语

喜欢坚持以内部格式输入数据的网站。 Dammit – 将数字存储为一个大整数并将其作为纯数字字符串发送; 这对计算机来说很好。 但是,让我输入可识别的人类易读格式 – 甚至以人类清晰的格式重新呈现数据。 处理信用卡号码的网站存在太多,太多,太多的懒惰。

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

这是HTML:

 

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

当然,您需要添加一个检查非数字的函数和一个用于获取四个字段并将它们合并为一个字符串以传递回表单的函数。 使用像Jquery这样的js库来确保事件以相同的方式处理并简化遍历输入也是一个不错的主意,这样你就可以使用像“name”这样的属性而不会产生任何混淆。

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

解决方案1:如何只放入4个可以取4位数字的文本框。 就像输入软件的许可证密钥一样。 输入空格字符或制表符后,您可以触发框以更改为下一行。

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

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

有效的信用卡号码的长度在12(例如Maestro)和19(例如Solo,Switch)之间变化。 客户端javascript可以找出卡号是否有效(只有数字(带破折号或空白),适合发行人权限,校验和确定,……)并执行“人类可读”的1:1映射(例如

 American Express 3400 0100 2000 009 

)内部表示,例如

   

一旦信用卡信息validation输入期间通过了validation,就可以将值透明地转换为提交内部forms。

可以在网上找到对该事项进行一些检查的普通javascript函数的示例,例如http://www.braemoor.co.uk/software/creditcard.shtml 。

对于答案的描述非常重要。