001/*
002 * jPOS Project [http://jpos.org]
003 * Copyright (C) 2000-2026 jPOS Software SRL
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Affero General Public License as
007 * published by the Free Software Foundation, either version 3 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU Affero General Public License for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018
019package org.jpos.core;
020
021public class DefaultCardValidator implements CardValidator {
022    private static LUHNCalculator DEFAULT_LUHN_CALCULATOR = new DefaultLUHNCalculator();
023    private LUHNCalculator luhnCalculator = DEFAULT_LUHN_CALCULATOR;
024
025    public void validate (Card card) throws InvalidCardException {
026        if (card != null) {
027            String pan = card.getPan();
028            if (pan != null) {
029                if (card.getTrack1() != null && !pan.equals(card.getTrack1().getPan()))
030                    throw new InvalidCardException ("track1 PAN mismatch");
031                if (card.getTrack2() != null && !pan.equals(card.getTrack2().getPan()))
032                    throw new InvalidCardException ("track2 PAN mismatch");
033            }
034            String exp = card.getExp();
035            if (exp != null) {
036                if (card.getTrack1() != null && !exp.equals(card.getTrack1().getExp()))
037                    throw new InvalidCardException ("track1 EXP mismatch");
038                if (card.getTrack2() != null && !exp.equals(card.getTrack2().getExp()))
039                    throw new InvalidCardException ("track2 EXP mismatch");
040            }
041            if (card.getServiceCode() != null) {
042                int mismatch = 0;
043                if (card.hasBothTracks()) {
044                    if (card.getTrack2().getServiceCode() != null) {
045                        if (!card.getTrack2().getServiceCode().equals(card.getServiceCode()))
046                            mismatch++;
047                        if (!card.getTrack2().getServiceCode().equals(card.getTrack1().getServiceCode()))
048                            mismatch++;
049                    }
050                } else if (card.hasTrack2()) {
051                    if (card.getTrack2().getServiceCode() != null) {
052                        if (!card.getTrack2().getServiceCode().equals(card.getServiceCode()))
053                            mismatch++;
054                    }
055                } else if (card.hasTrack1()) {
056                    if (card.getTrack1().getServiceCode() != null) {
057                        if (!card.getTrack1().getServiceCode().equals(card.getServiceCode()))
058                            mismatch++;
059                    }
060                }
061                if (mismatch > 0) {
062                    throw new InvalidCardException(String.format("service code mismatch (%d)", mismatch));
063                }
064            }
065            if (luhnCalculator != null && !luhnCalculator.verify(pan))
066                throw new InvalidCardException ("invalid LUHN");
067        }
068    }
069
070    public void setLuhnCalculator(LUHNCalculator luhnCalculator) {
071        this.luhnCalculator = luhnCalculator;
072    }
073}