I'm really new to regex but I think my problem might go beyond that at the moment. As the title says, I'm trying to determine if a credit card is visa, amex, master card etc.
I looked at this post which gave the regular expression for each of the card types:
How do you detect Credit card type based on number?
This is the code I then used but it doesn't do anything at all:
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");
}
}
});
The regexp in the pattern.compile function is for determining Discover cards according to the post above. I've noticed that I really can't get anything to work other than the "^" in regex (i.e ("^4" - visa, "^6001" discover) however this is obviously not sufficient in the case of editing for example. Any ideas what's up? I thought this could be an issue with my Java, but I am running Java 7
I might want to make this a new question, but I am also wondering how regex can be used to get spacing correct for various credit cards even if a user goes back and edits the number (xxxx xxxx xxxx xxxx)
EDIT: Added the DEBUG log from above. My input is a few digits that should associate with certain credit cards. Currently I am using Eagle Eye's code provided below (which should also work for detecting that the input is ONE of the card types):
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;
}
}
}
});
Log:
01-29 15:16:41.932 26194-26194/com.x.x D/DEBUG﹕ beforeTextChanged :
01-29 15:16:41.933 26194-26194/com.x.x D/DEBUG﹕ afterTextChanged : 4
01-29 15:16:46.815 26194-26194/com.x.x D/DEBUG﹕ beforeTextChanged : 4
01-29 15:16:46.816 26194-26194/com.x.x D/DEBUG﹕ afterTextChanged :
01-29 15:16:50.925 26194-26194/com.x.x D/DEBUG﹕ beforeTextChanged :
01-29 15:16:50.926 26194-26194/com.x.x D/DEBUG﹕ afterTextChanged : 6
01-29 15:16:51.542 26194-26194/com.x.x D/DEBUG﹕ beforeTextChanged : 6
01-29 15:16:51.543 26194-26194/com.x.x D/DEBUG﹕ afterTextChanged : 60
01-29 15:16:51.883 26194-26194/com.x.x D/DEBUG﹕ beforeTextChanged : 60
01-29 15:16:51.883 26194-26194/com.x.x D/DEBUG﹕ afterTextChanged : 600
01-29 15:16:52.928 26194-26194/com.x.x D/DEBUG﹕ beforeTextChanged : 600
01-29 15:16:52.929 26194-26194/com.x.x D/DEBUG﹕ afterTextChanged : 6001
01-29 15:16:55.781 26194-26194/com.x.x D/DEBUG﹕ beforeTextChanged : 6001
01-29 15:16:55.782 26194-26194/com.x.x D/DEBUG﹕ afterTextChanged : 600
01-29 15:16:56.206 26194-26194/com.x.x D/DEBUG﹕ beforeTextChanged : 600
01-29 15:16:56.206 26194-26194/com.x.x D/DEBUG﹕ afterTextChanged : 60
01-29 15:16:57.659 26194-26194/com.x.x D/DEBUG﹕ beforeTextChanged : 60
01-29 15:16:57.660 26194-26194/com.x.x D/DEBUG﹕ afterTextChanged : 605
01-29 15:16:59.297 26194-26194/com.x.x D/DEBUG﹕ beforeTextChanged : 605
01-29 15:16:59.298 26194-26194/com.x.x D/DEBUG﹕ afterTextChanged : 60
01-29 15:16:59.527 26194-26194/com.x.x D/DEBUG﹕ beforeTextChanged : 60
01-29 15:16:59.527 26194-26194/com.x.x D/DEBUG﹕ afterTextChanged : 6
01-29 15:17:00.314 26194-26194/com.x.x D/DEBUG﹕ beforeTextChanged : 6
01-29 15:17:00.314 26194-26194/com.x.x D/DEBUG﹕ afterTextChanged : 65
You'd expect the log "discover" to come out a few times for the different digits I've entered. The above log shows me typing in the first few digits of a visa card and a discover card.
EDIT ANSWER FOUND: I simply wasn't typing in enough digits for the card to be recognized!
MasterCard Card Identification Features All cards must include a full-color MasterCard brand mark. MasterCard account numbers must always start with the number “5.” The first four digits of the card number must be the same as those printed directly below (pre-printed BIN).
If your card starts with 3, your card uses the American Express network. Visa starts with 4, a Mastercard is 5 and Discover is 6. Other numbers are used to identify the industry. For instance, 1 and 2 are used for the airline industry.
According to one of the answers in the thread, The cards can be validated based on following data.
Visa: ^4[0-9]{6,}$
Visa card numbers start with a 4.
MasterCard: ^5[1-5][0-9]{5,}$
MasterCard numbers start with the numbers 51 through 55, but this will only detect MasterCard credit cards; there are other cards issued using the MasterCard system that do not fall into this IIN range.
American Express: ^3[47][0-9]{5,}$
American Express card numbers start with 34 or 37.
Diners Club: ^3(?:0[0-5]|[68][0-9])[0-9]{4,}$
Diners Club card numbers begin with 300 through 305, 36 or 38. There are Diners Club cards that begin with 5 and have 16 digits. These are a joint venture between Diners Club and MasterCard, and should be processed like a MasterCard.
Discover: ^6(?:011|5[0-9]{2})[0-9]{3,}$
Discover card numbers begin with 6011 or 65.
JCB: ^(?:2131|1800|35[0-9]{3})[0-9]{3,}$
JCB cards begin with 2131, 1800 or 35.
So you need to create separate pattern for each case. You can do as follows.
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);
}
and then,
@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;
}
}
}
And for your last question, The following thread should help you.
Format credit card in edit text in android
EDIT:
If the card number is 16 digits for example, After applying the logic to add spaces after 4 digits, you need to remove those spaces when you process the actual card number. Then only the above logic will work.
Hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With