So, for others that may needed, I'm including this small routine that validates the credit card number (not the card secure code, nor the expiration date). There are several implementations on the web that based on the card prefix digits you can determine the kind of card you are looking at (VISA, MC, Dinners, etc.) That kind of inferences are not reliable for a global solution so the decision was made to drop that auto detection.

function ValidateCreditCardNumber(CreditCardNumber:string):boolean;

Const

DigitsAllowed = ['0'..'9'];

MaxCCSize = 19;

MinCCSize = 13;

var

i : integer;

CleanCardNumber: string;

digit: Integer;

CheckSum: Integer; { Holds the value of the operation }

Flag: Boolean; { used to indicate when ready }

Counter: Integer; { index counter }

PartNumber: string; { used to extract each digit of number }

Number: Integer; { used to convert each digit to integer}

Begin

CleanCardNumber:='';

digit:=0;

// Remove any non numeric value

for I := 1 to Length(CreditCardNumber) do

Begin

if CreditCardNumber[i] in DigitsAllowed then

CleanCardNumber:= CleanCardNumber + CreditCardNumber[i];

End;

// Check for valid card length number

if (Length(CleanCardNumber)MaxCCSize) then

Begin

Result:= False;

Exit;

End;

// get the starting value for our counter

Counter := Length(CleanCardNumber);

CheckSum := 0;

PartNumber := '';

Number := 0;

Flag := false;

while (Counter >= 1) do

begin

// get the current digit

PartNumber := Copy(CleanCardNumber, Counter, 1);

Number := StrToInt(PartNumber); // convert to integer

if (Flag) then // only do every other digit

begin

Number := Number * 2;

if (Number >= 10) then

Number := Number - 9;

end;

CheckSum := CheckSum + Number;

Flag := not (Flag);

Counter := Counter - 1;

end;

result := ((CheckSum mod 10) = 0);

End;

This implementation is based on a 1996 VB Code migration from Shawn Wilson.

## 4 comments:

My implementation is somewhat shortrer, but does not check the length.

function CheckLuhn(s:string):Boolean;

var

alt,err:boolean;

i,sum:integer; d:byte;

const luhn_dbl:array[0..9] of byte=(0,2,4,6,8,1,3,5,7,9);

begin

Result:=False; err:=false; Sum:=0;

alt:=(length(s) mod 2=0);

for i := 1 to length(s) do

begin

d:=StrToIntDef(s[i],-1);

if d=-1 then

err:=true

else

if alt then sum:=sum+luhn_dbl[d] else sum:=sum+d;

alt:=not alt;

end;

Result:= (sum mod 10 =0) and (not err);

end;

Esteban,

Apologies, I posted a comment about using the prefix of the card to determine what information to verify and then noticed your comment that this wasn't acceptable for a global solution - so that is the reason I deleted the post.

Having said that, we have just had our new mail order system accredited by our authorising company and they are delighted that we make use of the IIN tables to pre-validate data before requesting authorisation from them. In fact they did say they wished more people would ;-) !

Apologies once again for clogging up you blog without first fully reading your comments,

Trevor

thank you

Post a Comment