All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.wicket.validation.validator.CreditCardValidator Maven / Gradle / Ivy

Go to download

Wicket is a Java web application framework that takes simplicity, separation of concerns and ease of development to a whole new level. Wicket pages can be mocked up, previewed and later revised using standard WYSIWYG HTML design tools. Dynamic content processing and form handling is all handled in Java code using a first-class component model backed by POJO data beans that can easily be persisted using your favorite technology.

There is a newer version: 10.0.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.wicket.validation.validator;

import org.apache.wicket.validation.IValidatable;
import org.apache.wicket.validation.IValidator;
import org.apache.wicket.validation.ValidationError;

/**
 * Checks if a credit card number is valid. The number will be checked for "American Express",
 * "China UnionPay", "Diners Club Carte Blanche", "Diners Club International",
 * "Diners Club US & Canada", "Discover Card", "JCB", "Laser", "Maestro", "MasterCard", "Solo",
 * "Switch", "Visa" and "Visa Electron". If none of those apply to the credit card number, the
 * credit card number is considered invalid.
 * 
 * 

* Card prefixes and lengths have been taken from Wikipedia. * * @author Johan Compagner * @author Joachim F. Rohde * @since 1.2.6 */ public class CreditCardValidator implements IValidator { private static final long serialVersionUID = 1L; /** */ public static enum CreditCard { /** */ INVALID(null), /** */ AMERICAN_EXPRESS("American Express"), /** */ CHINA_UNIONPAY("China UnionPay"), /** */ DINERS_CLUB_CARTE_BLANCHE("Diners Club Carte Blanche"), /** */ DINERS_CLUB_INTERNATIONAL("Diners Club International"), /** */ DINERS_CLUB_US_AND_CANADA("Diners Club US & Canada"), /** */ DISCOVER_CARD("Discover Card"), /** */ JCB("JCB"), /** */ LASER("Laser"), /** */ MAESTRO("Maestro"), /** */ MASTERCARD("MasterCard"), /** */ SOLO("Solo"), /** */ SWITCH("Switch"), /** */ VISA("Visa"), /** */ VISA_ELECTRON("Visa Electron"); private final String name; CreditCard(String name) { this.name = name; } } /** The ID which represents the credit card institute. */ private CreditCard cardId = CreditCard.INVALID; private boolean failOnUnknown = true; /** * Construct. */ public CreditCardValidator() { } /** * Construct. * * @param failOnUnkown */ public CreditCardValidator(final boolean failOnUnkown) { failOnUnknown = failOnUnkown; } /** * * @return Credit card issuer */ public final CreditCard getCardId() { return cardId; } /** * Allow subclasses to set the card id * * @param cardId */ protected void setCardId(final CreditCard cardId) { this.cardId = cardId; } @Override public void validate(final IValidatable validatable) { final String value = validatable.getValue(); try { if (!isLengthAndPrefixCorrect(value)) { validatable.error(decorate(new ValidationError(this), validatable)); } } catch (final NumberFormatException ex) { validatable.error(decorate(new ValidationError(this), validatable)); } } /** * Allows subclasses to decorate reported errors * * @param error * @param validatable * @return decorated error */ protected ValidationError decorate(ValidationError error, IValidatable validatable) { return error; } /** * Checks if the credit card number can be determined as a valid number. * * @param creditCardNumber * the credit card number as a string * @return TRUE if the credit card number could be determined as a valid number, * else FALSE is returned */ protected boolean isLengthAndPrefixCorrect(String creditCardNumber) { if (creditCardNumber == null) { return false; } // strip spaces and dashes creditCardNumber = creditCardNumber.replaceAll("[ -]", ""); // the length of the credit card number has to be between 12 and 19. // else the number is invalid. if ((creditCardNumber.length() >= 12) && (creditCardNumber.length() <= 19) && isChecksumCorrect(creditCardNumber)) { if ((failOnUnknown == false) || (determineCardId(creditCardNumber) != CreditCard.INVALID)) { return true; } } return false; } /** * Checks if the credit card number can be determined as a valid number. * * @param creditCardNumber * the credit card number as a string * @return TRUE if the credit card number could be determined as a valid number, * else FALSE is returned */ public final CreditCard determineCardId(String creditCardNumber) { if (creditCardNumber == null) { return CreditCard.INVALID; } // strip spaces and dashes creditCardNumber = creditCardNumber.replaceAll("[ -]", ""); // the length of the credit card number has to be between 12 and 19. // else the number is invalid. if ((creditCardNumber.length() >= 12) && (creditCardNumber.length() <= 19) && isChecksumCorrect(creditCardNumber)) { cardId = CreditCard.INVALID; if (cardId == CreditCard.INVALID) { cardId = isAmericanExpress(creditCardNumber); } if (cardId == CreditCard.INVALID) { cardId = isChinaUnionPay(creditCardNumber); } if (cardId == CreditCard.INVALID) { cardId = isDinersClubCarteBlanche(creditCardNumber); } if (cardId == CreditCard.INVALID) { cardId = isDinersClubInternational(creditCardNumber); } if (cardId == CreditCard.INVALID) { cardId = isDinersClubUsAndCanada(creditCardNumber); } if (cardId == CreditCard.INVALID) { cardId = isDiscoverCard(creditCardNumber); } if (cardId == CreditCard.INVALID) { cardId = isJCB(creditCardNumber); } if (cardId == CreditCard.INVALID) { cardId = isLaser(creditCardNumber); } if (cardId == CreditCard.INVALID) { cardId = isMaestro(creditCardNumber); } if (cardId == CreditCard.INVALID) { cardId = isMastercard(creditCardNumber); } if (cardId == CreditCard.INVALID) { cardId = isSolo(creditCardNumber); } if (cardId == CreditCard.INVALID) { cardId = isSwitch(creditCardNumber); } if (cardId == CreditCard.INVALID) { cardId = isVisa(creditCardNumber); } if (cardId == CreditCard.INVALID) { cardId = isVisaElectron(creditCardNumber); } } else { cardId = isUnknown(creditCardNumber); } return cardId; } /** * Can be used (subclassed) to extend the test with a credit card not yet known by the * validator. * * @param creditCardNumber * the credit card number as a string * @return The credit card id of the issuer */ protected CreditCard isUnknown(String creditCardNumber) { return CreditCard.INVALID; } /** * Check if the credit card is an American Express. An American Express number has to start with * 34 or 37 and has to have a length of 15. The number has to be validated with the Luhn * algorithm. * * @param creditCardNumber * the credit card number as a string * @return The credit card id of the issuer */ private CreditCard isAmericanExpress(String creditCardNumber) { if (creditCardNumber.length() == 15 && (creditCardNumber.startsWith("34") || creditCardNumber.startsWith("37"))) { return CreditCard.AMERICAN_EXPRESS; } return CreditCard.INVALID; } /** * Check if the credit card is a China UnionPay. A China UnionPay number has to start with 622 * (622126-622925) and has to have a length between 16 and 19. No further validation takes * place.
*
* * @param creditCardNumber * the credit card number as a string * @return The credit card id of the issuer */ private CreditCard isChinaUnionPay(String creditCardNumber) { if ((creditCardNumber.length() >= 16 && creditCardNumber.length() <= 19) && (creditCardNumber.startsWith("622"))) { int firstDigits = Integer.parseInt(creditCardNumber.substring(0, 6)); if (firstDigits >= 622126 && firstDigits <= 622925) { return CreditCard.CHINA_UNIONPAY; } } return CreditCard.INVALID; } /** * Check if the credit card is a Diners Club Carte Blanche. A Diners Club Carte Blanche number * has to start with a number between 300 and 305 and has to have a length of 14. The number has * to be validated with the Luhn algorithm. * * @param creditCardNumber * the credit card number as a string * @return The credit card id of the issuer */ private CreditCard isDinersClubCarteBlanche(String creditCardNumber) { if (creditCardNumber.length() == 14 && creditCardNumber.startsWith("30")) { int firstDigits = Integer.parseInt(creditCardNumber.substring(0, 3)); if (firstDigits >= 300 && firstDigits <= 305) { return CreditCard.DINERS_CLUB_CARTE_BLANCHE; } } return CreditCard.INVALID; } /** * Check if the credit card is a Diners Club International. A Diners Club International number * has to start with the number 36 and has to have a length of 14. The number has to be * validated with the Luhn algorithm. * * @param creditCardNumber * the credit card number as a string * @return The credit card id of the issuer */ private CreditCard isDinersClubInternational(String creditCardNumber) { if (creditCardNumber.length() == 14 && creditCardNumber.startsWith("36")) { return CreditCard.DINERS_CLUB_INTERNATIONAL; } return CreditCard.INVALID; } /** * Check if the credit card is a Diners Club US & Canada. A Diners Club US & Canada number has * to start with the number 54 or 55 and has to have a length of 16. The number has to be * validated with the Luhn algorithm. * * @param creditCardNumber * the credit card number as a string * @return The credit card id of the issuer */ private CreditCard isDinersClubUsAndCanada(String creditCardNumber) { if (creditCardNumber.length() == 16 && (creditCardNumber.startsWith("54") || creditCardNumber.startsWith("55"))) { return CreditCard.DINERS_CLUB_US_AND_CANADA; } return CreditCard.INVALID; } /** * Check if the credit card is a Discover Card. A Discover Card number has to start with 6011, * 622126-622925, 644-649 or 65 and has to have a length of 16. The number has to be validated * with the Luhn algorithm. * * @param creditCardNumber * the credit card number as a string * @return The credit card id of the issuer */ private CreditCard isDiscoverCard(String creditCardNumber) { if (creditCardNumber.length() == 16 && creditCardNumber.startsWith("6")) { int firstThreeDigits = Integer.parseInt(creditCardNumber.substring(0, 3)); int firstSixDigits = Integer.parseInt(creditCardNumber.substring(0, 6)); if (creditCardNumber.startsWith("6011") || creditCardNumber.startsWith("65") || (firstThreeDigits >= 644 && firstThreeDigits <= 649) || (firstSixDigits >= 622126 && firstSixDigits <= 622925)) { return CreditCard.DISCOVER_CARD; } } return CreditCard.INVALID; } /** * Check if the credit card is a JCB. A JCB number has to start with a number between 3528 and * 3589 and has to have a length of 16. The number has to be validated with the Luhn algorithm. * * @param creditCardNumber * the credit card number as a string * @return The credit card id of the issuer */ private CreditCard isJCB(String creditCardNumber) { if (creditCardNumber.length() == 16) { int firstFourDigits = Integer.parseInt(creditCardNumber.substring(0, 4)); if (firstFourDigits >= 3528 && firstFourDigits <= 3589) { return CreditCard.JCB; } } return CreditCard.INVALID; } /** * Check if the credit card is a Laser. A Laser number has to start with 6304, 6706, 6771 or * 6709 and has to have a length between 16 and 19 digits. The number has to be validated with * the Luhn algorithm. * * @param creditCardNumber * the credit card number as a string * @return The credit card id of the issuer */ private CreditCard isLaser(String creditCardNumber) { if (creditCardNumber.length() >= 16 && creditCardNumber.length() <= 19) { if (creditCardNumber.startsWith("6304") || creditCardNumber.startsWith("6706") || creditCardNumber.startsWith("6771") || creditCardNumber.startsWith("6709")) { return CreditCard.LASER; } } return CreditCard.INVALID; } /** * Check if the credit card is a Maestro. A Maestro number has to start with * 5018,5020,5038,6304,6759,6761 or 6763 and has to have a length between 12 and 19 digits. The * number has to be validated with the Luhn algorithm. * * @param creditCardNumber * the credit card number as a string * @return The credit card id of the issuer */ private CreditCard isMaestro(String creditCardNumber) { if (creditCardNumber.length() >= 12 && creditCardNumber.length() <= 19) { if (creditCardNumber.startsWith("5018") || creditCardNumber.startsWith("5020") || creditCardNumber.startsWith("5038") || creditCardNumber.startsWith("6304") || creditCardNumber.startsWith("6759") || creditCardNumber.startsWith("6761") || creditCardNumber.startsWith("6763")) { return CreditCard.MAESTRO; } } return CreditCard.INVALID; } /** * Check if the credit card is a Solo. A Solo number has to start with 6334 or 6767 and has to * have a length of 16, 18 or 19 digits. The number has to be validated with the Luhn algorithm. * * @param creditCardNumber * the credit card number as a string * @return The credit card id of the issuer */ private CreditCard isSolo(String creditCardNumber) { if ((creditCardNumber.length() == 16) || (creditCardNumber.length() == 18) || (creditCardNumber.length() == 19)) { if (creditCardNumber.startsWith("6334") || creditCardNumber.startsWith("6767")) { return CreditCard.SOLO; } } return CreditCard.INVALID; } /** * Check if the credit card is a Switch. A Switch number has to start with * 4903,4905,4911,4936,564182,633110,6333 or 6759 and has to have a length of 16, 18 or 19 * digits. The number has to be validated with the Luhn algorithm. * * @param creditCardNumber * the credit card number as a string * @return The credit card id of the issuer */ private CreditCard isSwitch(String creditCardNumber) { if ((creditCardNumber.length() == 16 || creditCardNumber.length() == 18 || creditCardNumber.length() == 19)) { if (creditCardNumber.startsWith("4903") || creditCardNumber.startsWith("4905") || creditCardNumber.startsWith("4911") || creditCardNumber.startsWith("4936") || creditCardNumber.startsWith("564182") || creditCardNumber.startsWith("633110") || creditCardNumber.startsWith("6333") || creditCardNumber.startsWith("6759")) { return CreditCard.SWITCH; } } return CreditCard.INVALID; } /** * Check if the credit card is a Visa. A Visa number has to start with a 4 and has to have a * length of 13 or 16 digits. The number has to be validated with the Luhn algorithm. * * @param creditCardNumber * the credit card number as a string * @return The credit card id of the issuer */ private CreditCard isVisa(String creditCardNumber) { if (creditCardNumber.length() == 13 || creditCardNumber.length() == 16) { if (creditCardNumber.startsWith("4")) { return CreditCard.VISA; } } return CreditCard.INVALID; } /** * Check if the credit card is a Visa Electron. A Visa Electron number has to start with * 417500,4917,4913,4508 or 4844 and has to have a length of 16 digits. The number has to be * validated with the Luhn algorithm. * * @param creditCardNumber * the credit card number as a string * @return The credit card id of the issuer */ private CreditCard isVisaElectron(String creditCardNumber) { if (creditCardNumber.length() == 16 && (creditCardNumber.startsWith("417500") || creditCardNumber.startsWith("4917") || creditCardNumber.startsWith("4913") || creditCardNumber.startsWith("4508") || creditCardNumber.startsWith("4844"))) { return CreditCard.VISA_ELECTRON; } return CreditCard.INVALID; } /** * Check if the credit card is a Mastercard. A Mastercard number has to start with a number * between 51 and 55 and has to have a length of 16. The number has to be validated with the * Luhn algorithm. * * @param creditCardNumber * the credit card number as a string * @return The credit card id of the issuer */ private CreditCard isMastercard(String creditCardNumber) { if (creditCardNumber.length() == 16) { int firstTwoDigits = Integer.parseInt(creditCardNumber.substring(0, 2)); if (firstTwoDigits >= 51 && firstTwoDigits <= 55) { return CreditCard.MASTERCARD; } } return CreditCard.INVALID; } /** * Calculates the checksum of a credit card number using the Luhn algorithm (the so-called * "mod 10" algorithm). * * @param creditCardNumber * the credit card number for which the checksum should be calculated * @return TRUE if the checksum for the given credit card number is valid, else * return FALSE * @see Wikipedie - Luhn algorithm */ protected final boolean isChecksumCorrect(final String creditCardNumber) { int nulOffset = '0'; int sum = 0; for (int i = 1; i <= creditCardNumber.length(); i++) { int currentDigit = creditCardNumber.charAt(creditCardNumber.length() - i) - nulOffset; if ((i % 2) == 0) { currentDigit *= 2; currentDigit = currentDigit > 9 ? currentDigit - 9 : currentDigit; sum += currentDigit; } else { sum += currentDigit; } } return (sum % 10) == 0; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy