Regex credit card number tests

非 Y 不嫁゛ 提交于 2019-11-26 15:08:24
Alexander Pavlov

Remove all , and - and other non-digits from the string first.

Then use this regex that matches Visa, MasterCard, American Express, Diners Club, Discover, and JCB cards:

^(?:4[0-9]{12}(?:[0-9]{3})?|[25][1-7][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$

ajithparamban

Common credit card vendor regular expressions:

  • Amex Card: ^3[47][0-9]{13}$
  • BCGlobal: ^(6541|6556)[0-9]{12}$
  • Carte Blanche Card: ^389[0-9]{11}$
  • Diners Club Card: ^3(?:0[0-5]|[68][0-9])[0-9]{11}$
  • Discover Card: ^65[4-9][0-9]{13}|64[4-9][0-9]{13}|6011[0-9]{12}|(622(?:12[6-9]|1[3-9][0-9]|[2-8][0-9][0-9]|9[01][0-9]|92[0-5])[0-9]{10})$
  • Insta Payment Card: ^63[7-9][0-9]{13}$
  • JCB Card: ^(?:2131|1800|35\d{3})\d{11}$
  • KoreanLocalCard: ^9[0-9]{15}$
  • Laser Card: ^(6304|6706|6709|6771)[0-9]{12,15}$
  • Maestro Card: ^(5018|5020|5038|6304|6759|6761|6763)[0-9]{8,15}$
  • Mastercard: ^(5[1-5][0-9]{14}|2(22[1-9][0-9]{12}|2[3-9][0-9]{13}|[3-6][0-9]{14}|7[0-1][0-9]{13}|720[0-9]{12}))$
  • Solo Card: ^(6334|6767)[0-9]{12}|(6334|6767)[0-9]{14}|(6334|6767)[0-9]{15}$
  • Switch Card: ^(4903|4905|4911|4936|6333|6759)[0-9]{12}|(4903|4905|4911|4936|6333|6759)[0-9]{14}|(4903|4905|4911|4936|6333|6759)[0-9]{15}|564182[0-9]{10}|564182[0-9]{12}|564182[0-9]{13}|633110[0-9]{10}|633110[0-9]{12}|633110[0-9]{13}$
  • Union Pay Card: ^(62[0-9]{14,17})$
  • Visa Card: ^4[0-9]{12}(?:[0-9]{3})?$
  • Visa Master Card: ^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14})$

The accepted answer is great, but to accommodate the new MasterCard BIN, I believe that it would need to be updated to:

^(?:4[0-9]{12}(?:[0-9]{3})?|[25][1-7][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$

(the critical piece being [25][1-7][0-9]{14}, since the first digit can now be either a 2 or a 5 and the second digit can be up to 7)

Please correct me if I'm wrong!

For Rupay Debit Card: ^6[0-9]{15}$

2019

DO. NOT. USE. REGEX !!! (with 3 exclamation marks)


From the comments, I must highlight PeteWiFi's comment:

Just a friendly warning, you're in for a world of hurt if you try and match specific schemes and card lengths this way. For example, Switch hasn't existed since 2002, Laser was withdrawn in 2014, Visa are due to issue 19 digit cards and MasterCard are now issuing in the 2xxxxx ranges, just to highlight a couple of issues with this approach. A regex is good for a basic "does it look like a card number" but not much beyond that.

If you want to use regex just to know the card brand for visual use (display Visa logo or label), that is fine. But if your code logic depends on it, then don't use regex, and don't use 3rd party plugin/library!

Regex detecting card numbers is quick & easy (so appealing, I know!). But, in the long run, your project will run into many serious & hard-to-solve bugs. Card issuers keep introducing new card number patterns, or withdraw old ones, or may completely close down. Who knows.


Solution

Build your own solution (preferably non-regex) based on some official pages that's frequently updated, like this page on wikipedia.

As for the "-", ".", "space", and all other noise, simply remove all these non-digits, you can use this (Based on this answer):

$number = preg_replace("/[^0-9]/", "", "4111-1111 1111.1111");
// Output: 4111111111111111

Not convinced yet?

This page goes into deep technical details why regex is hell. (Notice the artical used the word "hell" because once you're in you can't go out)

Regx for Rupay card :

(508[5-9][0-9]{12})|(6069[8-9][0-9]{11})|(607[0-8][0-9]{12})|(6079[0-8][0-9]{11})|(608[0-5][0-9]{12})|(6521[5-9][0-9]{11})|(652[2-9][0-9]{12})|(6530[0-9]{12})|(6531[0-4][0-9]{11})

using bin series : 508500 – 508999, 606985 – 606999, 607000 - 607899, 607900 - 607984, 608001 -- 608500, 652150 --- 652199, 652200 --- 652999, 653000 --- 653099, 653100 --- 653149,

In addition to all above, here's a regex for new MasterCards, that includes 2221-2720 BINs:

^5[1-5][0-9]{0,14}|^(222[1-9]|2[3-6]\\d{2}|27[0-1]\\d|2720)[0-9]{0,12}

Note, this regex will match if user starts typing card digits, that correspond to MasterCard. For example, if user types "222185" then the regex will match, because there is no other type of card that starts with "2221". This regex might come handy if you want to display card type while typing first digits of the card.

Alternatively, if you want "post factum" matching, you can change the last part from {0,14} and {0,12} to {14} and {12}:

^5[1-5][0-9]{14}|^(222[1-9]|2[3-6]\\d{2}|27[0-1]\\d|2720)[0-9]{12}

I came up with a regex that allows for dashes and spaces. Test it here: https://regex101.com/r/Rx2iWD/1

To allow commas (which I think is unusual), just add it to the sep definition.

In PHP:

$ccPatt = '/
    (?(DEFINE)
        (?<sep> [ -]?)
    )
    (?<!\d)(?:
      \d{4} (?&sep) \d{4} (?&sep) \d{4} (?&sep) \d{4}               # 16 digits
    | \d{3} (?&sep) \d{3} (?&sep) \d{3} (?&sep) \d (?&sep) \d{3}    # 13 digits
    | \d{4} (?&sep) \d{6} (?&sep) \d{4}                             # 14 digits
    | \d{4} (?&sep) \d{6} (?&sep) \d{5}                             # 15 digit card
    )(?!\d)
/xu';

First Data validates 15 digits for Amex and 16 for visa, mc, discover, diners, and jcb so I only send the card number to them if the number is 15 or 16 digits long using this:

^[0-9]{15}(?:[0-9]{1})?$

Regex for Leading Card Networks

Master Card(2-Bin, 5-Bin both):"(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}"

Visa: "^4[0-9]{6,}$"

Diner's Club: "(^30[0-5][0-9]{11}$)|(^(36|38)[0-9]{12}$)"

American Express: "^[34|37][0-9]{14}$"

JCB: "(^3[0-9]{15}$)|(^(2131|1800)[0-9]{11}$)"

Discover: "^6011-?\d{4}-?\d{4}-?\d{4}$"

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!