Skip to content

Instantly share code, notes, and snippets.

@icchan
Last active May 16, 2024 04:13
Show Gist options
  • Save icchan/47d83bacc5113db59fbc to your computer and use it in GitHub Desktop.
Save icchan/47d83bacc5113db59fbc to your computer and use it in GitHub Desktop.
Java Credit Card Number Validator
package net.bubblemix.cardcheck;
/**
* Validator for credit card numbers
* Checks validity and returns card type
*
* @author ian.chen
*/
public class RegexCardValidator {
/**
* Checks if the field is a valid credit card number.
* @param card The card number to validate.
* @return Whether the card number is valid.
*/
public static CardValidationResult isValid(final String cardIn) {
String card = cardIn.replaceAll("[^0-9]+", ""); // remove all non-numerics
if ((card == null) || (card.length() < 13) || (card.length() > 19)) {
return new CardValidationResult(card,"failed length check");
}
if (!luhnCheck(card)) {
return new CardValidationResult(card,"failed luhn check");
}
CardCompany cc = CardCompany.gleanCompany(card);
if (cc == null) return new CardValidationResult(card,"failed card company check");
return new CardValidationResult(card,cc);
}
/**
* Checks for a valid credit card number.
* @param cardNumber Credit Card Number.
* @return Whether the card number passes the luhnCheck.
*/
protected static boolean luhnCheck(String cardNumber) {
// number must be validated as 0..9 numeric first!!
int digits = cardNumber.length();
int oddOrEven = digits & 1;
long sum = 0;
for (int count = 0; count < digits; count++) {
int digit = 0;
try {
digit = Integer.parseInt(cardNumber.charAt(count) + "");
} catch(NumberFormatException e) {
return false;
}
if (((count & 1) ^ oddOrEven) == 0) { // not
digit *= 2;
if (digit > 9) {
digit -= 9;
}
}
sum += digit;
}
return (sum == 0) ? false : (sum % 10 == 0);
}
/**
* Run some tests to show this works
* @param args
*/
public static void main(String[] args) {
String visa = "4444444444444448";
String master = "5500005555555559";
String amex = "371449635398431";
String diners = "36438936438936";
String discover = "6011016011016011";
String jcb = "3566003566003566";
String luhnFail = "1111111111111111";
String invalid = "abcdabcdabcdabcd";
printTest(visa);
printTest(master);
printTest(amex);
printTest(diners);
printTest(discover);
printTest(jcb);
printTest(invalid);
printTest(luhnFail);
}
/**
* Check a card number and print the result
* @param cardIn
*/
private static void printTest(String cardIn) {
CardValidationResult result = RegexCardValidator.isValid(cardIn);
System.out.println(result.isValid() + " : " + (result.isValid()? result.getCardType().getIssuerName(): "") + " : " + result.getMessage() );
}
}
package net.bubblemix.cardcheck;
/**
* enum for card company specifics
*
*/
public enum CardCompany {
VISA ("^4[0-9]{12}(?:[0-9]{3})?$", "VISA"),
MASTERCARD ("^5[1-5][0-9]{14}$", "MASTER"),
AMEX ("^3[47][0-9]{13}$", "AMEX"),
DINERS ("^3(?:0[0-5]|[68][0-9])[0-9]{11}$", "Diners"),
DISCOVER ("^6(?:011|5[0-9]{2})[0-9]{12}$", "DISCOVER"),
JCB ("^(?:2131|1800|35\\d{3})\\d{11}$", "JCB");
private String regex;
private String issuerName;
CardCompany(String regex, String issuerName) {
this.regex = regex;
this.issuerName = issuerName;
}
public boolean matches(String card) {
return card.matches(this.regex);
}
public String getIssuerName() {
return this.issuerName;
}
/**
* get an enum from a card number
* @param card
* @return
*/
public static CardCompany gleanCompany(String card) {
for (CardCompany cc : CardCompany.values()){
if (cc.matches(card)) {
return cc;
}
}
return null;
}
/**
* get an enum from an issuerName
* @param issuerName
* @return
*/
public static CardCompany gleanCompanyByIssuerName(String issuerName) {
for (CardCompany cc : CardCompany.values()){
if (cc.getIssuerName().equals(issuerName)) {
return cc;
}
}
return null;
}
}
package net.bubblemix.cardcheck;
/**
* Container for validation result
*/
public class CardValidationResult {
private boolean valid;
private CardCompany cardType;
private String error;
private String cardNo;
public CardValidationResult(String cardNo, String error) {
this.cardNo = cardNo;
this.error = error;
}
public CardValidationResult(String cardNo, CardCompany cardType) {
this.cardNo = cardNo;
this.valid = true;
this.cardType = cardType;
}
public boolean isValid() {
return valid;
}
public CardCompany getCardType() {
return cardType;
}
public String getError() {
return error;
}
public String cardNo() {
return this.cardNo;
}
public String getMessage() {
return cardNo + " >> " + ((valid) ? ("card: " + this.cardType ): error) ;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment