2010-01-23 31 views
21

¿Alguien sabe cómo analizar una entrada de cadena de tarjeta de crédito desde una tarjeta magnética Swiper?Parse Entrada de tarjeta de crédito desde la banda magnética

Probé un analizador de JavaScript pero nunca lo hice funcionar. Así es como se ve la entrada.

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

Las N son el número de la tarjeta de crédito.

+10

tal vez quiere entrar en el negocio de las terminales de tarjetas de crédito? –

+1

Mi esposa es fotógrafa y yo soy un desarrollador. Acabamos de registrarnos en PayPal Payments Pro y queremos poder procesar CC en el camino (ferias comerciales y demás). –

+0

Encontré un complemento de GreaseMonkey para FireFox que me permite pasar directamente a la terminal virtual de PayPal. Aunque no es ideal, funcionará si no puedo resolver esto. –

Respuesta

24

Véase el Magnetic Stripe Card entry @ Wikipedia:


pista uno, Formato B:

  • inicio centinela - un carácter (por lo general '%')
  • código de formato = "B" - un caracter (solo alfa)
  • Número de cuenta principal (PAN): hasta 19 caracteres. Usualmente, pero no siempre, coincide con el número de tarjeta de crédito impreso en el frente de la tarjeta.
  • Separador de campo - un carácter (por lo general '^')
  • Nombre - dos a 26 caracteres
  • Separador de campo - un carácter (por lo general '^')
  • Fecha de caducidad - cuatro caracteres en forma AAMM.
  • Código de servicio - tres caracteres
  • datos discrecional - puede incluir PIN de verificación de indicadores clave (PVKI, 1 carácter), Valor de Verificación del PIN (PVV, 4 caracteres), verificación de la tarjeta Valor o Código de verificación de tarjeta (CVV o CVK, 3 caracteres)
  • Fin centinela - un carácter (en general)
  • comprobación de redundancia longitudinal (LRC) '?' - un carácter (la mayoría de los dispositivos de lectura no devuelva este valor cuando la tarjeta se desliza a la capa de presentación, y sólo lo utiliza para verificar la entrada internamente para el lector)

espero que el dato es falso, de lo contrario Cualquiera podía conseguir el:. Nombre

  • Fecha de caducidad
  • CVV

Y no estoy seguro, pero creo que el número de tarjeta de crédito (o el n. ° de posibilidades) se puede calcular utilizando el LRC.

+0

Si está escribiendo en el lector de banda magnética y usando un modo de escritura en bruto, entonces calcular el algoritmo LRC puede ser un poco confuso, lo cual debe hacer usted mismo, si usa el modo normal de escritura, la máquina de deslizamiento se ocupará de eso para ti. Pero para leer, la máquina de deslizamiento calculará automáticamente el LRC para verificar que el deslizamiento fue exitoso. – t0mm13b

+4

Los datos de la tarjeta son falsos. –

+1

¿Qué tan correcto es calcular LRC para rastrear? – bmalets

2

Por lo que puedo recordar:

Eso es un conjunto de datos de banda magnética de dos pistas - primera pista comienza con % y termina con ?, la segunda pista se inicia con ; y termina con ?. Estos son marcadores de inicio/final.

La primera pista es alfanumérica, la segunda pista es numérica, y hay una tercera pista que también es numérica (si mi memoria funciona correctamente).

Los datos entre los marcadores de inicio/final pueden variar dependiendo de la densidad de grabación de la banda magnética. Cuanto mayor es la densidad, más se puede grabar en una pista.

Usar una expresión regular para obtener los datos puede no ser un método confiable para seleccionar la información requerida.

Y no todas las tarjetas de crédito tienen exactamente dos pistas, algunas usan tres pistas.

1

En general, para una transacción con tarjeta no presente (es decir, transacciones MOTO) necesitará cC#, vencimiento y posiblemente el CVV (también conocido como CVC2, etc.). Puede obtener los primeros 2 desde un deslizamiento de tarjeta como este en los datos de la pista. CVV está impreso en la tarjeta.

El nombre en la tarjeta no importa tanto. A menos que su adquirente y el titular de la tarjeta estén usando la verificación de dirección, pero puede encontrar que entre ^^, puede tener un espacio en blanco que puede eliminar.

La parte que desea es track2 NNNNNNNNNNNNNNNN = 1210 donde NNNNN = número de tarjeta PAN y 1210 = Fecha de caducidad.

Incluso si track1 está vacío (lo que a veces es porque no se usa en el procesamiento), igual obtendrá el;?, Por lo que podría usar el índice del segundo; como comienzo de la cadena y = como el final de la cadena de CC#. Con los 4 caracteres después de = como el vencimiento.

Aconsejaría que el titular de la tarjeta firme algo en el registro de la transacción; de lo contrario, podrían disputar la tarjeta y realizar un reembolso.

Y no todas las tarjetas de crédito tienen exactamente dos pistas, algunas utilizan tres pistas.

Sólo pista2 se utiliza para el procesamiento y tiene un formato estandarizado.

Las tarjetas de débito generalmente no se pueden procesar (a menos que tengan una tarjeta de débito o visa).

P.S. no debe almacenar datos de CC en texto sin formato, intente mantener todo en memoria fuerte o cifrado.

5

te hizo algo mejor: hice un video que muestra cómo hacer exactamente esto con ASP.Net/c#:

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

Aquí está la sección de código que es probable que se preocupan por:

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

El código completo está en el sitio web que he vinculado anteriormente.

1
+0

El primer enlace es lo que estaba buscando en todas partes. Parece tener validación de datos de seguimiento e incluso un tiempo de espera. Afortunada o desafortunadamente es una pieza de código bastante impresionante, que simplemente está más allá de mis capacidades de implementación. ¿Puedes agregar un ejemplo sobre cómo usar la función CardReader? En mi código de lectura de pistas, que agregaré como una publicación separada, tengo un oyente, que no veo en CardReader. – Iannazzi

+0

Acabo de publicar mi lector de pistas y el código del analizador a continuación ... necesito integrar la validación de CardReader – Iannazzi

0

aquí es mi código:

primero al oyente para obtener los datos de esta .... datos necesitan validación en la que estoy buscando ayuda. Un buen deslizamiento funciona bien, pero un deslizamiento incorrecto provocará un error en el analizador.

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

}); 

Y aquí es el analizador .... en cuenta lo puse todo en una función para que pueda destruir todas las variables para que no sean persistentes en un navegador.

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

Agregué if (card_data.indexOf ('=') === -1 || card_data.indexOf ('^') === -1) para validar los datos de deslizamiento, lo que elimina un deslizamiento incorrecto, pero esto no es lo mismo que las comprobaciones de redundancia longitudinal que solicita auth.net: "Las verificaciones de redundancia longitudinales (LRC) deben calcularse para los datos leer de la Pista y compararla con la lectura LRC de la Pista. Se supone que los datos de la Pista se leen sin errores cuando no se detectan errores de paridad de caracteres y los LRC calculados y leídos coinciden ". -card presente guía – Iannazzi

Cuestiones relacionadas