Analyser L'entrée de carte de crédit à partir de la bande magnétique

Est-ce que quelqu'un sait comment analyser une entrée de chaîne de carte de crédit à partir d'un tireur de carte magnétique?

J'ai essayé un analyseur JavaScript mais je ne l'ai jamais fait fonctionner. C'est ce que l'entrée ressemble.

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

Les N sont le numéro de carte de crédit.

21
demandé sur Chase Florell 2010-01-23 05:55:14

6 réponses

Voir l'entrée de la carte à bande magnétique @ Wikipedia:


Première piste, Format B:

  • Démarrer sentinel - un caractère (généralement"%")
  • Format code = " B " - Un caractère (alpha seulement)
  • Numéro de compte principal (PAN) - jusqu'à 19 caractères. Habituellement, mais pas toujours, correspond au numéro de carte de crédit imprimée sur la face avant de la carte.
  • séparateur de champ - un caractère (généralement'^')
  • Nom-deux à 26 caractères
  • séparateur de champ - un caractère (généralement'^')
  • Date D'Expiration-quatre caractères sous la forme YYMM.
  • code de Service - trois caractères
  • données discrétionnaires-peut inclure L'indicateur de clé de vérification NIP (PVKI, 1 caractère), valeur de vérification de PIN (PVV, 4 caractères), vérification de la carte Code de vérification de la valeur ou de la carte (CVV ou CVK, 3 caractères)
  • end sentinel - un caractère (généralement '?')
  • contrôle de redondance longitudinale (LRC) - un caractère (la plupart des lecteurs ne pas retourner cette valeur lorsque la carte est glissé vers la couche de présentation, et l'utiliser uniquement pour vérifier l'entrée à l'interne pour le lecteur.)

j'espère que les données sont fausses, sinon n'importe qui pourrait obtenir le:

  • Nom
  • Date D'Expiration
  • CVV

et je ne suis pas sûr mais je pense que le numéro de carte de crédit (ou nombre de possibilités) peut être calculé en utilisant le LRC.

24
répondu Alix Axel 2010-01-23 03:14:21

Je vous ai fait mieux: j'ai fait une vidéo montrant comment faire exactement cela avec ASP.Net/c#:

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

Voici la section du code qui vous intéresse probablement:

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

Le code complet est sur ce site que j'ai lié ci-dessus.

6
répondu Mark Hagan 2011-12-09 16:32:13

D'après ce dont je me souviens:

C'est une bande magnétique de données à deux pistes-la première piste commence par % et se termine par ?, la deuxième piste commence par ; et se termine par ?. Ce sont de Début/Fin de marqueurs.

La première piste est alphanumérique, la deuxième piste est numérique, et il y a une troisième piste qui est également numérique (si ma mémoire est correcte).

Les données entre les marqueurs de début/fin peuvent être variables en fonction de la densité d'enregistrement de la bande magnétique. Plus la densité est élevée, plus elle peut être enregistrée sur une piste.

Aide d'une expression régulière pour obtenir les données peuvent ne pas être une méthode fiable pour choisir les informations requises.

Et toutes les cartes de crédit ont exactement deux pistes, certains utilise trois pistes.

2
répondu t0mm13b 2017-01-13 18:15:10

Généralement pour une transaction sans carte (c'est-à-dire les transactions MOTO), vous aurez besoin de cc#, d'expiration et éventuellement du CVV (alias CVC2, etc.). Vous pouvez obtenir le premier 2 à partir d'une carte-glisser comme cela dans les données de piste. CVV est imprimé sur la carte.

Nom sur la carte n'a pas tellement d'importance. Sauf si votre acquéreur et le titulaire de la carte utilisent la vérification de l'adresse, mais vous pouvez constater qu'entre ^^, il peut y avoir un remplissage d'espace blanc que vous pouvez supprimer.

La partie que vous voulez est track2 NNNNNNNNNNNNNNNNN=1210 où NNNNN = PAN numéro de carte, et 1210 = date d'expiration.

Même si track1 est vide (ce qui est parfois le cas car il n'est pas utilisé dans le traitement), vous obtiendrez toujours le ;?, vous pouvez donc utiliser l'index de la seconde ; comme début de la chaîne et = comme fin de la chaîne cc#. Avec les 4 caractères après le = comme expiration.

Je conseillerais au titulaire de la carte de signer quelque chose dans le dossier de la transaction sinon ils pourraient contester la carte et faire un frais de retour.

Et toutes les cartes de crédit n'ont pas exactement deux pistes, certaines utilisent trois pistes.

Seul track2 est utilisé pour le traitement et a un format standardisé.

Les cartes de débit ne peuvent généralement pas être traitées (sauf si elles ont une carte de débit visa ou autre).

P.S. vous ne devriez pas stocker les données cc en texte brut, alors essayez de tout garder en mem ou en cryptage fort.

1
répondu Kakkerlakkie 2010-06-02 05:05:29

Voici mon code:

1er l'écouteur pour obtenir les données.... ces données ont besoin de validation sur laquelle je cherche de l'aide. Un bon balayage fonctionne bien, mais un mauvais balayage provoquera une erreur dans l'analyseur.

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

});

Et voici l'analyseur.... note je mets tout cela dans une fonction afin que je puisse détruire toutes les variables afin qu'elles ne s'attardent pas dans un navigateur.

    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
répondu Iannazzi 2014-12-24 02:20:45