Regex для определения кредитных карт в Android

Я действительно новичок в регулярном выражении, но я думаю, что моя проблема может выйти за рамки этого в настоящий момент. Как говорится в названии, я пытаюсь определить, является ли кредитная карта визой, amex, master card и т. Д.

Я просмотрел этот пост, который дал регулярное выражение для каждого из типов карт:

Как вы определяете тип кредитной карты на основе номера?

Это код, который я использовал, но он ничего не делает:

etCCNum.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { Log.d("DEBUG", "beforeTextChanged : "+s); } @Override public void afterTextChanged(Editable s) { Pattern pattern = Pattern.compile("^6(?:011|5[0-9]{2})[0-9]{3,}$"); Log.d("DEBUG", "afterTextChanged : "+s); String ccNum = s.toString(); Matcher matcher = pattern.matcher(ccNum); if(matcher.matches()){ Log.d("DEBUG", "afterTextChanged : discover"); } } }); 

Регулярное выражение в функции pattern.compile предназначено для определения карт Discover в соответствии с вышеприведенным сообщением. Я заметил, что я действительно не могу заставить ничего работать, кроме «^» в регулярном выражении (т. Е. («^ 4» – visa, «^ 6001»), однако этого явно недостаточно для редактирования Я думаю, что это может быть проблемой с моей Java, но я запускаю Java 7

Мне может потребоваться задать новый вопрос, но мне также интересно, как регулярное выражение может использоваться для правильного интервала между различными кредитными картами, даже если пользователь возвращается и редактирует номер (xxxx xxxx xxxx xxxx)

EDIT: Добавлен журнал DEBUG сверху. Мой ввод – это несколько цифр, которые должны ассоциироваться с определенными кредитными картами. В настоящее время я использую приведенный ниже код Eagle Eye (который также должен работать для обнаружения того, что вход является одним из типов карт):

Final ArrayList listOfPattern = new ArrayList ();

 String ptVisa = "^4[0-9]{6,}$"; listOfPattern.add(ptVisa); String ptMasterCard = "^5[1-5][0-9]{5,}$"; listOfPattern.add(ptMasterCard); String ptAmeExp = "^3[47][0-9]{5,}$"; listOfPattern.add(ptAmeExp); String ptDinClb = "^3(?:0[0-5]|[68][0-9])[0-9]{4,}$"; listOfPattern.add(ptDinClb); String ptDiscover = "^6(?:011|5[0-9]{2})[0-9]{3,}$"; listOfPattern.add(ptDiscover); String ptJcb = "^(?:2131|1800|35[0-9]{3})[0-9]{3,}$"; listOfPattern.add(ptJcb); etCCNum.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { Log.d("DEBUG", "beforeTextChanged : "+s); } @Override public void afterTextChanged(Editable s) { Log.d("DEBUG", "afterTextChanged : "+s); String ccNum = s.toString(); for(String p:listOfPattern){ if(ccNum.matches(p)){ Log.d("DEBUG", "afterTextChanged : discover"); break; } } } }); 

Журнал:

 01-29 15:16:41.932 26194-26194/com.xx D/DEBUG﹕ beforeTextChanged : 01-29 15:16:41.933 26194-26194/com.xx D/DEBUG﹕ afterTextChanged : 4 01-29 15:16:46.815 26194-26194/com.xx D/DEBUG﹕ beforeTextChanged : 4 01-29 15:16:46.816 26194-26194/com.xx D/DEBUG﹕ afterTextChanged : 01-29 15:16:50.925 26194-26194/com.xx D/DEBUG﹕ beforeTextChanged : 01-29 15:16:50.926 26194-26194/com.xx D/DEBUG﹕ afterTextChanged : 6 01-29 15:16:51.542 26194-26194/com.xx D/DEBUG﹕ beforeTextChanged : 6 01-29 15:16:51.543 26194-26194/com.xx D/DEBUG﹕ afterTextChanged : 60 01-29 15:16:51.883 26194-26194/com.xx D/DEBUG﹕ beforeTextChanged : 60 01-29 15:16:51.883 26194-26194/com.xx D/DEBUG﹕ afterTextChanged : 600 01-29 15:16:52.928 26194-26194/com.xx D/DEBUG﹕ beforeTextChanged : 600 01-29 15:16:52.929 26194-26194/com.xx D/DEBUG﹕ afterTextChanged : 6001 01-29 15:16:55.781 26194-26194/com.xx D/DEBUG﹕ beforeTextChanged : 6001 01-29 15:16:55.782 26194-26194/com.xx D/DEBUG﹕ afterTextChanged : 600 01-29 15:16:56.206 26194-26194/com.xx D/DEBUG﹕ beforeTextChanged : 600 01-29 15:16:56.206 26194-26194/com.xx D/DEBUG﹕ afterTextChanged : 60 01-29 15:16:57.659 26194-26194/com.xx D/DEBUG﹕ beforeTextChanged : 60 01-29 15:16:57.660 26194-26194/com.xx D/DEBUG﹕ afterTextChanged : 605 01-29 15:16:59.297 26194-26194/com.xx D/DEBUG﹕ beforeTextChanged : 605 01-29 15:16:59.298 26194-26194/com.xx D/DEBUG﹕ afterTextChanged : 60 01-29 15:16:59.527 26194-26194/com.xx D/DEBUG﹕ beforeTextChanged : 60 01-29 15:16:59.527 26194-26194/com.xx D/DEBUG﹕ afterTextChanged : 6 01-29 15:17:00.314 26194-26194/com.xx D/DEBUG﹕ beforeTextChanged : 6 01-29 15:17:00.314 26194-26194/com.xx D/DEBUG﹕ afterTextChanged : 65 

Вы ожидаете, что журнал «обнаружит» несколько раз появится для разных цифр, которые я ввел. В приведенном выше журнале показано, как я печатаю первые несколько цифр карточки визы и карточки для открытия.

EDIT ANSWER FOUND: я просто не печатал достаточно цифр для распознавания карты!

Согласно одному из ответов в потоке, карты могут быть подтверждены на основе следующих данных.

Виза: ^4[0-9]{6,}$ Номера карт Visa начинаются с 4.

MasterCard: ^5[1-5][0-9]{5,}$ Номера MasterCard начинаются с номеров с 51 по 55, но это будет определять только кредитные карты MasterCard; Есть другие карты, выпущенные с использованием системы MasterCard, которые не попадают в этот диапазон IIN.

American Express: ^3[47][0-9]{5,}$ Номера карт American Express начинаются с 34 или 37.

Diners Club: ^3(?:0[0-5]|[68][0-9])[0-9]{4,}$ Номера карт Diners Club начинаются с 300 до 305, 36 или 38. Diners Club, которые начинаются с 5 и имеют 16 цифр. Это совместное предприятие Diners Club и MasterCard и должно обрабатываться как MasterCard.

Откройте: ^6(?:011|5[0-9]{2})[0-9]{3,}$ Номера карт начинаются с 6011 или 65.

JCB: ^(?:2131|1800|35[0-9]{3})[0-9]{3,}$ Карты JCB начинаются с 2131, 1800 или 35.

Поэтому вам нужно создать отдельный шаблон для каждого случая. Вы можете сделать следующее.

 ArrayList<String> listOfPattern=new ArrayList<String>(); String ptVisa = "^4[0-9]{6,}$"; listOfPattern.add(ptVisa); String ptMasterCard = "^5[1-5][0-9]{5,}$"; listOfPattern.add(ptMasterCard); String ptAmeExp = "^3[47][0-9]{5,}$"; listOfPattern.add(ptAmeExp); String ptDinClb = "^3(?:0[0-5]|[68][0-9])[0-9]{4,}$"; listOfPattern.add(ptDinClb); String ptDiscover = "^6(?:011|5[0-9]{2})[0-9]{3,}$"; listOfPattern.add(ptDiscover); String ptJcb = "^(?:2131|1800|35[0-9]{3})[0-9]{3,}$"; listOfPattern.add(ptJcb); } 

а потом,

 @Override public void afterTextChanged(Editable s) { Log.d("DEBUG", "afterTextChanged : "+s); String ccNum = s.toString(); for(String p:listOfPattern){ if(ccNum.matches(p)){ Log.d("DEBUG", "afterTextChanged : discover"); break; } } } 

И для вашего последнего вопроса, Следующий поток должен помочь вам.

Форматировать кредитную карту в текстовом редакторе в android

РЕДАКТИРОВАТЬ:

Если номер карты составляет 16 цифр, например, после применения логики для добавления пробелов после 4 цифр, вам необходимо удалить эти пробелы при обработке фактического номера карты. Тогда будет работать только вышеприведенная логика.

Надеюсь это поможет.

Используйте следующий класс для проверки вашей карты.

 public class Validator { public static final byte VISA = 0; public static final byte MASTERCARD = 1; public static final byte AMEX = 2; public static final byte DINERS_CLUB = 3; public static final byte CARTE_BLANCHE = 4; public static final byte DISCOVER = 5; public static final byte ENROUTE = 6; public static final byte JCB = 7; public static boolean validate(final String credCardNumber, final byte type) { String creditCard = credCardNumber.trim(); boolean applyAlgo = false; switch (type) { case VISA: // VISA credit cards has length 13 - 15 // VISA credit cards starts with prefix 4 if (creditCard.length() >= 13 && creditCard.length() <= 16 && creditCard.startsWith("4")) { applyAlgo = true; } break; case MASTERCARD: // MASTERCARD has length 16 // MASTER card starts with 51, 52, 53, 54 or 55 if (creditCard.length() == 16) { int prefix = Integer.parseInt(creditCard.substring(0, 2)); if (prefix >= 51 && prefix <= 55) { applyAlgo = true; } } break; case AMEX: // AMEX has length 15 // AMEX has prefix 34 or 37 if (creditCard.length() == 15 && (creditCard.startsWith("34") || creditCard .startsWith("37"))) { applyAlgo = true; } break; case DINERS_CLUB: case CARTE_BLANCHE: // DINERSCLUB or CARTEBLANCHE has length 14 // DINERSCLUB or CARTEBLANCHE has prefix 300, 301, 302, 303, 304, // 305 36 or 38 if (creditCard.length() == 14) { int prefix = Integer.parseInt(creditCard.substring(0, 3)); if ((prefix >= 300 && prefix <= 305) || creditCard.startsWith("36") || creditCard.startsWith("38")) { applyAlgo = true; } } break; case DISCOVER: // DISCOVER card has length of 16 // DISCOVER card starts with 6011 if (creditCard.length() == 16 && creditCard.startsWith("6011")) { applyAlgo = true; } break; case ENROUTE: // ENROUTE card has length of 16 // ENROUTE card starts with 2014 or 2149 if (creditCard.length() == 16 && (creditCard.startsWith("2014") || creditCard .startsWith("2149"))) { applyAlgo = true; } break; case JCB: // JCB card has length of 16 or 15 // JCB card with length 16 starts with 3 // JCB card with length 15 starts with 2131 or 1800 if ((creditCard.length() == 16 && creditCard.startsWith("3")) || (creditCard.length() == 15 && (creditCard .startsWith("2131") || creditCard .startsWith("1800")))) { applyAlgo = true; } break; default: throw new IllegalArgumentException(); } if (applyAlgo) { return validate(creditCard); } return false; } public static boolean validate(String creditCard) { // 4 9 9 2 7 3 9 8 7 1 6 // 6 // 1 x 2 = 2 = (0 + 2) = 2 // 7 // 8 x 2 = 16 = (1 + 6) = 7 // 9 // 3 x 2 = 6 = (0 + 6) = 6 // 7 // 2 x 2 = 4 = (0 + 4) = 4 // 9 // 9 X 2 = 18 = (1 + 8) = 9 // 4 // 6+2+7+7+9+6+7+4+9+9+4 = 70 // return 0 == (70 % 10) int sum = 0; int length = creditCard.length(); for (int i = 0; i < creditCard.length(); i++) { if (0 == (i % 2)) { sum += creditCard.charAt(length - i - 1) - '0'; } else { sum += sumDigits((creditCard.charAt(length - i - 1) - '0') * 2); } } return 0 == (sum % 10); } private static int sumDigits(int i) { return (i % 10) + (i / 10); } public final static boolean isValidEmail(CharSequence target) { return !TextUtils.isEmpty(target) && android.util.Patterns.EMAIL_ADDRESS.matcher(target).matches(); } 

}