Java tutorial
/* * Copyright (c) 2011, Eric McIntyre * All rights reserved. * * This software is under the BSD license. * http://www.opensource.org/licenses/bsd-license.php */ package com.riversoforion.yukon.bankcard; import static org.apache.commons.lang3.Range.between; import static org.apache.commons.lang3.Range.is; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Set; import java.util.TreeSet; import org.apache.commons.lang3.Range; /** * @author macdaddy */ @SuppressWarnings("unchecked") public enum Issuer { /** * Luhn algorithm, 15 digits, valid prefixes: 34, 37 */ AmericanExpress("American Express", LuhnAlgorithm.instance(), 15, between(340000, 349999), between(370000, 379999)), /** * Luhn algorithm, 14 digits, valid prefixes: 300-305 */ DinersClubCarteBlanche("Diners Club Carte Blanche", LuhnAlgorithm.instance(), 14, between(300000, 305999)), /** * Luhn algorithm, 14 digits, valid prefixes: 36 */ DinersClubInternational("Diners Club International", LuhnAlgorithm.instance(), 14, between(360000, 369999)), /** * Luhn algorithm, 16 digits, valid prefixes: 54, 55 */ DinersClubUsCa("Diners Club (US and Canada)", LuhnAlgorithm.instance(), 16, between(540000, 559999)), /** * Luhn algorithm, 16 digits, valid prefixes: 6011, 622126-622925, 644-649, * 65 */ Discover("Discover", LuhnAlgorithm.instance(), 16, between(601100, 601199), between(622126, 622925), between(644000, 649999), between(650000, 659999)), /** * Luhn algorithm, 16 digits, valid prefixes: 3528-3589 */ JapanCreditBureau("JCB", LuhnAlgorithm.instance(), 16, between(352800, 358999)), /** * Luhn algorithm, 16-19 digits, valid prefixes: 6304, 6706, 6771, 6709 */ Laser("Laser", LuhnAlgorithm.instance(), Arrays.asList(16, 17, 18, 19), between(630400, 630499), between(670600, 670699), between(670900, 670999), between(677100, 677199)), /** * Luhn algorithm, 12-19 digits, valid prefixes: 5018, 5020, 5038, 6304, * 6759, 6761, 6762, 6763 */ Maestro("Maestro", LuhnAlgorithm.instance(), Arrays.asList(12, 13, 14, 15, 16, 17, 18, 19), between(501800, 501899), between(502000, 502099), between(503800, 503899), between(630400, 630499), between(675900, 675999), between(676100, 676199), between(676200, 676299), between(676300, 676399)), /** * Luhn algorithm, 16 digits, valid prefixes: 51-55 */ MasterCard("Master Card", LuhnAlgorithm.instance(), 16, between(510000, 559999)), /** * Luhn algorithm, 16, 18, or 19 digits, valid prefixes: 6334, 6767 */ Solo("Solo", LuhnAlgorithm.instance(), Arrays.asList(16, 18, 19), between(633400, 633499), between(676700, 676799)), /** * Luhn algorithm, 16, 18, or 19 digits, valid prefixes: 4903, 4905, 4911, * 4936, 564182, 633110, 6333, 6759 */ Switch("Switch", LuhnAlgorithm.instance(), Arrays.asList(16, 18, 19), between(490300, 490399), between(490500, 490599), between(491100, 491199), between(493600, 493699), is(564182), is(633110), between(633300, 633399), between(675900, 675999)), /** * Luhn algorithm, 16 digits, valid prefixes: 4 */ Visa("Visa", LuhnAlgorithm.instance(), 16, between(400000, 499999)); private static final int IIN_LENGTH = 6; private String description; private CheckDigit checkDigitAlgorithm; private List<Integer> validLengths = new ArrayList<Integer>(); private Set<Range<Integer>> validIinRanges = new TreeSet<Range<Integer>>(); private Issuer(String description, CheckDigit checkDigitAlgorithm, List<Integer> validLengths, Range<Integer>... validIinRanges) { this.description = description; this.checkDigitAlgorithm = checkDigitAlgorithm; this.validLengths.addAll(validLengths); this.validIinRanges.addAll(Arrays.asList(validIinRanges)); } private Issuer(String description, CheckDigit checkDigitAlgorithm, int validLength, Range<Integer>... validIinRanges) { this(description, checkDigitAlgorithm, Arrays.asList(validLength), validIinRanges); } public String getDescription() { return this.description; } public CheckDigit getCheckDigitAlgorithm() { return this.checkDigitAlgorithm; } public List<Integer> getValidLengths() { return this.validLengths; } public Set<Range<Integer>> getValidIinRanges() { return this.validIinRanges; } public void validate(String bankCardNumber) { validateLength(bankCardNumber); validateIin(bankCardNumber); validateCheckDigit(bankCardNumber); } public void validateLength(String bankCardNumber) { int length = bankCardNumber.length(); for (int validLength : this.validLengths) { if (length == validLength) { return; } } throw new BankCardException(String.format("Invalid length for issuer %s: %d", this.name(), length)); } public void validateIin(String bankCardNumber) { String prefix = bankCardNumber.substring(0, IIN_LENGTH); int iin = Integer.parseInt(prefix); for (Range<Integer> range : this.validIinRanges) { if (range.contains(iin)) { return; } } throw new BankCardException(String.format("Invalid prefix for issuer %s: %s", this.name(), prefix)); } public void validateCheckDigit(String bankCardNumber) { this.checkDigitAlgorithm.verify(bankCardNumber); } }