2010-01-23 26 views
21

Qualcuno sa come analizzare l'input di una stringa di carta di credito da uno Swiper Magnetic Card?Ingresso carta di credito spunta da banda magnetica

Ho provato un parser JavaScript ma non l'ho mai fatto funzionare. Ecco come appare l'input.

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

Le N sono il numero di carta di credito.

+10

forse vuole entrare nel business delle carte di credito? –

+1

Mia moglie è una fotografa e io sono uno sviluppatore. Ci siamo appena registrati con PayPal Website Payments Pro e vogliamo essere in grado di elaborare i CC in viaggio (fiere e quant'altro). –

+0

Ho trovato un addin GreaseMonkey per FireFox che mi consente di scorrere verso destra sul terminale virtuale PayPal. Anche se non è l'ideale, farà il trucco se non riesco a capirlo. –

risposta

24

Vedere il Magnetic Stripe Card entry @ Wikipedia:


traccia uno, Formato B:

  • Inizio sentinella - un carattere (generalmente '%')
  • codice Formato = "B" - un carattere (solo alfa)
  • Numero account principale (PAN) - fino a 19 caratteri. Solitamente, ma non , corrisponde sempre al numero di carta di credito stampato sulla parte anteriore della carta.
  • Separatore campo - un carattere (generalmente '^')
  • Nome - da due a 26 caratteri
  • Separatore campo - un carattere (generalmente '^')
  • Data di scadenza - quattro caratteri in forma AAMM.
  • Codice di servizio - tre personaggi
  • dati discrezionale - può includere perno indicatore Controllo delle chiavi (PVKI, 1 carattere), PIN Verification Value (PVV, 4 caratteri), Card Verification Valore o Card Verification Code (CVV o CVK, 3 caratteri)
  • Fine sentinella - un carattere (in genere)
  • longitudinale controllo di ridondanza (LRC) '?' - un carattere (la maggior parte dei dispositivi di lettura non restituire questo valore quando la scheda è fregato al strato di presentazione, e usarlo solo per verificare l'ingresso internamente al lettore)

spero che il dato è falso, altrimenti Chiunque poteva ottenere il:. Nome

  • Data di scadenza
  • CVV

E non sono sicuro, ma penso che il numero di carta di credito (o numero di possibilità) può essere calcolato utilizzando il LRC.

+0

Se si sta scrivendo sul lettore di bande magnetiche e si utilizza una modalità di scrittura non elaborata, calcolare l'algoritmo LRC può essere un po 'di confusione che si deve fare da soli, se si utilizza la normale modalità di scrittura, la macchina di scorrimento si prenderà cura di quello per te. Ma per la lettura, la macchina a scorrimento calcola automaticamente l'LRC per verificare che il colpo sia andato a buon fine. – t0mm13b

+4

I dati della carta sono falsi. –

+1

Quanto è corretto calcolare LRC per traccia? – bmalets

2

Da quello che posso ricordare:

che è un due tracce di dati a banda magnetica - primo brano inizia con % e termina con ?, la seconda traccia inizia con ; e termina con ?. Questi sono marcatori Inizio/Fine.

La prima traccia è alfanumerica, la seconda traccia è numerica, e c'è una terza traccia che è anche numerica (se la mia memoria è corretta).

I dati tra i marcatori di inizio/fine possono essere variabili a seconda della densità di registrazione della banda magnetica. Maggiore è la densità, più può essere registrata su una traccia.

L'utilizzo di un'espressione regolare per ottenere i dati potrebbe non essere un metodo affidabile per individuare le informazioni richieste.

E non tutte le carte di credito hanno esattamente due tracce, alcune utilizzano tre tracce.

1

In genere per una transazione non presente sulla carta (cioè transazioni MOTO) è necessario cC#, scadenza e, eventualmente, CVV (ovvero CVC2, ecc.). È possibile ottenere i primi 2 da uno scambio di carte come questo nei dati di traccia. CVV è stampato sulla carta.

Il nome sulla carta non ha importanza. A meno che l'acquirente e il titolare della carta non stiano utilizzando la verifica dell'indirizzo, ma è possibile trovarlo tra ^^, potrebbe contenere spazi vuoti che è possibile rimuovere.

La parte che si desidera è traccia2 NNNNNNNNNNNNNNNNN = 1210 dove NNNNN = numero di scheda PAN e 1210 = Data di scadenza.

Anche se track1 è vuoto (che a volte è come non viene utilizzato nell'elaborazione), si otterrà comunque il;?, Quindi è possibile utilizzare l'indice del secondo; come inizio della stringa e = come la fine della stringa cC#. Con i 4 caratteri dopo il = come la scadenza.

Vorrei consigliare al titolare della carta di firmare qualcosa in registrazione della transazione altrimenti potrebbero contestare la carta e fare un riaddebito.

E non tutte le carte di credito hanno esattamente due tracce, alcune utilizzano tre tracce.

Solo track2 viene utilizzato per l'elaborazione e ha un formato standardizzato.

Le carte di debito non possono generalmente essere elaborate (a meno che non abbiano una carta Visa-Bit o qualcosa del genere).

P.S. non si dovrebbero memorizzare i dati cc in testo normale, quindi provare e tenere tutto in mem o crittografia avanzata.

5

ti ho fatto uno migliore: ho fatto un video che mostra come fare esattamente questo con ASP.Net/c#:

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

Ecco la sezione di codice che probabilmente vi preoccupate:

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); 
     } 
    } 

Il codice completo si trova sul sito Web che ho collegato sopra.

1
+0

Il primo collegamento è quello che cercavo ovunque. Sembra avere la convalida dei dati di traccia e persino un timeout. Fortunatamente o sfortunatamente è un pezzo di codice piuttosto impressionante, che è semplicemente al di là delle mie capacità di implementare. Puoi aggiungere un esempio su come utilizzare la funzione CardReader? Nel mio codice di lettura traccia, che aggiungerò come post separato, ho un ascoltatore, che non vedo in CardReader. – Iannazzi

+0

Appena pubblicato il mio lettore di tracciamento e il codice parser qui sotto ... è necessario integrare la convalida CardReader – Iannazzi

0

Ecco il mio codice:

prima l'ascoltatore per ottenere i dati .... questo i dati devono essere convalidati e sto cercando aiuto. Un buon scorrimento funziona bene, ma un colpo brutto causerà un errore nel parser.

$('#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? 

}); 

E qui è il parser .... nota che ho messo tutto in una funzione in modo da poter distruggere tutte le variabili in modo che non siano persistente nella un browser.

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"); 
} 
+0

Ho aggiunto if (card_data.indexOf ('=') === -1 || card_data.indexOf ('^') === -1) per convalidare i dati di scorrimento, che eliminano uno swipe errato, ma questo non è esattamente lo stesso dei controlli longitudinali di ridondanza richiesti da auth.net: "I controlli longitudinali di ridondanza (LRC) devono essere calcolati per i dati leggere dalla traccia e confrontato con LRC letto dalla traccia: si presuppone che i dati della traccia vengano letti senza errori quando non vengono rilevati errori di parità di caratteri e gli LRC calcolati e letti corrispondono ". -card guida presente – Iannazzi

Problemi correlati