Данный модуль создан на основе алгоритма ccard автора Peter Miller. Автор не против бесплатного использования, но резервирует все права на данный алгоритм.
авторское право 1996 Shawn Wilson Harvell ( shawn@inet.net )
применение:
Внесите данный модуль в список uses любого модуля, которому необходим доступ к функции проверки кредитной карты.
например, используйте это для уведомления пользователя о недействительности карты. CardNumber - строка, содержащая номер карты, которую необходимо проверить ReturnMessage - строка, с помощью которой функция может возвратить любое сообщение ( при этом старое содержимое строки стирается )
возвращает true если номер карточки верен, false - в противном случае.
во входных параметрах функции допускаются тире и пробелы, если же возможно присутствие других символов, вы можете их удалить. Функция RemoveChar довольно легко позаботится об этом, просто передайте ей входную строку и символ, который вы хотите удалить.
Пользователь может свободно изменять код модуля для собственных целей, но в случае его распространения он должен сообщить пользователям обо всех внесенных изменениях.
Используйте модуль на свой страх и риск, поскольку он свободен от явных и неявных гарантий. Ответственность за какой-либо ущерб, причиненный данным модулем лежит на его пользователе.
На момент написания модуля он устойчиво работал под Delphi версий 1 и 2, для Turbo Pascal необходимо внести некоторые несложные исправления (главным образом из-за различия реализации функций в модуле SysUtils).
Если вы нашли этот модуль полезным, имеете какие-то пожелания или предложения, отправьте автору письмо по адресу электронной почты shawn@inet.net
История изменений
версия 1.1 -- Декабрь 20, 1996 исправлена ошибка с Discover card: соответственно увеличина длина маски "database"
function RemoveChar(const Input: String; DeletedChar: Char): String; var
Index: Word; { переменная счетчика }begin
{ данная функция удаляет все вхождения указанного символа из переданной ей } { строки } Result := Input; for Index := Length( Result ) downto 1 do if Result[ Index ] = DeletedChar then Delete( Result, Index, 1 );end;
function ShiftMask( Input: Integer ): Integer; begin
{ простая оболочка для функции сдвига битов числа } result := ( 1 shl ( Input - 12 ) );end;
function ConfirmChecksum( CardNumber: String ): Boolean; var
CheckSum: Integer; { Содержит значение операции } Flag: Boolean; { флаг готовности } Counter: Integer; { индекс счетчика } PartNumber: String; { используется для извлечения каждой цифры числа} Number: Integer; { исп-ся для преобразования каждой цифры в число}begin
{************************************************************************** Это, вероятно, самая запутанный код, который вы когда-либо видели, я и сам запутался, когда работал над ним. Основное, что делает данная функция - извлекает каждую цифру из номера карты для использования в формуле проверки контрольной суммы, устанавливаемую компаниями. Алгоритм производит выборку, начиная от последней цифры и заканчивая первой. **************************************************************************}
{ получаем стартовое значение счетчика } Counter := Length( CardNumber ); CheckSum := 0; PartNumber := ''; Number := 0; Flag := false;
while ( Counter >= 1 ) do begin { получаем текущую цифру } PartNumber := Copy( CardNumber, Counter, 1 ); Number := StrToInt( PartNumber ); { преобразуем в число } if ( Flag ) then { только каждую вторую цифру } 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;
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 ); end;
function IsValidCreditCardNumber( CardNumber: String; var MessageText: String ): Boolean; var
StrippedNumber: String; { используется для хранения числа без дополнительных символов } Index: Integer; { универсальный счетчик для циклов и т.п. } TheMask: Integer; { число, которое мы будем использовать для маски } FoundIt: Boolean; { используется для индикации, когда что-либо найдено } CardName: String; { хранит имя типа карты } PerformChecksum: Boolean; { тип enRoute карты если контрольная сумма не сошлась }begin
{ сначала избавимся от пробелов и тире } StrippedNumber := RemoveChar( CardNumber, ' ' ); StrippedNumber := RemoveChar( StrippedNumber, '-' );
{ если строка была нулевой длины, то тоже OK } if ( StrippedNumber = '' ) then begin result := true; exit; end;
{ проверка правильности введенных символов в номере карты } for Index := 1 to Length( StrippedNumber ) do begin case StrippedNumber[ Index ] of '0'..'9': FoundIt := FoundIt; { другими словами не op } else MessageText := 'Неверный введенный символ'; result := false; exit; end; end;
{ теперь давайте определим тип используемой карты } for Index := 1 to 19 do begin if ( Pos( CardPrefixes[ Index ], StrippedNumber ) = 1 ) then begin { мы обнаружили правильный тип } FoundIt := true; CardName := CardTypes[ Index ]; TheMask := GetMask( CardName ); end; end;
{ если тип карты не определен, указываем на это } if ( not FoundIt ) then begin CardName := 'Unknown Card Type'; TheMask := 0; MessageText := 'Неизвестный тип карты '; result := false; exit; end;
{ проверка длины } if ( ( Length( StrippedNumber ) > 28 ) and result ) then begin MessageText := 'Номер слишком большой '; result := false; exit; end;
{ проверка длины } if ( ( Length( StrippedNumber ) < 12 ) or ( ( shiftmask( length( strippednumber ) ) and themask ) = 0 ) ) then begin messagetext := 'неверная длина числа'; result := false; exit; end;
{ проверяем вычисление контрольной суммы } if ( cardname = 'enroute' ) then performchecksum := false else performchecksum := true;
if ( performchecksum and ( not confirmchecksum( strippednumber ) ) ) then begin messagetext := 'неверная контрольная сумма'; result := false; exit; end;
{ если результат равен true, тогда все ok } if ( result ) then messagetext := 'номер верен: тип карты: ' + cardname;
{ если строка была нулевой длины, то тоже OK } if ( strippednumber = '' ) then result := true; end;