ActiveState Code

Recipe 172845: Python Luhn checksum for credit card validation


This is an industry standard algorithm I ported to python. It works on all major credit cards. You pass in the credit card number as a string and it returns 1 for a valid card or 0 for an invalid card

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
def cardLuhnChecksumIsValid(card_number):
    """ checks to make sure that the card passes a luhn mod-10 checksum """

    sum = 0
    num_digits = len(card_number)
    oddeven = num_digits & 1

    for count in range(0, num_digits):
        digit = int(card_number[count])

        if not (( count & 1 ) ^ oddeven ):
            digit = digit * 2
        if digit > 9:
            digit = digit - 9

        sum = sum + digit

    return ( (sum % 10) == 0 )

Discussion

This recipe was originally written for a now-defunct e-commerce application used within Zope.

It will save you time and money before trying to process a bad card with your credit card vendor, because you won't waste money trying to authorize a bad card with your credit card processing vendor.

The full suite of creditValidation methods are available here:

http://david.theresistance.net/files/creditValidation.py

Comments

  1. 1. At 4:52 a.m. on 1 jul 2004, Anonymous said:

    Checksum calculation.

    """ easy checksum """
    def checksum(a):
        return (10 - sum([int(y)*[7,3,1][x%3] for x, y in enumerate(str(a)[::-1])])%10)%10
    
  2. 2. At 5:10 a.m. on 19 oct 2004, sasa sasa said:

    Another take...

    # Return the "Luhn transform" of a digit.
    luhnify = lambda digit: sum(divmod( digit*2, 10 ))
    
    def luhn_checksum( digits ):
        """Return the Luhn checksum of a sequence of digits.
        """
        digits = map( int, digits )
        odds, evens = digits[-2::-2], digits[-1::-2]
        return sum( map(luhnify,odds) + evens ) % 10
    
  3. 3. At 6:12 p.m. on 7 feb 2005, Christopher Dunn said:

    That checksum is wrong. It does not match the other 2 listed here, and it returns "7" for my credit card. What is it for?

  4. 4. At 11:19 a.m. on 22 feb 2006, Lloyd Girty said:

    Integer only version. Here is a integer-only version that avoids string casts. You may need "from __future__ import division" to use the "//" floor operator.

    def luhn(n):
        """luhnsum(int)->bool
        Mod 10 checksum by Hans Peter Luhn (1896–1964)
        """
        sum=0
        while n:
            r=n%100
            n//=100
            z=r%10
            r=r//10*2
            sum+=r//10+r%10+z
        return 0==sum%10
    
  5. 5. At 11:22 a.m. on 22 feb 2006, Lloyd Girty said:

    generating many luhn numbers.

    def nextLuhn(n):
        """nextLuhn(int) -> int
        Gets the smallest Luhn number greater than n.
        Uses a naive (exhaustive) algorithm that must try
        the Luhn checksum an average of 10 times.
        """
        n+=1
        while not luhn(n):
            n+=1
        return n
    
    def biggerLuhn(n):
        """ biggerLuhn(int) -> int
        Gets a Luhn number greater than n.
        Uses a probability model that is very efficient if
        n passes the Luhn checksum.
        It may be possible to miss a Luhn number with this method.
        """
        for t in [8, 18, 7, 17, 6, 16]:
            if luhn(n+t):
                return n+t
        return nextLuhn(n)
    
    def xluhn(seed,howmany):
        """xluhn(int,int) ->*int
        Yields Luhn numbers greater than the seed.
        Some numbers may be left out of the sequence.
        """
        while howmany:
            seed=biggerLuhn(seed)
            howmany-=1
            yield seed
    
  6. 6. At 9:22 a.m. on 15 aug 2007, James Coe said:

    Incorrect LUHN checksum implementation. This LUHN implementation is actually incorrect. The card number digits must be traversed from end to beginning (reverse the direction the for loop counts) or some (but not all) perfectly valid card numbers will be rejected.

  7. 7. At 2:39 a.m. on 14 jun 2009, admin sekip said:

Sign in to comment