Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regex for determining credit cards in Android [duplicate]

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!

like image 584
AIntel Avatar asked Jan 29 '15 04:01

AIntel


People also ask

How do I identify a MasterCard?

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).

What are the first 4 digits of a Visa card?

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.


1 Answers

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.

like image 81
Vilas Avatar answered Nov 09 '22 23:11

Vilas