unit Creditc;
{ Überprüft eine Kreditkartennummer anhand Länge, Kartentyp und Checksumme
function IsValidCreditCardNumber( CardNumber: String; var MessageText: String ): Boolean;
return true --> Nummer OK, Messagetext übergibt den Kartentyp
return false --> Nummer ungültig, Messagetext erklärt genaueres
}
interface
uses SysUtils;
function IsValidCreditCardNumber( CardNumber:
String;
var MessageText:
String ): Boolean;
implementation
const
CardPrefixes:
array[ 1..19 ]
of string =
( '
2014', '
2149', '
300', '
301', '
302',
'
303', '
304', '
305', '
34', '
36', '
37',
'
38', '
4', '
51', '
52', '
53', '
54', '
55', '
6011' );
CardTypes:
array[ 1..19 ]
of String =
( '
enRoute',
'
enRoute',
'
Diner Club/Carte Blanche',
'
Diner Club/Carte Blanche',
'
Diner Club/Carte Blanche',
'
Diner Club/Carte Blanche',
'
Diner Club/Carte Blanche',
'
Diner Club/Carte Blanche',
'
American Express',
'
Diner Club/Carte Blanche',
'
American Express',
'
Diner Club/Carte Blanche',
'
Visa',
'
MasterCard',
'
MasterCard',
'
MasterCard',
'
MasterCard',
'
MasterCard',
'
Discover' );
function RemoveChar(
const Input:
String; DeletedChar: Char):
String;
//wirft DeletedChar aus dem String
var
i: integer;
begin
result := Input;
for i := Length( Result )
downto 1
do
if Result[ i ] = DeletedChar
then Delete( Result, i, 1 );
end;
function ShiftMask( Input: Integer ): Integer;
begin
//Wrapper für shift left Operation
result := ( 1
shl ( Input - 12 ) );
end;
//Checksumme berechnen
function ConfirmChecksum( CardNumber:
String ): Boolean;
var
CheckSum: Integer;
//Checksumme
Flag: Boolean;
i: integer;
Number: integer;
//immer eine Ziffer
begin
i := Length( CardNumber );
CheckSum := 0;
Number := 0;
Flag := false;
while ( i >= 1 )
do
begin
{ get the current digit }
Number := StrToInt(Copy( CardNumber, i, 1 ));
if ( Flag )
then
begin
Number := Number * 2;
if ( Number >= 10 )
then Number := Number - 9;
end;
CheckSum := CheckSum + Number;
Flag :=
not( Flag );
i := i - 1;
end;
result := ( ( CheckSum
mod 10 ) = 0 );
end;
function GetMask( CardName:
String ): Integer;
begin
result := 0;
if ( CardName = '
MasterCard' )
then result := ShiftMask( 16 );
if ( CardName = '
Visa' )
then result := ( ShiftMask( 13 )
or ShiftMask( 16 ) );
if ( CardName = '
American Express' )
then result := ShiftMask( 15 );
if ( CardName = '
Diner Club/Carte Blanche' )
then result := ShiftMask( 14 );
if ( CardName = '
Discover' )
then result := ShiftMask( 16 );
if ( CardName = '
enRoute' )
then result := ShiftMask( 15 );
end;
function IsValidCreditCardNumber( CardNumber:
String;
var MessageText:
String ): Boolean;
var
StrippedNumber:
String;
//Nummer ohne Spezialzeichen
i: integer;
TheMask: integer;
FoundIt: Boolean;
//Kartentyp gefunden
CardName:
String;
//Kartenname
PerformChecksum: Boolean;
//enroute-Karte hat keine Checksumme
begin
// Leerzeichen und - rauswerfen
StrippedNumber := RemoveChar( CardNumber, '
' );
StrippedNumber := RemoveChar( StrippedNumber, '
-' );
// Wenn der String länge 0 hat, ist auch OK (Warum auch immer)
if ( StrippedNumber = '
' )
then begin
result := true;
exit;
end;
MessageText := '
';
result := true;
FoundIt := false;
//ungültige Zeichen herausfischen
for i := 1
to Length( StrippedNumber )
do
begin
case StrippedNumber[ i ]
of
'
0'..'
9': FoundIt := FoundIt;
//hier machen wir nix
else
MessageText := '
ungültige Zeichen in Kartennummer';
result := false;
exit;
end;
end;
//Kartentyp herausfinden
for i := 1
to 19
do
begin
if ( Pos( CardPrefixes[ i ], StrippedNumber ) = 1 )
then
begin
//gefunden
FoundIt := true;
CardName := CardTypes[ i ];
TheMask := GetMask( CardName );
break;
end;
end;
//Wenn kein Kartentyp gefunden, hat die Nummer schon verloren
if (
not FoundIt )
then
begin
CardName := '
Kartentyp nicht bekannt';
TheMask := 0;
MessageText := '
Kartentyp nicht bekannt';
result := false;
exit;
end;
//allgemeine Längenüberprüfung
if ( ( Length( StrippedNumber ) > 28 )
and result )
then
begin
MessageText := '
Nummer ist zu lang';
result := false;
exit;
end;
//genaue Längenprüfung
if ( ( Length( StrippedNumber ) < 12 )
or
( ( shiftmask( length( strippednumber ) )
and themask ) = 0 ) )
then
begin
messagetext := '
ungültige Nummernlänge';
result := false;
exit;
end;
//Checksumme überprüfen
if ( cardname = '
enroute' )
then
performchecksum := false
else
performchecksum := true;
if ( performchecksum
and (
not confirmchecksum( strippednumber ) ) )
then
begin
messagetext := '
ungültige Checksumme';
result := false;
exit;
end;
//Wenn Result immer noch true ist, ist die Nummer gültig
if ( result )
then
messagetext := cardname;
end;
end.