2010-01-23 25 views
21

Có ai biết cách phân tích cú pháp đầu vào chuỗi thẻ tín dụng từ Trình quét thẻ từ không?Đầu vào thẻ tín dụng phân tích cú pháp từ Sọc từ

Tôi đã thử trình phân tích cú pháp JavaScript nhưng chưa bao giờ làm việc đó. Đây là đầu vào trông như thế nào.

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

Chữ N là số thẻ tín dụng.

+10

có thể anh ấy muốn tham gia kinh doanh thiết bị đầu cuối thẻ tín dụng? –

+1

Vợ tôi là một nhiếp ảnh gia và tôi là một nhà phát triển. Chúng tôi vừa đăng ký với PayPal Website Payments Pro và muốn có thể xử lý CC trên đường (các chương trình thương mại và điều gì đó). –

+0

Tôi đã tìm thấy một add-in GreaseMonkey cho FireFox cho phép tôi vuốt ngay tại đầu cuối ảo PayPal. Mặc dù không lý tưởng, nó sẽ thực hiện thủ thuật nếu tôi không thể hiểu được điều này. –

Trả lời

24

Xem Magnetic Stripe Card entry @ Wikipedia:


Theo dõi một, Format B:

  • Bắt đầu sentinel - một nhân vật (thường '%')
  • đang Format = "B" - một ký tự (chỉ alpha)
  • Số tài khoản chính (PAN) - tối đa 19 ký tự. Thông thường, không phải luôn khớp với số thẻ tín dụng được in ở mặt trước thẻ.
  • Dòng Separator - một nhân vật (thường '^')
  • Tên - hai đến 26 ký tự
  • Dòng Separator - một nhân vật (thường '^')
  • Ngày hết hạn - bốn nhân vật theo hình thức YYMM.
  • mã dịch vụ - ba nhân vật
  • dữ liệu tùy ý - có thể bao gồm Pin xác nhận chính Chỉ số (PVKI, 1 nhân vật), mã PIN xác nhận giá trị (PVV, 4 ký tự), Thẻ Xác Giá trị hoặc Mã xác minh thẻ (CVV hoặc CVK, 3 ký tự)
  • End sentinel - một nhân vật (nói chung)
  • redundancy check dọc (LRC) '?' - một trong những nhân vật (Hầu hết các thiết bị đọc không trở về giá trị này khi thẻ là swiped đến lớp trình bày, và chỉ sử dụng nó để kiểm tra đầu vào trong nội bộ để người đọc)

Tôi hy vọng dữ liệu là giả, nếu không Bất cứ ai cũng có thể nhận được:. Tên

  • Ngày hết hạn
  • CVV

Và tôi không chắc chắn nhưng tôi nghĩ rằng số thẻ tín dụng (hoặc số khả năng) có thể được tính bằng LRC.

+0

Nếu bạn đang viết cho đầu đọc thẻ từ, và sử dụng chế độ viết thô, thì việc tính toán thuật toán LRC có thể hơi khó hiểu mà bạn phải tự làm, nếu bạn sử dụng chế độ viết bình thường, máy vuốt sẽ xử lý điều đó cho bạn. Nhưng để đọc, máy vuốt sẽ tự động tính toán LRC để xác minh thao tác vuốt thành công. – t0mm13b

+4

Dữ liệu thẻ là giả mạo. –

+1

Cách tính toán LRC chính xác cho tuyến đường? – bmalets

2

Từ những gì tôi có thể nhớ:

Đó là hai ca khúc dữ liệu dải từ - ca khúc đầu tiên bắt đầu với % và kết thúc với ?, ca khúc thứ hai bắt đầu với ; và kết thúc với ?. Đây là các điểm đánh dấu Bắt đầu/Kết thúc.

Bài hát đầu tiên có dạng chữ và số, bài hát thứ hai là số và có bản nhạc thứ ba cũng là số (nếu bộ nhớ của tôi phục vụ đúng).

Dữ liệu giữa các điểm đánh dấu đầu/cuối có thể thay đổi tùy thuộc vào mật độ ghi của dải từ. Mật độ càng cao thì càng có thể ghi lại trên một bản nhạc.

Sử dụng regex để lấy dữ liệu có thể không phải là phương pháp đáng tin cậy để chọn thông tin bắt buộc.

Và không phải tất cả thẻ tín dụng đều có chính xác hai bản nhạc, một số sử dụng ba bản nhạc.

1

Nói chung đối với giao dịch không có thẻ (tức là giao dịch MOTO), bạn cần cC#, hết hạn và có thể là CVV (còn gọi là CVC2, v.v.). Bạn có thể có được 2 đầu tiên từ một swipe thẻ như thế này trong dữ liệu theo dõi. CVV được in trên thẻ.

Tên trên thẻ không quan trọng lắm. Trừ khi người thâu tóm của bạn và chủ thẻ đang sử dụng xác minh địa chỉ, nhưng bạn có thể thấy rằng giữa^^, nó có thể có khoảng trống màu trắng mà bạn có thể xóa.

Phần bạn muốn là track2 NNNNNNNNNNNNNNNN = 1210 trong đó NNNNN = số thẻ PAN và 1210 = Ngày hết hạn.

Ngay cả khi track1 trống (đôi khi nó không được sử dụng trong quá trình xử lý), bạn vẫn sẽ nhận được;?, Vì vậy bạn có thể sử dụng chỉ mục thứ hai; khi bắt đầu chuỗi và = là phần cuối của chuỗi cC#. Với 4 ký tự sau dấu = khi hết hạn.

Tôi khuyên bạn nên để chủ thẻ ký tên vào hồ sơ giao dịch nếu không họ có thể tranh chấp thẻ và thực hiện hoàn tiền.

Và không phải tất cả thẻ tín dụng đều có chính xác hai bản nhạc, một số sử dụng ba bản nhạc.

Chỉ track2 được sử dụng để xử lý và có định dạng chuẩn.

Thẻ ghi nợ thường không thể được xử lý (trừ khi họ có thẻ ghi nợ visa hoặc thứ gì đó).

P.S. bạn không nên lưu trữ dữ liệu cc ở dạng văn bản thuần túy, vì vậy hãy thử và giữ mọi thứ trong mã hóa mem hoặc mã hóa mạnh.

5

Tôi đã làm cho bạn một tốt hơn: Tôi đã thực hiện một đoạn video cho thấy làm thế nào để thực hiện chính xác này với ASP.Net/c#:

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

Dưới đây là phần mã mà bạn có thể quan tâm:

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

Mã đầy đủ trên trang web mà tôi đã liên kết ở trên.

1
+0

Liên kết đầu tiên là những gì tôi đang tìm kiếm ở khắp mọi nơi. Dường như có xác thực dữ liệu theo dõi và thậm chí là hết thời gian chờ. May mắn thay hoặc tiếc là nó là một đoạn mã khá ấn tượng, đó là chỉ đơn giản là vượt ra ngoài khả năng của tôi để thực hiện. Bạn có thể thêm một ví dụ về cách sử dụng chức năng CardReader không? Trong đoạn mã theo dõi của tôi, mà tôi sẽ thêm vào như một bài viết riêng biệt, tôi có một người nghe, mà tôi không thấy trong CardReader. – Iannazzi

+0

Chỉ cần đăng đầu đọc và mã trình phân tích cú pháp của tôi dưới đây ... cần tích hợp xác thực CardReader – Iannazzi

0

đây là mã của tôi:

1 người nghe để có được những dữ liệu .... này dữ liệu cần xác thực mà tôi đang tìm kiếm trợ giúp. Một swipe tốt hoạt động tốt, nhưng một swipe xấu sẽ gây ra một lỗi trong phân tích cú pháp.

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

}); 

Và đây là trình phân tích cú pháp .... lưu ý Tôi đặt tất cả trong một hàm để tôi có thể phá hủy tất cả các biến để chúng không nằm trong trình duyệt.

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

Tôi đã thêm nếu (card_data.indexOf ('=') === -1 || card_data.indexOf ('^') === -1) để xác thực dữ liệu vuốt, thao tác này sẽ loại bỏ thao tác vuốt không đúng, nhưng điều này không hoàn toàn giống với kiểm tra dự phòng theo chiều dọc mà auth.net yêu cầu: "Kiểm tra dự phòng dọc (LRC) phải được tính toán cho dữ liệu đọc từ Track và so sánh với LRC đọc từ Track. Dữ liệu Track được giả định là không đọc lỗi khi không phát hiện lỗi chẵn lẻ ký tự và kết quả LRC được tính toán và đọc. " hướng dẫn hiện tại -card – Iannazzi

Các vấn đề liên quan