8

I am developing a set of tools in Java for validating and working with credit cards. So far I have support for:

  • LUHN validation.

  • Date validation (simple expiration).

  • Card code length validation (CVV, CVC, CID) based on the brand (Visa, MasterCard, etc).

  • Credit card number length validation (based on the brand).

  • BIN/IIN validation (against a database of valid numbers).

  • Hiding the digits (425010 * * * * * * 1234)

To make the tool set a bit more complete, I would like to create a credit card random number generator based on the different card brands. This functionality will (hopefully) make my test cases a bit more reliable.

Basically, I would like to be able to generate numbers which are:

  • LUHN valid

  • Valid based on the brand prefixes

  • Valid based on the BIN/IIN prefix numbers

For BIN/IIN valid card numbers, I am thinking of looking up a random BIN/IIN number from the database (based on the brand of course) and then appending the remaining digits using Random. Obviously, that would not be valid most of the time and I will have to increment one of the digits until it passes the LUHN validation.

I can't seem to be able to think of a better way. Perhaps someone could suggest something a little smarter...?

Looking forward to your suggestions! Thanks in advance! :)

carlspring
  • 31,231
  • 29
  • 115
  • 197
  • 5
    Am I missing something obvious? The way I'd do it is the following: 1) Get BIN/IIN number from dtb. 2) Append a random number without the check digit (which is the last digit - so you'll make it one digit short). 2) Compute the last check digit. Voila? – Petr Janeček Jul 20 '12 at 13:17
  • 3
    @Slanec That's a partial solution, but don't forget that the number isn't "random", e.g. a VISA card will only have a narrow range of initial digits. – Widor Jul 20 '12 at 13:18
  • [Does this help?](http://stackoverflow.com/a/6276949/644450) – oers Jul 20 '12 at 13:33
  • 1
    @Slanec, that would be one way, I guess. – carlspring Jul 20 '12 at 14:07
  • @oers, I'm afraid I don't find that answer or the links in it too useful. Maybe I'm missing your point...? – carlspring Jul 20 '12 at 14:08
  • sry I forgot some of your requirements while looking at some links :) I just thought you needed a set of dummy numbers and forgot the creating-them-myself part – oers Jul 20 '12 at 16:28
  • @Slanec, perhaps you would like to post an answer with the example? – carlspring Jul 23 '12 at 12:49

3 Answers3

4

Not so long ago I've authored a library called MockNeat. One of the features is to allow the developer to generate different valid credit card numbers.

Check this method: creditCards().

A short example to write 1000 Credit Cards AMEX and Mastercard in a file for later use:

 MockNeat m = MockNeat.threadLocal();
    final Path path = Paths.get("cc.txt");

// Write in a file 1000 credit cards AMEX and Mastercard:
 m.creditCards()
            .types(MASTERCARD, AMERICAN_EXPRESS)
            .list(1000)
            .consume(list -> {
                try { Files.write(path, list, CREATE, WRITE); }
                catch (IOException e) { e.printStackTrace(); }
            });
Andrei Ciobanu
  • 12,500
  • 24
  • 85
  • 118
2

This functionality will (hopefully) make my test cases a bit more reliable.

I'm not convinced. In my experience, it is not a good idea to use random data in unit tests, because you never know if you've covered all of the important cases ... and bugs.

I'd recommend creating your test credit card numbers by hand, and taking care that they cover all of the cases that need to be tested.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Well, this is what I have done currently. However, if you have card number validators, this randomness should not be a concern, but rather -- a proof that they really work. – carlspring Jul 20 '12 at 15:10
  • (Hmmm ... 8 months later you upvoted and accepted my answer. Does this mean that I was right about random data not giving you good test coverage? :-) ) – Stephen C Mar 06 '13 at 12:21
  • Haha! No, I agreed back then. You are right that test data should be easily predictable and guarantee reproducible results. I fully agree with this. I was actually checking the questions for which I hadn't accepted answers. Cheers! ;) – carlspring Mar 06 '13 at 12:25
2

Here goes some Groovy to generate LUHN valid Credit Cards.. I'm sure you can re-write it in your own language:

cardPrepend = "400141"
cardLength = "16"

random = new Random()
myString = ""

    (cardLength.toInteger() - cardPrepend.length()).times{
        randomNumber = random.nextInt(9)
        myString = myString + randomNumber.toString()  
    }

    myString = cardPrepend + myString

    myStringMinusLastDigit = myString.substring(0, myString.length()-1)
    mod10Digit = getMod10Digit(myStringMinusLastDigit)
    myString = myStringMinusLastDigit + mod10Digit

    return  """${myString}"""  


//-------------------------------------------------------------------------
def getMod10Digit(String number) {
    int weight = 2;
    int sum    = 0;
    for (int i = number.length() - 1; i >= 0; i--) {
        int digit = weight * Integer.parseInt(number.substring(i,i+1));
        sum = sum + (digit / 10) + (digit % 10);
        weight = (weight == 2) ? 1: 2;
    }
 
    
    return ((10 - (sum % 10)) % 10);
    }
Roberto Rodriguez
  • 3,179
  • 32
  • 31