C# Tutorials and offshore development in India
Tutorials Resources Forum Reviews Communities Interview Jobs Projects Training Videos


Prizes & Awards
My Profile



Active Members
TodayLast 7 Days more...


Birthday Greetings
Learn Windows 7: Google chrome tips and tricks   In this resource I will provide some simple google chrome tips and tricks.



Resources » Articles » Databases »

Validate Credit Card Numbers with the Luhn Function


Posted Date: 02 Dec 2004    Resource Type: Articles    Category: Databases
Author: Andrew NovickMember Level: Bronze    
Rating: 1 out of 5Points: 7


This article shows how to calculate the Luhn (Mod 10) function for a string of numbers in a T-SQL UDF and explains how to validate a credit card number.



Introduction

Credit card numbers are among the most common numbers in commercial use today. Most credit card numbers and many other numbers used in financial services use the Luhn (a.k.a Mod 10) formula for check digits. It's been formalized as part of the ANSI X4.13 specification.

This article's UDF is udf_Bank_IsLuhn, which validates a Luhn number such as a credit card: Here's the CREATE FUNCTION script:


SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO

CREATE FUNCTION dbo.udf_Bank_IsLuhn (

@Target varchar(20) -- Number string to validate

/* Validates that a sequence of digits satisfies the Luhn
* validation formula. It's also know as MOD 10. The full
* description is in the ANSI X4.13 specification. The Luhn
* formula is used to validate credit card numbers, Canadian
* social security numbers and many other financial services
* numbers. Another common formula is Mod 11.
*
* Dashes are removed before the number is checked. They're
* removed from anywhere in the number so if they have to be
* in certain positions, the number should be pre-validated
* for the correct positions. False is returned for non-numerics,
* null arguments or zero length arguments.
*
* Here's a definition of the algorithm from webopedia:
* 1) Starting with the second to last digit and moving left,
* double the value of all the alternating digits.
* 2) Starting from the left, take all the unaffected digits
* and add them to the results of all the individual digits
* from step 1. If the results from any of the numbers from
* step 1 are double digits, make sure to add the two numbers
* first (i.e. 18 would yield 1+8).
* 3) The total from step 2 must end in zero for the credit-card
* number to be valid.
*
* Example:
select CASE WHEN 1=dbo.udf_Bank_IsLuhn ('2323-2005-7766-3554')
then 'Valid' ELSE 'Invalid' END
*
* Test:
SELECT CASE WHEN 1=dbo.udf_Bank_IsLuhn ('2323-2005-7766-3554')
then 'Worked' ELSE 'ERROR' END
SELECT CASE WHEN 0=dbo.udf_Bank_IsLuhn ('3323-2005-7766-3554')
then 'Worked' ELSE 'ERROR' END
SELECT CASE WHEN 0=dbo.udf_Bank_IsLuhn ('2323-2D05-7766-3554')
then 'Worked' ELSE 'ERROR' END
SELECT CASE WHEN 1=dbo.udf_Bank_IsLuhn ('4111-1111-1111-1111')
then 'Worked' ELSE 'ERROR' END -- Visa
SELECT CASE WHEN 1=dbo.udf_Bank_IsLuhn ('3400-0000-0000-009')
then 'Worked' ELSE 'ERROR' END -- Amex
SELECT CASE WHEN 1=dbo.udf_Bank_IsLuhn ('3400-0000-0000-009')
then 'Worked' ELSE 'ERROR' END -- Amex
SELECT CASE WHEN 1=dbo.udf_Bank_IsLuhn ('6011-0000-0000-0004')
then 'Worked' ELSE 'ERROR' END -- Discover
SELECT CASE WHEN 1=dbo.udf_Bank_IsLuhn ('5500-0000-0000-0004')
then 'Worked' ELSE 'ERROR' END -- Master card
*
* © Copyright 2004 Andrew Novick http://www.NovickSoftware.com
* You may use this function in any of your SQL Server databases
* including databases that you sell, so long as they contain
* other unrelated database objects. You may not publish this
* UDF either in print or electronically.
* Published as T-SQL UDF of the Week Vol 2 #47 11/30/04
http://www.NovickSoftware.com/UDFofWeek/UDFofWeek.htm
****************************************************************/

) RETURNS BIT

AS BEGIN

DECLARE @pos int
, @a int
, @b int
, @chrVal int

-- Handle Null, zero length, or non-numeric input as false
IF @Target IS NULL OR LEN(@Target)=0 RETURN 0

-- remove any dashes from the number.
SET @Target = REPLACE(@Target, '-', '')

IF 0=ISNUMERIC(@Target) RETURN 0 -- Must be numeric

SELECT @a = 0, @b = 0, @pos=len(@Target) -- Start from end

WHILE @pos>0 BEGIN -- Until the beginning

IF @pos>1 BEGIN -- Not at the 1st character

SET @ChrVal= (ASCII(SUBSTRING(@Target,@pos-1,1))-48)*2
SET @a = @A + @chrVal
+ CASE WHEN @ChrVal>9 THEN -9 ELSE 0 END
END

SET @b= @b + (ASCII(SUBSTRING(@Target,@pos,1))-48)
SET @pos = @pos - 2
END -- WHILE

-- True if @A + @B mod 10 is zero
RETURN CASE WHEN 0 = (@a + @b) % 10 THEN 1 ELSE 0 END

END


GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO



The tests from the function header illustrate how the function works so lets use them as the demonstration:


set nocount on
SELECT CASE WHEN 1=dbo.udf_Bank_IsLuhn ('2323-2005-7766-3554')
then 'Worked' ELSE 'ERROR' END
SELECT CASE WHEN 0=dbo.udf_Bank_IsLuhn ('3323-2005-7766-3554')
then 'Worked' ELSE 'ERROR' END
SELECT CASE WHEN 0=dbo.udf_Bank_IsLuhn ('2323-2D05-7766-3554')
then 'Worked' ELSE 'ERROR' END
SELECT CASE WHEN 1=dbo.udf_Bank_IsLuhn ('4111-1111-1111-1111')
then 'Worked' ELSE 'ERROR' END -- Visa
SELECT CASE WHEN 1=dbo.udf_Bank_IsLuhn ('3400-0000-0000-009')
then 'Worked' ELSE 'ERROR' END -- Amex
SELECT CASE WHEN 1=dbo.udf_Bank_IsLuhn ('3400-0000-0000-009')
then 'Worked' ELSE 'ERROR' END -- Amex
SELECT CASE WHEN 1=dbo.udf_Bank_IsLuhn ('6011-0000-0000-0004')
then 'Worked' ELSE 'ERROR' END -- Discover
SELECT CASE WHEN 1=dbo.udf_Bank_IsLuhn ('5500-0000-0000-0004')
then 'Worked' ELSE 'ERROR' END -- Master card
GO


(Results)
Worked

Worked

Worked

Worked

Worked

Worked

Worked

Worked


Summary

Luhn is one of the more common validations that an e-commerce application must implement. Putting the validation in the database may or may not be the best place but there are times when you need validation at multiple levels of the application including the database.





Responses to the resource: "Validate Credit Card Numbers with the Luhn Function"
Author: Prasad Papudesi    07 May 2005Member Level: Bronze   Points : 0
private bool ValidateCreditCardNumber(string creditCardNumber)
{
//Replace any character other than 0-9 with ""
creditCardNumber = Regex.Replace(creditCardNumber,@"[^0-9]","");
int cardSize = creditCardNumber.Length;
//Creditcard number length must be between 13 and 16
if (cardSize >= 13 && cardSize <= 16)
{
int odd = 0;
int even = 0;
char[] cardNumberArray = new char[cardSize];
//Read the creditcard number into an array
cardNumberArray = creditCardNumber.ToCharArray();
//Reverse the array
Array.Reverse(cardNumberArray, 0, cardSize);
//Multiply every second number by two and get the sum.
//Get the sum of the rest of the numbers.
for (int i = 0; i < cardSize; i++)
{
if (i%2 ==0)
{
odd += (Convert.ToInt32(cardNumberArray.GetValue(i))-48);
}
else
{
int temp = (Convert.ToInt32(cardNumberArray[i]) - 48) * 2;
//if the value is greater than 9, substract 9 from the value
if (temp > 9)
{
temp = temp-9;
}
even += temp;
}
}
if ((odd+even)%10 == 0)
return true;
else
return false;
}
else
return false;
}


Feedbacks      
Popular Tags   What are tags ?   Search Tags  
Sign In to add tags.
(No tags found.)

Post Feedback


This is a strictly moderated forum. Only approved messages will appear in the site. Please use 'Spell Check' in Google toolbar before you submit.
You must Sign In to post a response.
Next Resource: Case sensitive select query in SQL Server
Previous Resource: Updating bulk data with single execution to Sqlserver using XML - SQL XML
Return to Resources
Post New Resource
Category: Databases


Post resources and earn money!
 
More Resources



About Us    Contact Us    Privacy Policy    Terms Of Use