/*! ******************************************************************************
*
* Pentaho Data Integration
*
* Copyright (C) 2002-2016 by Pentaho : http://www.pentaho.com
*
*******************************************************************************
*
* Licensed 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.pentaho.di.trans.steps.creditcardvalidator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.pentaho.di.core.util.Utils;
import org.pentaho.di.i18n.BaseMessages;
/**
* @author Samatar
* @since 03-Juin-2008
*
*/
public class CreditCardVerifier {
private static Class<?> PKG = CreditCardValidatorMeta.class; // for i18n purposes, needed by Translator2!!
public static final int INVALID = -1;
public static final int VISA = 0;
public static final int MASTERCARD = 1;
public static final int AMERICAN_EXPRESS = 2;
public static final int EN_ROUTE = 3;
public static final int DINERS_CLUB = 4;
public static final int DISCOVER = 5;
public static final int JCB1 = 6;
public static final int JCB2 = 7;
public static final int BANKCARD = 8;
public static final int MAESTRO = 9;
public static final int SOLO = 10;
public static final int SWITCH = 11;
public static final int AIRPLUS = 12;
public static final int LASER = 13;
public static final int VOYAGER = 14;
private static final String[] cardNames = {
"Visa", "Mastercard", "American Express", "En Route", "Diner's CLub/Carte Blanche", "Discover", "JCB1",
"JCB2", "BankCard", "Maestro", "Solo", "Switch", "Airplus", "Laser", "Voyager" };
private static final String[] NotValidCardNames = {
BaseMessages.getString( PKG, "CreditCardValidator.Log.NotValidVisa" ),
BaseMessages.getString( PKG, "CreditCardValidator.Log.NotValidMastercard" ),
BaseMessages.getString( PKG, "CreditCardValidator.Log.NotValidAmericanExpress" ),
BaseMessages.getString( PKG, "CreditCardValidator.Log.NotValidEnRoute" ),
BaseMessages.getString( PKG, "CreditCardValidator.Log.NotValidDiners" ),
BaseMessages.getString( PKG, "CreditCardValidator.Log.NotValidDiscover" ),
BaseMessages.getString( PKG, "CreditCardValidator.Log.NotValidJcb1" ),
BaseMessages.getString( PKG, "CreditCardValidator.Log.NotValidJcb2" ),
BaseMessages.getString( PKG, "CreditCardValidator.Log.NotValidBankCard" ),
BaseMessages.getString( PKG, "CreditCardValidator.Log.NotValidMaestro" ),
BaseMessages.getString( PKG, "CreditCardValidator.Log.NotValidSolo" ),
BaseMessages.getString( PKG, "CreditCardValidator.Log.NotValidSwitch" ),
BaseMessages.getString( PKG, "CreditCardValidator.Log.NotValidAirplus" ),
BaseMessages.getString( PKG, "CreditCardValidator.Log.NotValidLaser" ),
BaseMessages.getString( PKG, "CreditCardValidator.Log.NotValidVoyager" ) };
public static String getCardName( int id ) {
return ( id > -1 && id < cardNames.length ? cardNames[id] : null );
}
public static String getNotValidCardNames( int id ) {
return ( id > -1 && id < NotValidCardNames.length ? NotValidCardNames[id] : null );
}
public static ReturnIndicator CheckCC( String CardNumber ) {
ReturnIndicator ri = new ReturnIndicator();
if ( Utils.isEmpty( CardNumber ) ) {
ri.UnValidMsg = BaseMessages.getString( PKG, "CreditCardValidator.Log.EmptyNumber" );
return ri;
}
Matcher m = Pattern.compile( "[^\\d\\s.-]" ).matcher( CardNumber );
if ( m.find() ) {
ri.UnValidMsg = BaseMessages.getString( PKG, "CreditCardValidator.OnlyNumbers" );
return ri;
}
int cardId = getCardID( CardNumber );
if ( cardId > -1 ) {
if ( luhnValidate( CardNumber ) ) {
ri.CardValid = true;
ri.CardType = getCardName( cardId );
} else {
ri.CardValid = false;
ri.UnValidMsg = getNotValidCardNames( cardId );
}
} else {
// try luhn
// ri.UnValidMsg="This card is unsupported!";
if ( luhnValidate( CardNumber ) ) {
ri.CardValid = true;
} else {
ri.UnValidMsg = BaseMessages.getString( PKG, "CreditCardValidator.Log.CardNotValid" );
}
}
return ri;
}
// The Luhn algorithm is basically a CRC type
// system for checking the validity of an entry.
// All major credit cards use numbers that will
// pass the Luhn check. Also, all of them are based
// on MOD 10.
public static boolean luhnValidate( String numberString ) {
try {
int j = numberString.length();
String[] s1 = new String[j];
for ( int i = 0; i < j; i++ ) {
s1[i] = "" + numberString.charAt( i );
}
int checksum = 0;
for ( int i = s1.length - 1; i >= 0; i -= 2 ) {
int k = 0;
if ( i > 0 ) {
k = Integer.valueOf( s1[i - 1] ).intValue() * 2;
if ( k > 9 ) {
String s = "" + k;
k = Integer.valueOf( s.substring( 0, 1 ) ).intValue() + Integer.valueOf( s.substring( 1 ) ).intValue();
}
checksum += Integer.valueOf( s1[i] ).intValue() + k;
} else {
checksum += Integer.valueOf( s1[0] ).intValue();
}
}
return ( ( checksum % 10 ) == 0 );
} catch ( Exception e ) {
// e.printStackTrace();
return false;
}
}
public static int getCardID( String number ) {
int valid = INVALID;
String digit1 = number.substring( 0, 1 );
String digit2 = number.substring( 0, 2 );
String digit3 = number.substring( 0, 3 );
String digit4 = number.substring( 0, 4 );
if ( isNumber( number ) ) {
if ( digit4.equals( "4903" )
|| digit4.equals( "4905" ) || digit4.equals( "4911" ) || digit4.equals( "4936" )
|| digit4.equals( "564182" ) || digit4.equals( "633110" ) || digit4.equals( "6333" )
|| digit4.equals( "6759" ) ) {
if ( number.length() == 16 || number.length() == 18 || number.length() == 19 ) {
/*
* ----* SWITCH card prefix = 4903,4905,4911,4936,564182,633110,6333,6759* -------- length = 16,18,19
*/
valid = SWITCH;
}
} else if ( digit4.equals( "6304" )
|| digit4.equals( "6706" ) || digit4.equals( "6771" ) || digit4.equals( "6709" ) ) {
if ( number.length() >= 16 && number.length() <= 19 ) {
/*
* ----* LASER card prefix = 6304, 6706, 6771, 6709* --------
*/
valid = LASER;
}
} else if ( digit1.equals( "4" ) ) {
if ( number.length() == 13 || number.length() == 16 ) {
/*
* ----* VISA prefix=4* ---- length=13 or 16 (can be 15 too!?! maybe)
*/
valid = VISA;
}
} else if ( digit2.compareTo( "51" ) >= 0 && digit2.compareTo( "55" ) <= 0 ) {
if ( number.length() == 16 ) {
valid = MASTERCARD;
}
} else if ( digit2.equals( "34" ) || digit2.equals( "37" ) ) {
if ( number.length() == 15 ) {
/*
* ----* AMEX prefix=34 or 37* ---- length=15
*/
valid = AMERICAN_EXPRESS;
}
} else if ( digit4.equals( "2014" ) || digit4.equals( "2149" ) ) {
if ( number.length() == 15 ) {
/*
* -----* ENROUTE prefix=2014 or 2149* ----- length=15
*/
valid = EN_ROUTE;
}
} else if ( digit2.equals( "36" )
|| digit2.equals( "38" ) || ( digit3.compareTo( "300" ) >= 0 && digit3.compareTo( "305" ) <= 0 ) ) {
if ( number.length() == 14 ) {
/*
* -----* DCLUB prefix=300 ... 305 or 36 or 38* ----- length=14
*/
valid = DINERS_CLUB;
}
} else if ( digit4.equals( "6011" ) ) {
if ( number.length() == 16 ) {
/*
* ----* DISCOVER card prefix = 6011* -------- length = 16
*/
valid = DISCOVER;
}
} else if ( digit1.equals( "3" ) ) {
if ( number.length() == 16 ) {
/*
* ----* JCB1 card prefix = 3* -------- length = 16
*/
valid = JCB1;
}
} else if ( digit4.equals( "2131" ) || digit4.equals( "1800" ) ) {
if ( number.length() == 15 ) {
/*
* ----* JCB2 card prefix = 2131, 1800* -------- length = 15
*/
valid = JCB2;
}
} else if ( digit4.equals( "5610" )
|| digit4.equals( "560221" ) || digit4.equals( "560222" ) || digit4.equals( "560223" )
|| digit4.equals( "560224" ) || digit4.equals( "560225" ) ) {
if ( number.length() == 16 ) {
/*
* ----* BANKCARD card prefix = 56* -------- length = 16
*/
valid = BANKCARD;
}
} else if ( digit4.equals( "5018" )
|| digit4.equals( "5020" ) || digit4.equals( "5038" ) || digit4.equals( "6304" )
|| digit4.equals( "6759" ) || digit4.equals( "6761" ) || digit4.equals( "6763" ) ) {
if ( number.length() == 12 || number.length() == 13 || number.length() >= 14 && number.length() <= 19 ) {
/*
* ----* MAESTRO card prefix = 5020,6* -------- length = 16
*/
valid = MAESTRO;
}
} else if ( digit4.equals( "6334" ) || digit4.equals( "6767" ) ) {
if ( number.length() == 16 || number.length() == 18 || number.length() == 19 ) {
/*
* ----* SOLO card prefix = 6334, 6767* -------- length = 16,18,19
*/
valid = SOLO;
}
} else if ( digit3.equals( "192" ) || digit3.equals( "122" ) ) {
/*
* ----* AIRLUS card prefix = 192, 122* --------
*/
valid = AIRPLUS;
} else if ( digit4.equals( "8699" ) ) {
if ( number.length() == 15 ) {
/*
* ----* VOYAGER card prefix = 6011* -------- length = 15
*/
valid = VOYAGER;
}
}
}
return valid;
}
public static boolean isNumber( String n ) {
try {
Double.valueOf( n ).doubleValue();
return true;
} catch ( NumberFormatException e ) { // ignore this exception
return false;
}
}
}