Skip to content

Instantly share code, notes, and snippets.

@gabrielbauman
Last active December 13, 2023 04:21
Show Gist options
  • Star 23 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save gabrielbauman/f3db7ce8ae7828fa05b3 to your computer and use it in GitHub Desktop.
Save gabrielbauman/f3db7ce8ae7828fa05b3 to your computer and use it in GitHub Desktop.
A Java enum representing credit card types (Visa, Mastercard etc) that can detect card type from a credit card number.
package com.gabrielbauman.gist;
import java.util.regex.Pattern;
public enum CardType {
UNKNOWN,
VISA("^4[0-9]{12}(?:[0-9]{3}){0,2}$"),
MASTERCARD("^(?:5[1-5]|2(?!2([01]|20)|7(2[1-9]|3))[2-7])\\d{14}$"),
AMERICAN_EXPRESS("^3[47][0-9]{13}$"),
DINERS_CLUB("^3(?:0[0-5]\\d|095|6\\d{0,2}|[89]\\d{2})\\d{12,15}$"),
DISCOVER("^6(?:011|[45][0-9]{2})[0-9]{12}$"),
JCB("^(?:2131|1800|35\\d{3})\\d{11}$"),
CHINA_UNION_PAY("^62[0-9]{14,17}$");
private Pattern pattern;
CardType() {
this.pattern = null;
}
CardType(String pattern) {
this.pattern = Pattern.compile(pattern);
}
public static CardType detect(String cardNumber) {
for (CardType cardType : CardType.values()) {
if (null == cardType.pattern) continue;
if (cardType.pattern.matcher(cardNumber).matches()) return cardType;
}
return UNKNOWN;
}
}
package com.gabrielbauman.gist;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class CardTypeTest {
@Test
public void testDetection() {
assertEquals(CardType.VISA, CardType.detect("4000056655665556"));
assertEquals(CardType.VISA, CardType.detect("4242424242424242"));
assertEquals(CardType.MASTERCARD, CardType.detect("5105105105105100"));
assertEquals(CardType.MASTERCARD, CardType.detect("5200828282828210"));
assertEquals(CardType.MASTERCARD, CardType.detect("5555555555554444"));
assertEquals(CardType.AMERICAN_EXPRESS, CardType.detect("371449635398431"));
assertEquals(CardType.AMERICAN_EXPRESS, CardType.detect("378282246310005"));
assertEquals(CardType.DISCOVER, CardType.detect("6011000990139424"));
assertEquals(CardType.DISCOVER, CardType.detect("6011111111111117"));
assertEquals(CardType.DINERS_CLUB, CardType.detect("30569309025904"));
assertEquals(CardType.DINERS_CLUB, CardType.detect("38520000023237"));
assertEquals(CardType.JCB, CardType.detect("3530111333300000"));
assertEquals(CardType.JCB, CardType.detect("3566002020360505"));
assertEquals(CardType.UNKNOWN, CardType.detect("0000000000000000"));
}
}
@attacomsian
Copy link

attacomsian commented Jul 30, 2019

Just a little correction. You missed the escaped character for DINERS_CLUB. It should be the following:

DINERS_CLUB("^3(?:0[0-5]\\d|095|6\\d{0,2}|[89]\\d{2})\\d{12,15}$")

@gabrielbauman
Copy link
Author

Good catch, thank you! Updating the gist.

@Hdebbech
Copy link

Hdebbech commented Mar 9, 2021

Thank you this is very useful, though the unit test passed only when i used this regex for DINERS_CLUB
^3(?:0[0-5]|[68][0-9])[0-9]{11}$

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment