You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by jd...@apache.org on 2009/11/08 08:50:07 UTC
svn commit: r833843 - in /wicket/trunk/wicket/src:
main/java/org/apache/wicket/validation/validator/CreditCardValidator.java
test/java/org/apache/wicket/validation/validator/CreditCardValidatorTest.java
Author: jdonnerstag
Date: Sun Nov 8 07:50:07 2009
New Revision: 833843
URL: http://svn.apache.org/viewvc?rev=833843&view=rev
Log:
fixed CreditCardValidator accepts invalid inputs
Issue: WICKET-2552
Added:
wicket/trunk/wicket/src/test/java/org/apache/wicket/validation/validator/CreditCardValidatorTest.java
Modified:
wicket/trunk/wicket/src/main/java/org/apache/wicket/validation/validator/CreditCardValidator.java
Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/validation/validator/CreditCardValidator.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/validation/validator/CreditCardValidator.java?rev=833843&r1=833842&r2=833843&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/validation/validator/CreditCardValidator.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/validation/validator/CreditCardValidator.java Sun Nov 8 07:50:07 2009
@@ -19,27 +19,586 @@
import org.apache.wicket.validation.IValidatable;
/**
- * Performs the so-called "mod 10" algorithm to check the validity of credit card numbers such as
- * VISA.
+ * 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.
+ *
* <p>
- * In addition to this, the credit card number can be further validated by its length and prefix,
- * but those properties depend upon the credit card type, and such validation is not performed by
- * this validator.
+ * Card prefixes and lengths have been taken from <a
+ * href="http://en.wikipedia.org/w/index.php?title=Bank_card_number&oldid=322132931">Wikipedia</a>.
*
* @author Johan Compagner
+ * @author Joachim F. Rohde
* @since 1.2.6
*/
public class CreditCardValidator extends AbstractValidator<String>
{
private static final long serialVersionUID = 1L;
+ /** The credit card number, which should be validated. */
+ private String creditCardNumber = null;
+
+ /** The ID which represents the credit card institute. */
+ private int cardId = -1;
+
+ /** */
+ public static final int INVALID = -1;
+ public static final int AMERICAN_EXPRESS = 0;
+ public static final int CHINA_UNIONPAY = 1;
+ public static final int DINERS_CLUB_CARTE_BLANCHE = 2;
+ public static final int DINERS_CLUB_INTERNATIONAL = 3;
+ public static final int DINERS_CLUB_US_AND_CANADA = 4;
+ public static final int DISCOVER_CARD = 5;
+ public static final int JCB = 6;
+ public static final int LASER = 7;
+ public static final int MAESTRO = 8;
+ public static final int MASTERCARD = 9;
+ public static final int SOLO = 10;
+ public static final int SWITCH = 11;
+ public static final int VISA = 12;
+ public static final int VISA_ELECTRON = 13;
+
+ private static final String[] creditCardNames = { "American Express", "China UnionPay",
+ "Diners Club Carte Blanche", "Diners Club International", "Diners Club US & Canada",
+ "Discover Card", "JCB", "Laser", "Maestro", "MasterCard", "Solo", "Switch", "Visa",
+ "Visa Electron" };
+
/**
* @see AbstractValidator#onValidate(IValidatable)
*/
@Override
protected void onValidate(IValidatable<String> validatable)
{
- String input = (validatable.getValue());
+ creditCardNumber = validatable.getValue();
+ if (!isLengthAndPrefixCorrect(creditCardNumber))
+ {
+ error(validatable);
+ }
+ }
+
+ /**
+ * Checks if the credit card number can be determined as a valid number.
+ *
+ * @param creditCardNumber
+ * the credit card number as a string
+ * @return <code>TRUE</code> if the credit card number could be determined as a valid number,
+ * else <code>FALSE</code> is returned
+ */
+ private boolean isLengthAndPrefixCorrect(String creditCardNumber)
+ {
+ if (creditCardNumber != null)
+ {
+ // 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 != null && creditCardNumber.length() >= 12 &&
+ creditCardNumber.length() <= 19)
+ {
+ if (isAmericanExpress(creditCardNumber))
+ {
+ return true;
+ }
+ else if (isChinaUnionPay(creditCardNumber))
+ {
+ return true;
+ }
+ else if (isDinersClubCarteBlanche(creditCardNumber))
+ {
+ return true;
+ }
+ else if (isDinersClubInternational(creditCardNumber))
+ {
+ return true;
+ }
+ else if (isDinersClubUsAndCanada(creditCardNumber))
+ {
+ return true;
+ }
+ else if (isDiscoverCard(creditCardNumber))
+ {
+ return true;
+ }
+ else if (isJCB(creditCardNumber))
+ {
+ return true;
+ }
+ else if (isLaser(creditCardNumber))
+ {
+ return true;
+ }
+ else if (isMaestro(creditCardNumber))
+ {
+ return true;
+ }
+ else if (isMastercard(creditCardNumber))
+ {
+ return true;
+ }
+ else if (isSolo(creditCardNumber))
+ {
+ return true;
+ }
+ else if (isSwitch(creditCardNumber))
+ {
+ return true;
+ }
+ else if (isVisa(creditCardNumber))
+ {
+ return true;
+ }
+ else if (isVisaElectron(creditCardNumber))
+ {
+ return true;
+ }
+ else if (isUnknown(creditCardNumber))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * 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 <code>TRUE</code> if the credit card number seems to be a valid American Express
+ * number. Else <code>FALSE</code> will be returned
+ */
+ protected boolean isUnknown(String creditCardNumber)
+ {
+ return false;
+ }
+
+ /**
+ * 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
+ * alorithm.
+ *
+ * @param creditCardNumber
+ * the credit card number as a string
+ * @return <code>TRUE</code> if the credit card number seems to be a valid American Express
+ * number. Else <code>FALSE</code> will be returned
+ */
+ private boolean isAmericanExpress(String creditCardNumber)
+ {
+ cardId = CreditCardValidator.INVALID;
+ boolean returnValue = false;
+
+ if (creditCardNumber.length() == 15 &&
+ (creditCardNumber.startsWith("34") || creditCardNumber.startsWith("37")))
+ {
+ if (isChecksumCorrect(creditCardNumber))
+ {
+ cardId = CreditCardValidator.AMERICAN_EXPRESS;
+ returnValue = true;
+ }
+ }
+
+ return returnValue;
+ }
+
+ /**
+ * 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.<br/>
+ * <br/>
+ *
+ * @param creditCardNumber
+ * the credit card number as a string
+ * @return <code>TRUE</code> if the credit card number seems to be a valid China UnionPay
+ * number. Else <code>FALSE</code> will be returned.
+ */
+ private boolean isChinaUnionPay(String creditCardNumber)
+ {
+ cardId = CreditCardValidator.INVALID;
+ boolean returnValue = false;
+
+ if ((creditCardNumber.length() >= 16 && creditCardNumber.length() <= 19) &&
+ (creditCardNumber.startsWith("622")))
+ {
+ int firstDigits = Integer.parseInt(creditCardNumber.substring(0, 5));
+ if (firstDigits >= 622126 && firstDigits <= 622925)
+ {
+ cardId = CreditCardValidator.CHINA_UNIONPAY;
+ returnValue = true;
+ }
+ }
+
+ return returnValue;
+ }
+
+ /**
+ * 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 alorithm.
+ *
+ * @param creditCardNumber
+ * the credit card number as a string
+ * @return <code>TRUE</code> if the credit card number seems to be a valid Diners Club Carte
+ * Blanche number. Else <code>FALSE</code> will be returned
+ */
+ private boolean isDinersClubCarteBlanche(String creditCardNumber)
+ {
+ cardId = CreditCardValidator.INVALID;
+ boolean returnValue = false;
+
+ if (creditCardNumber.length() == 14 && creditCardNumber.startsWith("30"))
+ {
+ int firstDigits = Integer.parseInt(creditCardNumber.substring(0, 3));
+ if (firstDigits >= 300 && firstDigits <= 305 && isChecksumCorrect(creditCardNumber))
+ {
+ cardId = CreditCardValidator.DINERS_CLUB_CARTE_BLANCHE;
+ returnValue = true;
+ }
+ }
+
+ return returnValue;
+ }
+
+ /**
+ * 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 alorithm.
+ *
+ * @param creditCardNumber
+ * the credit card number as a string
+ * @return <code>TRUE</code> if the credit card number seems to be a valid Diners Club
+ * International number. Else <code>FALSE</code> will be returned
+ */
+ private boolean isDinersClubInternational(String creditCardNumber)
+ {
+ cardId = CreditCardValidator.INVALID;
+ boolean returnValue = false;
+
+ if (creditCardNumber.length() == 14 && creditCardNumber.startsWith("36") &&
+ isChecksumCorrect(creditCardNumber))
+ {
+ cardId = CreditCardValidator.DINERS_CLUB_INTERNATIONAL;
+ returnValue = true;
+ }
+
+ return returnValue;
+ }
+
+ /**
+ * 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 alorithm.
+ *
+ * @param creditCardNumber
+ * the credit card number as a string
+ * @return <code>TRUE</code> if the credit card number seems to be a valid Diners Club US &
+ * Canada number. Else <code>FALSE</code> will be returned
+ */
+ private boolean isDinersClubUsAndCanada(String creditCardNumber)
+ {
+ cardId = CreditCardValidator.INVALID;
+ boolean returnValue = false;
+
+ if (creditCardNumber.length() == 16 &&
+ (creditCardNumber.startsWith("54") || creditCardNumber.startsWith("55")) &&
+ isChecksumCorrect(creditCardNumber))
+ {
+ cardId = CreditCardValidator.DINERS_CLUB_US_AND_CANADA;
+ returnValue = true;
+ }
+
+ return returnValue;
+ }
+
+ /**
+ * 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 alorithm.
+ *
+ * @param creditCardNumber
+ * the credit card number as a string
+ * @return <code>TRUE</code> if the credit card number seems to be a valid Discover Card number.
+ * Else <code>FALSE</code> will be returned
+ */
+ private boolean isDiscoverCard(String creditCardNumber)
+ {
+ cardId = CreditCardValidator.INVALID;
+ boolean returnValue = false;
+
+ if (creditCardNumber.length() == 16 && creditCardNumber.startsWith("6") &&
+ isChecksumCorrect(creditCardNumber))
+ {
+ 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))
+ {
+ cardId = CreditCardValidator.DISCOVER_CARD;
+ returnValue = true;
+ }
+ }
+
+ return returnValue;
+ }
+
+ /**
+ * 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 alorithm.
+ *
+ * @param creditCardNumber
+ * the credit card number as a string
+ * @return <code>TRUE</code> if the credit card number seems to be a valid JCB number. Else
+ * <code>FALSE</code> will be returned
+ */
+ private boolean isJCB(String creditCardNumber)
+ {
+ cardId = CreditCardValidator.INVALID;
+ boolean returnValue = false;
+
+ if (creditCardNumber.length() == 16 && isChecksumCorrect(creditCardNumber))
+ {
+ int firstFourDigits = Integer.parseInt(creditCardNumber.substring(0, 4));
+ if (firstFourDigits >= 3528 && firstFourDigits <= 3589)
+ {
+ cardId = CreditCardValidator.JCB;
+ returnValue = true;
+ }
+ }
+
+ return returnValue;
+ }
+
+ /**
+ * 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 alorithm.
+ *
+ * @param creditCardNumber
+ * the credit card number as a string
+ * @return <code>TRUE</code> if the credit card number seems to be a valid Laser number. Else
+ * <code>FALSE</code> will be returned
+ */
+ private boolean isLaser(String creditCardNumber)
+ {
+ cardId = CreditCardValidator.INVALID;
+ boolean returnValue = false;
+
+ if (creditCardNumber.length() >= 16 && creditCardNumber.length() <= 19 &&
+ isChecksumCorrect(creditCardNumber))
+ {
+ if (creditCardNumber.startsWith("6304") || creditCardNumber.startsWith("6706") ||
+ creditCardNumber.startsWith("6771") || creditCardNumber.startsWith("6709"))
+ {
+ cardId = CreditCardValidator.LASER;
+ returnValue = true;
+ }
+ }
+
+ return returnValue;
+ }
+
+ /**
+ * 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 alorithm.
+ *
+ * @param creditCardNumber
+ * the credit card number as a string
+ * @return <code>TRUE</code> if the credit card number seems to be a valid Maestro number. Else
+ * <code>FALSE</code> will be returned
+ */
+ private boolean isMaestro(String creditCardNumber)
+ {
+ cardId = CreditCardValidator.INVALID;
+ boolean returnValue = false;
+
+ if (creditCardNumber.length() >= 12 && creditCardNumber.length() <= 19 &&
+ isChecksumCorrect(creditCardNumber))
+ {
+ if (creditCardNumber.startsWith("5018") || creditCardNumber.startsWith("5020") ||
+ creditCardNumber.startsWith("5038") || creditCardNumber.startsWith("6304") ||
+ creditCardNumber.startsWith("6759") || creditCardNumber.startsWith("6761") ||
+ creditCardNumber.startsWith("6763"))
+ {
+ cardId = CreditCardValidator.MAESTRO;
+ returnValue = true;
+ }
+ }
+
+ return returnValue;
+ }
+
+ /**
+ * 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 alorithm.
+ *
+ * @param creditCardNumber
+ * the credit card number as a string
+ * @return <code>TRUE</code> if the credit card number seems to be a valid Solo number. Else
+ * <code>FALSE</code> will be returned
+ */
+ private boolean isSolo(String creditCardNumber)
+ {
+ cardId = CreditCardValidator.INVALID;
+ boolean returnValue = false;
+
+ if ((creditCardNumber.length() == 16 || creditCardNumber.length() == 18 || creditCardNumber.length() == 19) &&
+ isChecksumCorrect(creditCardNumber))
+ {
+ if (creditCardNumber.startsWith("6334") || creditCardNumber.startsWith("6767"))
+ {
+ cardId = CreditCardValidator.SOLO;
+ returnValue = true;
+ }
+ }
+
+ return returnValue;
+ }
+
+ /**
+ * 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 alorithm.
+ *
+ * @param creditCardNumber
+ * the credit card number as a string
+ * @return <code>TRUE</code> if the credit card number seems to be a valid Switch number. Else
+ * <code>FALSE</code> will be returned
+ */
+ private boolean isSwitch(String creditCardNumber)
+ {
+ cardId = CreditCardValidator.INVALID;
+ boolean returnValue = false;
+
+ if ((creditCardNumber.length() == 16 || creditCardNumber.length() == 18 || creditCardNumber.length() == 19) &&
+ isChecksumCorrect(creditCardNumber))
+ {
+ 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"))
+ {
+ cardId = CreditCardValidator.SWITCH;
+ returnValue = true;
+ }
+ }
+
+ return returnValue;
+ }
+
+ /**
+ * 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 alorithm.
+ *
+ * @param creditCardNumber
+ * the credit card number as a string
+ * @return <code>TRUE</code> if the credit card number seems to be a valid Visa number. Else
+ * <code>FALSE</code> will be returned
+ */
+ private boolean isVisa(String creditCardNumber)
+ {
+ cardId = CreditCardValidator.INVALID;
+ boolean returnValue = false;
+
+ if (creditCardNumber.length() == 13 || creditCardNumber.length() == 16)
+ {
+ if (creditCardNumber.startsWith("4"))
+ {
+ cardId = CreditCardValidator.SWITCH;
+ returnValue = true;
+ }
+ }
+
+ return returnValue;
+ }
+
+ /**
+ * 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 alorithm.
+ *
+ * @param creditCardNumber
+ * the credit card number as a string
+ * @return <code>TRUE</code> if the credit card number seems to be a valid Visa Electron number.
+ * Else <code>FALSE</code> will be returned
+ */
+ private boolean isVisaElectron(String creditCardNumber)
+ {
+ cardId = CreditCardValidator.INVALID;
+ boolean returnValue = false;
+
+ if (creditCardNumber.length() == 16 &&
+ (creditCardNumber.startsWith("417500") || creditCardNumber.startsWith("4917") ||
+ creditCardNumber.startsWith("4913") || creditCardNumber.startsWith("4508") || creditCardNumber.startsWith("4844")))
+ {
+ cardId = CreditCardValidator.VISA_ELECTRON;
+ returnValue = true;
+ }
+
+ return returnValue;
+ }
+
+ /**
+ * 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 alorithm.
+ *
+ * @param creditCardNumber
+ * the credit card number as a string
+ * @return <code>TRUE</code> if the credit card number seems to be a valid Mastercard number.
+ * Else <code>FALSE</code> will be returned
+ */
+ private boolean isMastercard(String creditCardNumber)
+ {
+ cardId = CreditCardValidator.INVALID;
+ boolean returnValue = false;
+
+ if (creditCardNumber.length() == 16 && isChecksumCorrect(creditCardNumber))
+ {
+ int firstTwoDigits = Integer.parseInt(creditCardNumber.substring(0, 2));
+ if (firstTwoDigits >= 51 && firstTwoDigits <= 55)
+ {
+ cardId = CreditCardValidator.MASTERCARD;
+ returnValue = true;
+ }
+ }
+
+ return returnValue;
+ }
+
+ /**
+ * Just used for debugging purposes.<br>
+ * Due to re-branding (e.g. Switch was re-branded as Maestro in mid 2007) some rules might
+ * overlap, but those overlappings are not considered. So it might happen, that a Switch-card is
+ * identified as a Maestro. <br>
+ * So you shouldn't rely on the name which is returned here.
+ *
+ * @return the name of the credit card if it could be determined, else an empty string
+ */
+ private String getCardName()
+ {
+ return (cardId > -1 && cardId < creditCardNames.length ? creditCardNames[cardId] : "");
+ }
+
+ /**
+ * 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 <code>TRUE</code> if the checksum for the given credit card number is valid, else
+ * return <code>FALSE</code>
+ * @see <a href="http://en.wikipedia.org/wiki/Luhn_algorithm">Wikipedie - Luhn algorithm</a>
+ */
+ private boolean isChecksumCorrect(String creditCardNumber)
+ {
+ String input = creditCardNumber;
String numberToCheck = input.replaceAll("[ -]", "");
int nulOffset = '0';
int sum = 0;
@@ -57,9 +616,7 @@
sum += currentDigit;
}
}
- if (!((sum % 10) == 0))
- {
- error(validatable);
- }
+
+ return (sum % 10) == 0;
}
}
Added: wicket/trunk/wicket/src/test/java/org/apache/wicket/validation/validator/CreditCardValidatorTest.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/test/java/org/apache/wicket/validation/validator/CreditCardValidatorTest.java?rev=833843&view=auto
==============================================================================
--- wicket/trunk/wicket/src/test/java/org/apache/wicket/validation/validator/CreditCardValidatorTest.java (added)
+++ wicket/trunk/wicket/src/test/java/org/apache/wicket/validation/validator/CreditCardValidatorTest.java Sun Nov 8 07:50:07 2009
@@ -0,0 +1,164 @@
+/*
+ * 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 junit.framework.TestCase;
+
+import org.apache.wicket.validation.IValidatable;
+import org.apache.wicket.validation.Validatable;
+
+/**
+ * Tests a few valid and invalid credit card numbers.
+ *
+ * @author Joachim F. Rohde
+ */
+public class CreditCardValidatorTest extends TestCase
+{
+ /**
+ * Constructor.
+ */
+ public CreditCardValidatorTest()
+ {
+ super();
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param name
+ */
+ public CreditCardValidatorTest(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Tests a couple of credit card numbers that shouldn't be valid.
+ */
+ public void testInvalidCreditCardNumbers()
+ {
+ // null value
+ CreditCardValidator test = new CreditCardValidator();
+ IValidatable<String> validatable = new Validatable(null);
+ test.onValidate(validatable);
+ assertEquals(false, validatable.isValid());
+
+ // too short
+ validatable = new Validatable("9845");
+ test.onValidate(validatable);
+ assertEquals(false, validatable.isValid());
+
+ // too long
+ validatable = new Validatable("1234678910111213141516");
+ test.onValidate(validatable);
+ assertEquals(false, validatable.isValid());
+
+ // contains a char
+ validatable = new Validatable("3782822X6310005");
+ test.onValidate(validatable);
+ assertEquals(false, validatable.isValid());
+
+ // invalid number
+ validatable = new Validatable("840898920205250");
+ test.onValidate(validatable);
+ assertEquals(false, validatable.isValid());
+ }
+
+ /**
+ * Tests a couple of credit card numbers that should be valid. Those numbers has been taken from
+ * https://www.paypal.com/en_US/vhelp/paypalmanager_help/credit_card_numbers.htm
+ */
+ public void testValidCreditCardNumbers()
+ {
+ // American Express
+ CreditCardValidator test = new CreditCardValidator();
+ IValidatable<String> validatable = new Validatable("378282246310005");
+ test.onValidate(validatable);
+ assertEquals(true, validatable.isValid());
+
+ // American Express
+ validatable = new Validatable("371449635398431");
+ test.onValidate(validatable);
+ assertEquals(true, validatable.isValid());
+
+ // American Express Corporate
+ validatable = new Validatable("378734493671000");
+ test.onValidate(validatable);
+ assertEquals(true, validatable.isValid());
+
+ // American Express Corporate with dashes and spaces (should be filtered
+ // and are therefor legal)
+ validatable = new Validatable("378 - 7344-9367 1000");
+ test.onValidate(validatable);
+ assertEquals(true, validatable.isValid());
+
+ // Diners Club
+ validatable = new Validatable("30569309025904");
+ test.onValidate(validatable);
+ assertEquals(true, validatable.isValid());
+
+ // Discover
+ validatable = new Validatable("6011111111111117");
+ test.onValidate(validatable);
+ assertEquals(true, validatable.isValid());
+
+ // Discover
+ validatable = new Validatable("6011000990139424");
+ test.onValidate(validatable);
+ assertEquals(true, validatable.isValid());
+
+ // JCB
+ validatable = new Validatable("3530111333300000");
+ test.onValidate(validatable);
+ assertEquals(true, validatable.isValid());
+
+ // JCB
+ validatable = new Validatable("3566002020360505");
+ test.onValidate(validatable);
+ assertEquals(true, validatable.isValid());
+
+ // Mastercard
+ validatable = new Validatable("5555555555554444");
+ test.onValidate(validatable);
+ assertEquals(true, validatable.isValid());
+
+ // Mastercard
+ validatable = new Validatable("5105105105105100");
+ test.onValidate(validatable);
+ assertEquals(true, validatable.isValid());
+
+ // Visa
+ validatable = new Validatable("4111111111111111");
+ test.onValidate(validatable);
+ assertEquals(true, validatable.isValid());
+
+ // Visa
+ validatable = new Validatable("4012888888881881");
+ test.onValidate(validatable);
+ assertEquals(true, validatable.isValid());
+
+ // Visa
+ validatable = new Validatable("4222222222222");
+ test.onValidate(validatable);
+ assertEquals(true, validatable.isValid());
+
+ // Switch / Solo
+ validatable = new Validatable("6331101999990016");
+ test.onValidate(validatable);
+ assertEquals(true, validatable.isValid());
+ }
+}