Analizuj wejście karty kredytowej z paska magnetycznego

Czy ktoś wie jak parsować wejście ciągu karty kredytowej z suwaka karty magnetycznej?

Próbowałem parsera JavaScript, ale nigdy nie dostałem go do pracy. Tak wygląda wejście.

%BNNNNNNNNNNNNNNNN^DOE/JOHN
^1210201901000101000100061000000?;NNNNNNNNNNNNNNNN=12102019010106111001?

N to numer karty kredytowej.

Author: Chase Florell, 2010-01-23

6 answers

Zobacz wpis Karta Z Paskiem Magnetycznym @ Wikipedia:


Ścieżka pierwsza, Format B:

  • Start sentinel-jeden znak (ogólnie'%')
  • Format code = " B " - jeden znak (tylko Alfa)
  • numer konta głównego (PAN) - do 19 znaków. Zazwyczaj, ale nie zawsze pasuje do numeru karty kredytowej wydrukowany z przodu karty.
  • Separator pól - jeden znak (ogólnie'^')
  • Nazwa-od 2 do 26 znaków
  • Separator pól - jeden znak (ogólnie'^')
  • data ważności-cztery znaki w formie YYMM.
  • kod serwisowy-trzy znaki
  • dane uznaniowe - mogą zawierać wskaźnik klucza weryfikacji Pin (PVKI, 1 znak), wartość weryfikacji PIN (PVV, 4 znaki), weryfikacja karty Wartość lub kod weryfikacyjny karty (CVV lub CVK, 3 znaki)
  • End sentinel-jeden znak ( ogólnie '?')
  • Longitudinal redundancy check (LRC) - jeden znak (Większość czytników nie zwracaj tej wartości, gdy karta przesuwa się do warstwy prezentacji, i używaj go tylko do weryfikacji danych wejściowych wewnętrznie do czytelnika.)

mam nadzieję, że dane są fałszywe, w przeciwnym razie każdy może dostać:

  • Nazwa
  • Data Ważności
  • CVV

i nie jestem pewien, ale myślę, że numer karty kredytowej (lub # możliwości) można obliczyć za pomocą LRC.

 24
Author: Alix Axel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-23 03:14:21

Zrobiłem coś lepszego: zrobiłem filmik pokazujący jak to zrobić dokładnie z ASP.Net/c#:

Http://www.markhagan.me/Samples/CreditCardSwipeMagneticStripProcessing

Oto sekcja kodu, na której prawdopodobnie ci zależy:

    protected void CardReader_OTC(object sender, EventArgs e)
    {
        bool CaretPresent = false;
        bool EqualPresent = false;

        CaretPresent = CardReader.Text.Contains("^");
        EqualPresent = CardReader.Text.Contains("=");

        if (CaretPresent)
        {
            string[] CardData = CardReader.Text.Split('^');
            //B1234123412341234^CardUser/John^030510100000019301000000877000000?

            PersonName.Text = FormatName(CardData[1]);
            CardNumber.Text = FormatCardNumber(CardData[0]);
            CardExpiration.Text = CardData[2].Substring(2, 2) + "/" + CardData[2].Substring(0, 2);
        }
        else if (EqualPresent)
        {
            string[] CardData = CardReader.Text.Split('=');
            //1234123412341234=0305101193010877?

            CardNumber.Text = FormatCardNumber(CardData[0]);
            CardExpiration.Text = CardData[1].Substring(2, 2) + "/" + CardData[1].Substring(0, 2);
        }
    }

Pełny kod znajduje się na tej stronie, którą podlinkowałem powyżej.

 6
Author: Mark Hagan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-09 16:32:13

Z tego co pamiętam:

Jest to dwutorowa Taśma magnetyczna-pierwsza ścieżka zaczyna się od % i kończy się na ?, druga ścieżka zaczyna się na ; i kończy się na ?. Są to znaczniki początku/końca.

Pierwsza ścieżka jest alfanumeryczna, druga ścieżka jest numeryczna, a trzecia ścieżka jest również numeryczna (jeśli moja pamięć jest poprawna).

Dane między znacznikami początku/końca mogą być zmienne w zależności od gęstości zapisu paska magnetycznego. Im większa gęstość, tym bardziej można ją nagrać na jednej ścieżce.

Użycie wyrażenia regularnego do uzyskania danych może nie być wiarygodną metodą, aby wybrać wymagane informacje.

I nie wszystkie karty kredytowe mają dokładnie dwa utwory, niektóre używają trzech utworów.

 2
Author: t0mm13b,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-13 18:15:10

Ogólnie do transakcji bez karty (tj. transakcji MOTO) będziesz potrzebował cc#, expiry i ewentualnie CVV (aka CVC2 itp.). Możesz uzyskać pierwsze 2 z karty-przesuń jak to w danych utworu. CVV jest drukowany na karcie.

Imię na karcie nie ma większego znaczenia. Chyba że Twój acquirer i posiadacz karty używają weryfikacji adresu, ale możesz zauważyć, że między ^ ^ może mieć białe odstępy, które możesz usunąć.

The part you want is track2 NNNNNNNNNNNNNNN=1210, gdzie NNNNNN = numer karty PAN, a 1210 = data ważności.

Nawet jeśli track1 jest pusty (co czasami jest, ponieważ nie jest używany w przetwarzaniu), nadal otrzymasz ;?, więc możesz użyć indeksu drugiego; jako początku łańcucha i = jako końca łańcucha CC#. Z 4 znakami po = jako wygaśnięcie.

Radzę, aby Posiadacz karty podpisał coś w dokumentacji transakcji, w przeciwnym razie mogliby zakwestionować kartę i zrobić / align = "left" /

I nie wszystkie karty kredytowe mają dokładnie dwa utwory, niektóre używają trzech utworów.

Tylko track2 jest używany do przetwarzania i ma znormalizowany format.

Karty debetowe zazwyczaj nie mogą być przetwarzane(chyba że mają kartę Visa-debetową lub coś takiego).

P. S. nie powinieneś przechowywać danych cc w zwykłym tekście, więc staraj się zachować wszystko w mem lub silnym szyfrowaniu.

 1
Author: Kakkerlakkie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-02 05:05:29
 1
Author: Ana El Bembo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-20 03:29:25

Oto Mój kod:

Pierwszy słuchacz, aby uzyskać dane.... te dane wymagają walidacji, w której szukam pomocy. Dobre machnięcie działa dobrze, ale złe machnięcie spowoduje błąd w parserze.

$('#cc-dialog-form').keypress(function(e) 
{

    var charCode = e.which;
    //ie? evt = e || window.event;
    track_start = '%';
    finished = false;
    timeout = 100;
    track_start_code = track_start.charCodeAt(0);
    //console.log('Track_start_code: ' + track_start_code);

    //console.log('keycode ' + e.keycode);


    //console.log('charcode ' + charCode);
    //console.log('track_start_code ' + track_start_code);
    if (charCode == track_start_code)
    {
        collect_track_data = true;
            $('#offline_cc_entry').hide();
            $('#cc_online').hide();
            $('#Manual_CC_DATA').hide();
            $('#cc_loading_image').show();      

    }
    if (collect_track_data)
    {   
        if (charCode == $.ui.keyCode.ENTER) 
        {
            //all done
            //console.log( card_data);
            collect_track_data = false;
            $('#cc_loading_image').hide();
            $('#Manual_CC_DATA').show();
            //console.log("Track Data: " + card_data);


            process_swipe_cc_payment(card_data);
            card_data = '';

        }
        else
        {
            card_data = card_data + String.fromCharCode(charCode);
            console.log(card_data);
            if (e.preventDefault) e.preventDefault();
            e.returnValue=false;
            return false;
        }
    }
    else
    {
        //i am guessing this will be regular input?
        if (charCode == $.ui.keyCode.ENTER) 
        {
             process_keyed_or_offline_CC_payment();
        }
    }
    //console.log("which: " + e.which);
    //console.log("keyCode: " + e.keyCode);
    //track and collect data here?

});

A oto parser.... Uwaga umieściłem to wszystko w jednej funkcji, więc mogę zniszczyć wszystkie zmienne, aby nie pozostały w przeglądarce.

    parse_data = true;
if (parse_data)
{

var parsed_card_data = {};
parsed_card_data['card_data'] = card_data;
var tracks = card_data.split("?");

//console.log ("tracks");
//console.log (tracks);
parsed_card_data['track1'] = tracks[0];
parsed_card_data['track2'] = tracks[1];
//if there is a third track we might find it under tracks[2]

//splitting the card data OPTION 1

var track1_parsed = tracks[0].split("^");

//console.log (track1_parsed);



//track1 data....
var card_number_track1 = track1_parsed[0].substring(2);


parsed_card_data['card_number_track1'] = card_number_track1;

var details2_1 = tracks[1].split(";");
details2_1 = details2_1[1].split("=");


var exp_date_track_1 = details2_1[1];
exp_date_track_1 = exp_date_track_1.substring(0, exp_date_track_1.length - 1);
exp_date_track_1 = exp_date_track_1.substring(2, 4) + "/" + exp_date_track_1.substring(0,2);
parsed_card_data['exp_track1'] = exp_date_track_1;



//now check if track one matches track 2...

track2_parsed = tracks[1].split("=");


card_number_track_2 = track2_parsed[0].substring(1);



parsed_card_data['card_number_track_2'] = card_number_track_2;
exp_date_track_2 = track2_parsed[1].substring(0,4);
exp_date_track_2 = exp_date_track_2.substring(2, 4) + "/" + exp_date_track_2.substring(0,2);
parsed_card_data['exp_date_track_2'] = exp_date_track_2;


var primary_account_number =  card_number_track1.substring(0,1);


if(card_number_track1 == card_number_track_2 &&  exp_date_track_1 == exp_date_track_2)
{
        //now make a security feature showing the last 4 digits only....
    parsed_card_data['secure_card_number'] = "xxxx " + card_number_track1.substring(card_number_track1.length-4, card_number_track1.length);




    if(card_number_track1.length == 15)
    {
        parsed_card_data['card_type'] = "American Express"; 
    }
    else if(primary_account_number == 4)
    {
        parsed_card_data['card_type'] = "Visa";
    }
    else if(primary_account_number == 5)
    {
        parsed_card_data['card_type'] = "Master Card";
    }
    else if(primary_account_number == 6)
    {
        parsed_card_data['card_type'] = "Discover";
    }
    else
    {
        parsed_card_data['card_type'] = false;
    }

    var names_1 = track1_parsed[1].split("/");
    parsed_card_data['first_name'] = names_1[1].trim();
    parsed_card_data['last_name'] = names_1[0].trim();


    //console.log("return Data");
    //console.log(return_data);

}
else
{
    parsed_card_data = false;
}

    //zero out the variables...

    tracks = '';
    track1_parsed = '';
    card_number_track1 = '';
    details2_1 = '';
    exp_date_track_1 = '';
    track2_parsed = '';
    card_number_track_2 = '';
    exp_date_track_2 = '';
    primary_account_number = '';
}

if(parsed_card_data)
{
    //console.log(parsed_card_data);
    $('#card_type').val(parsed_card_data['card_type']);
    $('#credit_card_number').val(parsed_card_data['secure_card_number']);
    $('#expiration').val(parsed_card_data['exp']);
    $('#card_holder').val(parsed_card_data['first_name']+ " " + parsed_card_data['last_name']);

    //parsed_card_data['track1'] is basically what we want???

    $('#CC_SWIPE_INSTRUCTIONS').hide();
    $('#CC_DATA').hide();
    $('#cc_loading_image').show();



    var post_string = {};
    post_string['ajax_request'] = 'CREDIT_CARD_PAYMENT';
    post_string['amount'] = $('#cc_input').val();
    post_string['card_data'] = parsed_card_data;
    post_string['pos_sales_invoice_id'] = pos_sales_invoice_id;
    post_string['pos_payment_gateway_id'] = $('#pos_payment_gateway_id').val();
    post_string['line'] = 'online';
    post_string['swipe'] = 'swipe';

    card_data = '';
                parsed_card_data = {};
    var url = 'ajax_requests.php';
    $.ajax({
            type: 'POST',
            url: url,
            data: post_string,
            async: true,
            success:    function(response) 
            {
                $('#cc_loading_image').hide();
                console.log(response);
                $('#CC_RESPONSE').show();
                $('#CC_RESPONSE').html(response);
                //here we would update the payment table - currently we will just refresh

                post_string = '';

            }
            });
    post_string = '';
}
else
{
    //error
    alert("Read Error");
    $( "#cc-dialog-form" ).dialog( "close" );
}
 1
Author: Iannazzi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-24 02:20:45