[Delphi] libExtractCC - Извлечение данных

comm1x

VIP member
Messages
428
Reputation
74
Reaction score
116
Points
43
Код библиотеки Delphi для извлечения данных из строки.
Сохраняем в директорию с проектом, как "libExtractCC.pas", жмем, Shift+F11, добавляем, прописываем в uses. Используемая функция "ExtractCCData()"

Узкие места:
ExpData распознается в виде "mmyy" или "mm yyyy".
Вид "mm yy" (или любой другой разделитель) не поддерживается.
Cvv распознается только трехзначный.

Обновление: Теперь скрипт распознает данные как в начале так и в конце строки. Добавлена функция проверки данных. Т. о. на входе мы имеем массив строк размерности n, на выходе получаем двумерный массив размерности nx5:
{n1[cc: string], n2[mm: string], n3[yyyy: string], n4[cvv: string], n5[error: integer]}, где n5[error: integer]>0 - строки, не прошедшие проверку данных.

PHP:
unit libExtractCC;

interface

uses
  SysUtils, Dialogs;

function IsNumber(data: char): Integer;
function CheckData(ccdata: array of string): Integer;
procedure FindCC(var ccdata, cc: string);
procedure FindCvv(var ccdata, cc, cvv: string);
procedure FindExpDate(var ccdata, exp_m, exp_y: string);
procedure ExtractCCData(var ccdata: string; var result: array of string);


implementation
var
  pos : real;

function IsNumber(data: char): Integer;
begin
  if (Ord(data) >= 48) and (Ord(data) <= 57) then
    IsNumber := 1
  else
    IsNumber := 0;
end;

function CheckData(ccdata: array of string): Integer;
var
  i, err: Integer;
begin
  err := 0;

  if Length(ccdata[0]) <> 16 then
    inc(err);

  if Length(ccdata[1]) <> 2 then
    inc(err)
  else
  begin
  {  if (StrToInt(ccdata[1]) < 1) or (StrToInt(ccdata[1]) > 12) then
      inc(err); }
  end;

  if Length(ccdata[2]) <> 4 then
    inc(err)
  else
  begin
    if (StrToInt(ccdata[2]) < 2011) or (StrToInt(ccdata[1]) > 2020) then
      inc(err);
  end;

  if Length(ccdata[3]) <> 3 then
    inc(err);

  CheckData := err;
end;

procedure FindCC(var ccdata, cc: string);

var
  i, j: Integer;
begin
  j := 0;
  for i := 0 to Length(ccdata) do
  begin
    if IsNumber(ccdata[i]) = 1 then
    begin
      inc(j);
      cc := cc + ccdata[i];
      if (j = 16) and (IsNumber(ccdata[i + 1]) = 0) then
        break;
    end
    else
    begin
      j := 0;
      cc := '';
    end;
  end;
end;

procedure FindExpDate(var ccdata, exp_m, exp_y: string);
var
  i, j, position: Integer;
  m_left, m_right, y_pxe: string;
  dist_l, dist_r: Integer;
  k: string;
begin
  j := 0;
  if pos > 2 then
  begin
    for i := 0 to Length(ccdata) do
    begin
      if (IsNumber(ccdata[i]) = 1) then
      begin
        inc(j);
        exp_y := exp_y + ccdata[i];
        if (j = 4) and (IsNumber(ccdata[i + 1]) = 0) then
          break;
      end
      else
      begin
        j := 0;
        exp_y := '';
      end;
    end;
  end
  else 
  begin
    for i := Length(ccdata) downto 0 do
    begin
      if (IsNumber(ccdata[i]) = 1) then
      begin
        inc(j);
        exp_y := exp_y + ccdata[i];
        if (j = 4) and (IsNumber(ccdata[i - 1]) = 0) then
          break;
      end

      else
      begin
        j := 0;
        exp_y := '';
      end;
    end;
    y_pxe := exp_y;
    exp_y[1] := y_pxe[4];
    exp_y[2] := y_pxe[3];
    exp_y[3] := y_pxe[2];
    exp_y[4] := y_pxe[1];
  end;

  if StrToInt(Copy(exp_y, 1, 2)) = 20 then
  begin
    j := 0;
    position := AnsiPos(exp_y, ccdata) - 1;
    for i := 0 to position - 1 do
    begin
      if (Ord(ccdata[position - i]) >= 48) and
        (Ord(ccdata[position - i]) <= 57) then
      begin
        inc(j);
        m_left := m_left + ccdata[position - i];
        if (j = 2) and (IsNumber(ccdata[position - i - 1]) = 0) then
          break;
      end
      else
      begin
        j := 0;
        m_left := '';
      end;
    end;
    dist_l := i - 1;
    SetLength(k, 1);
    k[1] := m_left[1];
    m_left[1] := m_left[2];
    m_left[2] := k[1];

    j := 0;
    position := AnsiPos(exp_y, ccdata) + 4;
    for i := 0 to Length(ccdata) - position do
    begin
      if IsNumber(ccdata[position + i]) = 1 then
      begin
        inc(j);
        m_right := m_right + ccdata[i + position];
        if (j = 2) and (IsNumber(ccdata[position + i]) = 0) then
          break;
      end
      else
      begin
        j := 0;
        m_right := '';
      end;
    end;
    dist_r := i - 1;

    if dist_l <= dist_r then
      exp_m := m_left
    else
      exp_m := m_right;

  end
  else
  begin
    exp_m := Copy(exp_y, 1, 2);
    exp_y := '20' + Copy(exp_y, 3, 2);
  end;
end;

procedure FindCvv(var ccdata, cc, cvv: string);
var
  i, j: Integer;
  vvc: string;
begin
  j := 0;
  if pos > 2 then
  begin
    for i := 0 to Length(ccdata) do
    begin
      if IsNumber(ccdata[i]) = 1 then
      begin
        inc(j);
        cvv := cvv + ccdata[i];
        if (j = 3) and (IsNumber(ccdata[i + 1]) = 0) then
          break;
      end
      else
      begin
        j := 0;
        cvv := '';
      end;
    end;
  end
  else
  begin
    for i := Length(ccdata) downto 0 do
    begin
      if IsNumber(ccdata[i]) = 1 then
      begin
        inc(j);
        cvv := cvv + ccdata[i];
        if (j = 3) and (IsNumber(ccdata[i - 1]) = 0) then
          break;
      end
      else
      begin
        j := 0;
        cvv := '';
      end;
    end;
    vvc := cvv;
    cvv[1] := vvc[3];
    cvv[3] := vvc[1];
  end;
end;

procedure ExtractCCData(var ccdata: string; var result: array of string);
begin
  FindCC(ccdata, result[0]);
  pos := Length(ccdata) / (AnsiPos(result[0], ccdata) + 8);
  FindExpDate(ccdata, result[1], result[2]);
  FindCvv(ccdata, result[0], result[3]);
  result[4] := IntToStr(CheckData(result));
end;

//from CMX.CC Checking 1.2
//comm1x (c)

end.

comm1x (c)
 
Last edited:

xanter

VIP member
Messages
834
Reputation
78
Reaction score
109
Points
43
спасиб за статью, побольше бы таких статей ;)
 

comm1x

VIP member
Messages
428
Reputation
74
Reaction score
116
Points
43
Обновил библиотеку.
 

xanter

VIP member
Messages
834
Reputation
78
Reaction score
109
Points
43
как всегда , спасибо за обнову..
 
Top