Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's a good way to generate a random number for a valid credit card?

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! :)

like image 299
carlspring Avatar asked Jul 20 '12 13:07

carlspring


3 Answers

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(); }
            });
like image 180
Andrei Ciobanu Avatar answered Nov 08 '22 08:11

Andrei Ciobanu


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.

like image 43
Stephen C Avatar answered Nov 08 '22 06:11

Stephen C


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);
    }
like image 23
Roberto Rodriguez Avatar answered Nov 08 '22 08:11

Roberto Rodriguez