Tuesday, September 02, 2008

Credit Card number validator for Delphi

We are implementing parts of a global electronic payment solution and one of the mandatory features was to verify credit card numbers. This is done using the Luhn algorithm. I was expecting to find a wide variety of implementations on our sexy Delphi language but to my surprise there were very few hits on my search.

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.

A painless self-hosted Git service

Remember how a part of my NAS setup was to host my own Git server? Well that forced me to review options and I stumble into Gitea .  A extr...