Apurva Patel
Apurva Patel

Reputation: 71

Python Credit Card Validation

I'm a beginner Python learner and I'm currently working on Luhn Algorithm to check credit card validation. I wrote most of the code, but I'm stuck with 2 errors I get 1st one is num is referenced before assignment. 2nd one I'm getting is object of type '_io.TextIOWrapper' has no len(). Further help/ guidance will be greatly appreciated.

These are the steps for Luhn Algorithm (Mod10 Check)

  1. Double every second digit from right to left. If this “doubling” results in a two-digit number, add the two-digit number to get a single digit.
  2. Now add all single digit numbers from step 1.
  3. Add all digits in the odd places from right to left in the credit card number.
  4. Sum the results from steps 2 & 3.
  5. If the result from step 4 is divisible by 10, the card number is valid; otherwise, it is invalid.

Here's what my output is supposed to be

Card Number         Valid / Invalid
--------------------------------------
3710293             Invalid
5190990281925290    Invalid
3716820019271998    Valid
37168200192719989   Invalid
8102966371298364    Invalid
6823119834248189    Valid

And here is the code.

def checkSecondDigits(num):
    length = len(num)
    sum =  0
    for i in range(length-2,-1,-2):
      number = eval(num[i])
      number = number * 2
      if number > 9:
          strNumber = str(number)
          number = eval(strNumber[0]) + eval(strNumber[1])
          sum += number
      return sum

def odd_digits(num):
    length = len(num)
    sumOdd = 0
    for i in range(length-1,-1,-2):
        num += eval(num[i])
    return sumOdd

def c_length(num):
    length = len(num)
    if num >= 13 and num <= 16:
    if num [0] == "4" or num [0] == "5" or num [0] == "6" or (num [0] == "3" and num [1] == "7"):
        return True
    else:
        return False


def main():
    filename = input("What is the name of your input file? ")
    infile= open(filename,"r")
    cc = (infile.readline().strip())
    print(format("Card Number", "20s"), ("Valid / Invalid"))
    print("------------------------------------")
    while cc!= "EXIT":
        even = checkSecondDigits(num)
        odd = odd_digits(num)
        c_len = c_length(num)
        tot = even + odd

        if c_len == True and tot % 10 == 0:
            print(format(cc, "20s"), format("Valid", "20s"))
        else:
            print(format(cc, "20s"), format("Invalid", "20s"))
        num = (infile.readline().strip())

main()

Upvotes: 2

Views: 37604

Answers (8)

Mohit Saini
Mohit Saini

Reputation: 1

def check_credit_card(request):
    if request.method == "POST":
        card_no = request.POST.get("card_number")

        if card_no and check_luhn_algorithm(card_no):
            context = {"valid": True}
            return render(request, "Credit_card_check.html", context)

    return render(request, "Credit_card_check.html")


def check_luhn_algorithm(card_no):
    n_digits = len(card_no)
    n_sum = 0
    is_second = False

    for i in range(n_digits - 1, -1, -1):
        d = int(card_no[i])

        if is_second:
            d = d * 2

        n_sum += d // 10
        n_sum += d % 10

        is_second = not is_second

    return n_sum % 10 == 0

Upvotes: 0

Sandesh Karumuri
Sandesh Karumuri

Reputation: 1

n = input("Enter 16-digit Credit Card Number:")
lst = []
for i in range(16):
    lst.append(n[i])
# print(lst)
# list1 = n.split()
# print(list1)


def validate_credit_card():
    global lst
    if len(lst) == 16:
        for i in range(0, len(lst)):
            lst[i] = int(lst[i])
        # print(lst)
        last = lst[15]
        first = lst[:15]
        # print(first)
        # print(last)
        first = first[::-1]
        # print(first)
        for i in range(len(first)):
            if i % 2 == 0:
                first[i] = first[i] * 2
            if first[i] > 9:
                first[i] -= 9
        sum_all = sum(first)
        # print(first)
        # print(sum_all)
        t1 = sum_all % 10
        t2 = t1 + last
        if t2 % 10 is 0:
            print("Valid Credit Card")
        else:
            print("Invalid Credit Card!")
    else:
        print("Credit Card number limit Exceeded!!!!")
        exit()


if __name__ == "__main__":
    validate_credit_card()

Upvotes: 0

Preyash Patel
Preyash Patel

Reputation: 45

you can use my code for card validation it is 100% dynamic because of the card structure is stored in CSV file, so it is easy to update here is the code on GitHub profile, python file link, code explanation file link and CSV for datafile link

python code:

# -*- coding: utf-8 -*-
"""
Created on Tue Sep 10 20:55:30 2019
@author: [email protected]
"""


import csv
import numpy as np

#csv file imported and storf in reader
reader = csv.DictReader(open("card_data.csv"))

#input card number
card_number = input("Enter the card No: ")

#global variable declaration
min_digits=0
max_digits=0
card_number_list = list(card_number)
card_number_list_reverse=card_number_list[::-1]
card_number_length=len(card_number_list)
first_digit = int(card_number_list[0])

#global variable for final output
card_provider_list_number = 0
result_found = False
card_number_digits = 0
mit_name=""

#list
start=[]
end=[]
name=[]
c_d=[]
number_length=[]
min_max_digits_list=[]

#append the list from csv
for raw in reader:
    start.append(raw['start'])
    end.append(raw['end'])
    name.append(raw['name'])
    c_d.append(raw['c_d'])
    number_length.append(raw['number_length'])

#initialize the value of min_digits & max_digits
def min_max_digits():
    global min_digits
    global max_digits
    for i in range(len(start)):
        available_length=number_length[i].split(',')
        for j in range(len(available_length)):
            min_max_digits_list.append(available_length[j])
    min_max_digits_array = np.array(min_max_digits_list) 
    np.unique(min_max_digits_array)
    min_digits=int(min(min_max_digits_array))
    max_digits=int(max(min_max_digits_array))

#list to int
def list_to_int(noofdigits): 
    str1 = ""
    return int(str1.join(noofdigits))

#card validation
def iin_identifier():
    first_six_digit = list_to_int(card_number_list[0:6])
    for i in range(len(start)):
        if(first_six_digit >= int(start[i]) and first_six_digit <= int(end[i])):
            available_length=number_length[i].split(',')
            for j in range(len(available_length)):
                if(card_number_length == int(available_length[j])):
                    global card_provider_list_number
                    card_provider_list_number = i
                    global card_number_digits
                    card_number_digits = available_length[j]
                    global result_found
                    result_found = True

#Major Industry Identifier (MII) identification
def mit_identifier():
    global first_digit
    global mit_name
    switcher = { 
         1: "Airlines",
         2: "Airlines",
         3: "Travel and Entertainment",
         4: "Banking and Financial Services",
         5: "Banking and Financial Services",
         6: "Merchandising and Banking",
         7: "Petroleum",
         8: "Health care, Telecommunications",
         9: "National Assignment"
    }
    mit_name=switcher.get(first_digit, "MIT Identifier Not Found") 

#Luhn Algorithm or modulo-10 Algorithm
def luhn_algorithm():
    for i in range(card_number_length):
        if(i%2!=0 and i!=0):
            card_number_list_reverse[i]=int(card_number_list_reverse[i])*2
            #print(str(i)+" "+ str(card_number_list_reverse[i]))
            if(len(str(card_number_list_reverse[i]))==2):
                even_number_2=list(str(card_number_list_reverse[i]))
                card_number_list_reverse[i] = int(even_number_2[0])+int(even_number_2[1])
                #print("\tsubsum "+str(i)+" "+str(card_number_list_reverse[i]))
        else:
            card_number_list_reverse[i]=int(card_number_list_reverse[i])
    division_int = int(sum(card_number_list_reverse)/10)
    division_float=sum(card_number_list_reverse)/10
    if(division_int-division_float==0):
        return True

#initial level number length validation
def card_number_validation():
    min_max_digits()
    if(card_number_length>= min_digits and card_number_length <= max_digits and first_digit != 0):
        iin_identifier()
        mit_identifier()
        if(result_found and luhn_algorithm()):
            print("\nEntered Details are Correct\n")
            print("\nHere are the some details we know about you card")
            print("\nNo: "+card_number)
            print("\nIssuing Network: "+name[card_provider_list_number])
            print("\nType: "+c_d[card_provider_list_number]+" Card")
            print("\nCategory of the entity which issued the Card: "+mit_name)
        else:
            print("\nCard Number is Invalid\nPlease renter the number!\n")
    else:
        print("\nCard Number is Invalid\n")

#method called to run program
card_number_validation()

Upvotes: 0

Vadim Kuzmyk
Vadim Kuzmyk

Reputation: 21

First, maybe you should remove the extra characters:

def format_card(card_num):
    """
    Formats card numbers to remove any spaces, unnecessary characters, etc
    Input: Card number, integer or string
    Output: Correctly formatted card number, string
    """
    import re
    card_num = str(card_num)
    # Regex to remove any nondigit characters
    return re.sub(r"\D", "", card_num)

After check if credit card is valid using the Luhn algorithm:

def validate_card(formated_card_num):
    """
    Input: Card number, integer or string
    Output: Valid?, boolean
    """
    double = 0
    total = 0

    digits = str(card_num)

    for i in range(len(digits) - 1, -1, -1):
        for c in str((double + 1) * int(digits[i])):
            total += int(c)
        double = (double + 1) % 2

    return (total % 10) == 0

Upvotes: 1

zedman350
zedman350

Reputation: 1

Further, num should not appear anywhere in main() as it should be local to (only appear inside of) the functions called... The last line in this code should be the same as the first, but the last line incorrectly assigns the data to num instead of cc

cc = (infile.readline().strip())
print(format("Card Number", "20s"), ("Valid / Invalid"))
print("------------------------------------")
while cc!= "EXIT":
    even = checkSecondDigits(num)
    odd = odd_digits(num)
    c_len = c_length(num)
    tot = even + odd

    if c_len == True and tot % 10 == 0:
        print(format(cc, "20s"), format("Valid", "20s"))
    else:
        print(format(cc, "20s"), format("Invalid", "20s"))
    num = (infile.readline().strip())

Upvotes: 0

zedman350
zedman350

Reputation: 1

Old thread but the answer concerns me... and the real issue wasn't identified. Actually, the error is that you have used the identifier (num) for the parameter when defining checkSecondDigits as the identifier/name of the argument when calling the function in the mainline. The function should be called in main() by even = checkSecondDigits(cc) so the value in cc (which is the argument) is passed into num (as the parameter) for use within the function. The same rookie error is made with odd_digits and cc_length.

This question (and the initially suggested answer) demonstrates a fundamental mis-understanding of passing arguments to parameters... The suggested 'declaring' of num just hides this error/misunderstanding and also obfuscates the local and global scopes of num (which should only be local) and cc (which is global) so whilst the suggestion works in this case, it works for the wrong reason and is poor style and bad programming.

Upvotes: 0

This is a very simpler version of code it is based on lunh's algorithm

def validator(n):

    validatelist=[]

    for i in n:
        validatelist.append(int(i))


    for i in range(0,len(n),2):


        validatelist[i] = validatelist[i]*2

        if validatelist[i] >= 10:

            validatelist[i] = validatelist[i]//10 + validatelist[i]%10


    if sum(validatelist)%10 == 0:
        print('This a valid credit card') 

    else:
        print('This is not valid credit card')

def cardnumber():

    result=''
    while True:
        try:
            result = input('Please enter the 16 digit credit card number : ')

            if not (len(result) == 16) or not type(int(result) == int) :
                raise Exception

        except Exception:    
            print('That is not a proper credit card number. \nMake sure you are entering digits not characters and all the 16 digits.')
            continue

        else:
            break


    return result

def goagain():
    return input('Do you want to check again? (Yes/No) : ').lower()[0] == 'y'

def main():

    while True:

        result = cardnumber()
        validator(result)


        if not goagain():
            break

if __name__ == '__main__':
    main()

Upvotes: 0

2ps
2ps

Reputation: 15926

You just forgot to initialize num

def main():
    filename = input("What is the name of your input file? ")
    infile= open(filename,"r")
    # initialize num here
    num = cc = (infile.readline().strip())
    print(format("Card Number", "20s"), ("Valid / Invalid"))
    print("------------------------------------")
    while cc!= "EXIT":
        even = checkSecondDigits(num)
        odd = odd_digits(num)
        c_len = c_length(num)
        tot = even + odd

        if c_len == True and tot % 10 == 0:
            print(format(cc, "20s"), format("Valid", "20s"))
        else:
            print(format(cc, "20s"), format("Invalid", "20s"))
        num = cc = (infile.readline().strip())

Upvotes: 2

Related Questions