Android Open Source - CreditCardEntry Credit Card Util






From Project

Back to project page CreditCardEntry.

License

The source code is released under:

MIT License

If you think the Android project CreditCardEntry listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.devmarvel.creditcardentry.internal;
/*from   w  w w  . j  a v a  2 s  . c  om*/
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.annotation.SuppressLint;
import android.widget.EditText;

import com.devmarvel.creditcardentry.R;
import com.devmarvel.creditcardentry.fields.CreditEntryFieldBase;

@SuppressLint("SimpleDateFormat")
public class CreditCardUtil {

  // See: http://www.regular-expressions.info/creditcard.html
  public static final String REGX_VISA = "^4[0-9]{15}?";// VISA 16
  public static final String REGX_MC = "^5[1-5][0-9]{14}$"; // MC 16
  public static final String REGX_AMEX = "^3[47][0-9]{13}$";// AMEX 15
  public static final String REGX_DISCOVER = "^6(?:011|5[0-9]{2})[0-9]{12}$";// Discover
                                        // 16
  public static final String REGX_DINERS_CLUB = "^3(?:0[0-5]|[68][0-9])[0-9]{11}$";// DinersClub
                                            // 14
                                            // //
                                            // 38812345678901

  public static final int CC_LEN_FOR_TYPE = 4; // number of characters to
                          // determine length

  public static final String REGX_AMEX_REG_TYPE = "^3[47][0-9]{2}$";// AMEX 15
  public static final String REGX_DINERS_CLUB_TYPE = "^3(?:0[0-5]|[68][0-9])[0-9]$";// DinersClub
  public static final String REGX_VISA_TYPE = "^4[0-9]{3}?";// VISA 16
  public static final String REGX_MC_TYPE = "^5[1-5][0-9]{2}$";// MC 16
  public static final String REGX_DISCOVER_TYPE = "^6(?:011|5[0-9]{2})$";// Discover
                                      // 16

  public static String cleanNumber(String number) {
    return number.replaceAll("\\s", "");
  }

  public static CardType findCardType(String number) {

    if (number.length() < CC_LEN_FOR_TYPE) {
      return CardType.INVALID;

    }

    String reg = null;

    for (CardType type : CardType.values()) {
      switch (type) {
      case AMEX:
        reg = REGX_AMEX_REG_TYPE;
        break;
      case DISCOVER:
        reg = REGX_DISCOVER_TYPE;
        break;
      case MASTERCARD:
        reg = REGX_MC_TYPE;
        break;
      case VISA:
        reg = REGX_VISA_TYPE;
        break;
      default:
        break;
      }

      Pattern pattern = Pattern.compile(reg);
      Matcher matcher = pattern.matcher(number.substring(0,
          CC_LEN_FOR_TYPE));

      if (matcher.matches()) {
        return type;
      }
    }

    return CardType.INVALID;
  }

  public static boolean isValidNumber(String number) {
    boolean result = false;

    String cleaned = cleanNumber(number);

    String reg = null;

    switch (findCardType(cleaned)) {
    case AMEX:
      reg = REGX_AMEX;
      break;
    case DISCOVER:
      reg = REGX_DISCOVER;
      break;
    case INVALID:
      return result;
    case MASTERCARD:
      reg = REGX_MC;
      break;
    case VISA:
      reg = REGX_VISA;
      break;
    default:
      return result;
    }

    Pattern pattern = Pattern.compile(reg);
    Matcher matcher = pattern.matcher(cleaned);

    return matcher.matches() && validateCardNumber(cleaned);
  }

  public static boolean validateCardNumber(String cardNumber)
      throws NumberFormatException {
    int sum = 0, digit, addend = 0;
    boolean doubled = false;
    for (int i = cardNumber.length() - 1; i >= 0; i--) {
      digit = Integer.parseInt(cardNumber.substring(i, i + 1));
      if (doubled) {
        addend = digit * 2;
        if (addend > 9) {
          addend -= 9;
        }
      } else {
        addend = digit;
      }
      sum += addend;
      doubled = !doubled;
    }
    return (sum % 10) == 0;
  }

  public static String formatForViewing(String enteredNumber) {
    return formatForViewing(enteredNumber, findCardType(enteredNumber));
  }

  public static String formatForViewing(String enteredNumber, CardType type) {
    String cleaned = cleanNumber(enteredNumber);
    int len = cleaned.length();

    if (len <= CC_LEN_FOR_TYPE)
      return cleaned;

    // NSRange r2; r2.location = NSNotFound;
    // NSRange r3; r3.location = NSNotFound;
    // NSRange r4; r4.location = NSNotFound;
    // NSMutableArray *gaps = [NSMutableArray arrayWithObjects:@"", @"",
    // @"", nil];

    ArrayList<String> gaps = new ArrayList<String>();

    int segmentLengths[] = { 0, 0, 0 };

    switch (type) {
    case VISA:
    case MASTERCARD:
    case DISCOVER: // { 4-4-4-4}
      gaps.add(" ");
      segmentLengths[0] = 4;
      gaps.add(" ");
      segmentLengths[1] = 4;
      gaps.add(" ");
      segmentLengths[2] = 4;
      break;
    case AMEX: // {4-6-5}
      gaps.add(" ");
      segmentLengths[0] = 6;
      gaps.add(" ");
      segmentLengths[1] = 5;
      gaps.add("");
      segmentLengths[2] = 0;
      break;
    default:
      return enteredNumber;
    }

    int end = CC_LEN_FOR_TYPE;
    int start = 0;
    String segment1 = cleaned.substring(0, end);
    start = end;
    end = segmentLengths[0] + end > len ? len : segmentLengths[0] + end;
    String segment2 = cleaned.substring(start, end);
    start = end;
    end = segmentLengths[1] + end > len ? len : segmentLengths[1] + end;
    String segment3 = cleaned.substring(start, end);
    start = end;
    end = segmentLengths[2] + end > len ? len : segmentLengths[2] + end;
    String segment4 = cleaned.substring(start, end);

    String ret = String.format("%s%s%s%s%s%s%s", segment1, gaps.get(0),
        segment2, gaps.get(1), segment3, gaps.get(2), segment4);

    return ret.trim();
  }

  public static int lengthOfStringForType(CardType type) {
    int idx = 0;

    switch (type) {
    case VISA:
    case MASTERCARD:
    case DISCOVER: // { 4-4-4-4}
      idx = 16;
      break;
    case AMEX: // {4-6-5}
      idx = 15;
      break;
    default:
      idx = 0;
    }

    return idx;
  }

  public static int lengthOfFormattedStringForType(CardType type) {
    int idx = 0;

    switch (type) {
    case VISA:
    case MASTERCARD:
    case DISCOVER: // { 4-4-4-4}
      idx = 16 + 3;
      break;
    case AMEX: // {4-6-5}
      idx = 15 + 2;
      break;
    default:
      idx = 0;
    }

    return idx;
  }

  public static int lengthOfFormattedStringTilLastGroupForType(CardType type) {
    int idx = 0;

    switch (type) {
    case VISA:
    case MASTERCARD:
    case DISCOVER: // { 4-4-4-4}
      idx = 16 + 3 - 4;
      break;
    case AMEX: // {4-6-5}
      idx = 15 + 2 - 5;
      break;
    default:
      idx = 0;
    }
    return idx;
  }

  public static String formatExpirationDate(String text) {

    try {
      switch (text.length()) {
      case 1:
        int digit = Integer.parseInt(text);

        if (digit < 2) {
          return text;
        } else {
          return "0" + text + "/";
        }
      case 2:
        int month = Integer.parseInt(text);
        if (month > 12 || month < 1) {
          // Invalid digit
          return text.substring(0, 1);
        } else {
          return text + "/";
        }
      case 3:
        if (text.substring(2, 3).equalsIgnoreCase("/")) {
          return text;
        } else {
          text = text.substring(0, 2) + "/" + text.substring(2, 3);
        }
      case 4:
        int yearDigit = Integer.parseInt(text.substring(3, 4));
        String year = String.valueOf(Calendar.getInstance().get(
            Calendar.YEAR));
        int currentYearDigit = Integer.parseInt(year.substring(2, 3));
        if (yearDigit < currentYearDigit) {
          // Less than current year invalid
          return text.substring(0, 3);
        } else {
          return text;
        }
      case 5:
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
            "MM/yy");
        simpleDateFormat.setLenient(false);
        Date expiry = simpleDateFormat.parse(text);
        if (expiry.before(new Date())) {
          // Invalid exp date
          return text.substring(0, 4);
        } else {
          return text;
        }
      default:
        if (text.length() > 5) {
          return text.substring(0, 5);
        } else {
          return text;
        }
      }

    } catch (ParseException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    // If an exception is thrown we clear out the text
    return "";
  }

  public static int securityCodeValid(CardType type) {
    switch (type) {
    case AMEX:
      return 4;
    case DISCOVER:
    case INVALID:
    case MASTERCARD:
    case VISA:
    default:
      return 3;
    }
  }

  public static int cardImageForCardType(CardType type, boolean back) {
    switch (type) {
    case AMEX:
      if (back) {
        return R.drawable.amex_back;
      } else {
        return R.drawable.amex;
      }
    case DISCOVER:
      if (back) {
        return R.drawable.cc_back;
      } else {
        return R.drawable.discover;
      }
    case MASTERCARD:
      if (back) {
        return R.drawable.cc_back;
      } else {
        return R.drawable.master_card;
      }
    case VISA:
      if (back) {
        return R.drawable.cc_back;
      } else {
        return R.drawable.visa;
      }
    default:
      if (back) {
        return R.drawable.cc_back;
      } else {
        return R.drawable.unknown_cc;
      }
    }
  }

  public static enum CardType {
    VISA, MASTERCARD, AMEX, DISCOVER, INVALID;
  }

  public static interface CreditCardFieldDelegate {
    // When the card type is identified
    public void onCardTypeChange(CardType type);

    public void onCreditCardNumberValid();

    public void onExpirationDateValid();

    // Image should flip to back for security code
    public void onSecurityCodeValid();

    public void onZipCodeValid();

    public void onBadInput(EditText field);

    public void focusOnField(CreditEntryFieldBase field);

    public void focusOnPreviousField(CreditEntryFieldBase field);
  }
}




Java Source Code List

com.devmarvel.creditcardentry.fields.CreditCardText.java
com.devmarvel.creditcardentry.fields.CreditEntryFieldBase.java
com.devmarvel.creditcardentry.fields.ExpDateText.java
com.devmarvel.creditcardentry.fields.SecurityCodeText.java
com.devmarvel.creditcardentry.fields.ZipCodeText.java
com.devmarvel.creditcardentry.internal.CreditCardEntry.java
com.devmarvel.creditcardentry.internal.CreditCardUtil.java
com.devmarvel.creditcardentry.internal.FlipAnimator.java
com.devmarvel.creditcardentry.library.CreditCardForm.java
com.devmarvel.creditcardentry.library.CreditCard.java
com.devmarvel.creditcardentrydemo.MainActivity.java