Managing credit card details within the Rails framework

Is it possible to validate credit card information on the client side without transmitting any data to the server for PCI compliance?

The API I am using responds with a token after I send them the credit card information, which is the only data I need to store in my database. However, currently, the information is being passed through my server as seen in the server log:

Started POST "/api_checkout" for 127.0.0.1 at 2014-08-04 21:53:02 -0300
Processing by Marketplace::CheckoutController#api_buy as JS
Parameters: {"utf8"=>"✓", "number"=>"4111 1111 1111 1111", "verification_value"=>"123", "full_name"=>"Test user", "expiration"=>"14/15", "token"=>"B5E7A1F1-9822-4433-9FEE-30B625B8B070"}
Rendered marketplace/checkout/api_buy.js.erb (0.4ms)
Completed 200 OK in 43ms (Views: 39.2ms | ActiveRecord: 0.0ms | Solr: 0.0ms)


Started POST "/api_checkout" for 127.0.0.1 at 2014-08-04 21:53:03 -0300
Processing by Marketplace::CheckoutController#api_buy as HTML
Parameters: {"utf8"=>"✓", "number"=>"4111 1111 1111 1111", "verification_value"=>"123", "full_name"=>"Test user", "expiration"=>"14/15", "token"=>"B5E7A1F1-9822-4433-9FEE-30B625B8B070"}
Completed 500 Internal Server Error in 21ms 

Despite having methods to validate credit cards via JavaScript and make an API call on the client side, I want to eliminate the need to pass the information through my server. Here is what my current setup consists of:

Here is the form structure:

<%= form_tag api_buy_path,:method => :post, :id => 'payment-form', :remote => true do %>
    <div class="usable-creditcard-form">
      <div class="wrapper">
        <div class="input-group nmb_a">
          <div class="icon ccic-brand"></div>
          <%= text_field_tag :number, params[:number], :class=>"credit_card_number",  :"data-api"=>"number" %>
        </div>
        <div class="input-group nmb_b">
           <div class="icon ccic-cvv"></div>
           <%= text_field_tag :verification_value, params[:verification_value], :class=>"credit_card_cvv",  :"data-api"=>"verification_value" %>
        </div>
        <div class="input-group nmb_c">
          <div class="icon ccic-name"></div>
          <%= text_field_tag :full_name, params[:full_name], :class=>"credit_card_name",  :"data-api"=>"full_name" %>
        </div>
        <div class="input-group nmb_d">
          <div class="icon ccic-exp"></div>
          <%= text_field_tag :expiration, params[:expiration], :class=>"credit_card_expiration",  :"data-api"=>"expiration" %>
        </div>
      </div>
    </div>
    <div class="token-area">
      <%= label_tag :token, "Card token:"%>
      <%= text_field_tag :token, params[:token],:id=>"token", :readonly=> true, :value=>""%>
     </div>
<%= submit_tag 'Submit' %>
<% end %>

And here is the JavaScript implementation:

SomeAPI.setAccountID("some-id");
SomeAPI.setTestMode(true);
jQuery(function($) {
$('#payment-form').submit(function(evt) {    
    var form = $(this);
    var cardNumber = document.getElementById("number").value;
    //Check if the number is valid
    if(SomeAPI.utils.validateCreditCardNumber(cardNumber)){
       var brand = SomeAPI.utils.getBrandByCreditCardNumber(cardNumber);
       var cvv = document.getElementById("verification_value").value;
       //Validate CVV based on the brand
       if(SomeAPI.utils.validateCVV(cvv, brand)){
         var expiration = document.getElementById("expiration").value.split("/");
         var expiration_year = expiration[1];
         var expiration_month = expiration[0];
         //Validate the expiration date
         if(SomeAPI.utils.validateExpiration(expiration_month, expiration_year)){
           var name = document.getElementById("full_name").value.split(" ");     
           var firstName = name[0];
           var lastName = name[name.length - 1];
           //Perform all checks
           cc = SomeAPI.CreditCard(cardNumber, expiration_month, expiration_year, firstName, lastName, cvv);
           var tokenResponseHandler = function(data) {       
           if (data.errors) {
              alert("Error: " + JSON.stringify(data.errors));
             } 
             else {
               $("#token").val( data.id );
               form.get(0).submit();
            }
            form.trigger("submit.rails");
          }
          SomeAPI.createPaymentToken(cc, tokenResponseHandler);
          return true;
        }else{
          alert("Invalid")
          return false;
        }
      }else{
        alert("Invalid")
        return false;
      }
    }else{
      alert("Invalid")
      return false
    }
  });
});

Answer №1

The issue at hand is the necessity of clearing out sensitive form data before triggering the form submission:

  $("#token").val( data.id );
  form.get(0).submit();

In order for the form to validate, it requires access to sensitive credit card information, even though your Rails application only requires the token.

As a practice, I often replace the actual card number with a string that includes only the last four digits, like: ** ** **** 1234

If your SomeAPI does not already provide a masked CC, you may need to handle this using Javascript.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Contrasting .queue() with jquery.queue()

Can someone clarify the distinction between .queue() with .dequeue() and $.queue() OR jquery.queue()? If they serve the same purpose, why did jQuery provide them in two separate documentations? Could someone provide examples to illustrate their difference ...

Unable to substitute 'npm run build' for 'webpack' command

I'm having trouble with npm run build not calling webpack as expected. I've modified the script in my package.json file, but it didn't work. I'm using Linux. Here is a snippet from my package.json file: { "name": "learn-webpack", ...

Prevent inheriting styles with jQuery Else / If conditions

I'm seeking advice on how to prevent elements from retaining the same inline styles in different breakpoints. My goal is to adjust styling based on window width, similar to CSS media queries, but with the additional need to increment a numeric value ...

In a peculiar occurrence, the behavior of array.splice is exhibiting unusual characteristics within an

Be sure to take a look at this plunkr for reference: http://plnkr.co/edit/FQ7m6HPGRrJ80bYpH8JB?p=preview I'm encountering an issue where, after adding an element and then deleting it from the array using the splice method, everything becomes disorg ...

Tips for universally updating the FormData TypeScript interface within React Native applications

While attempting a simple append with FormData in React Native like the following... const formData = new FormData(); formData.append('image-data', { uri: '/awesome-chat-app/ImagePicker/abb9-a435046e971c.jpg', name: 'image001. ...

Create a shader in ThreeJS without the need to include a Geometry in the scene

Currently, I am experimenting with drawing shapes or geometric figures in ThreeJS r128 using only shaders. The traditional approach in this library involves creating a mesh with a geometry associated with it, and then applying a shader using the ShaderMat ...

Issue encountered while using JSONP: {"readyState":4,"status":200,"statusText":"load"}

After sending a command to an external server through the URL, the HTML code shows {"readyState":4,"status":200,"statusText":"load"}, but in the console, the correct data is displayed as shown in the image. Need any assistance? https://i.sstatic.net/MQ ...

Implementing dynamic props in Vue2 component by passing arbitrary named variables

Having recently delved into Vue, I am facing a challenge that has left me scratching my head after consulting the documentation: I am struggling to pass an arbitrarily named variable as a prop to a component instance. As per my understanding, props serve ...

What is the process for transforming an asynchronous method into a synchronous version?

I am currently working on creating a functionality similar to the core fs module's methods, where there is an Async method by default and a Sync method if requested like fs.readDir() and fs.readDirSync(). In my case, I have a method named fetchUrls w ...

Retrieving attribute values when using the .on function in jQuery

I currently have 10 links with the following format: <a href="#" data-test="test" class="testclass"></a> as well as a function that looks like this: $(document).on("click", ".testclass", function () { alert($(this).attr('data-t ...

Having trouble retrieving the value from the $scope variable

Includes application module app.js var appProfileDetails = angular.module('profileDetailsApp', [ 'ngMaterial','ngAria','ngAnimate','ngRoute']); This module conta ...

Issue with integrating the jquery tokeniput plugin in asp.net mvc 3

Having trouble integrating the jQuery Tokeninput plugin into my MVC application. Something seems off with the setup... The Code I'm Using: <input type="text" id="MajorsIds" name="MajorsIds" /> <script type="text/jav ...

This particular JavaScript function is only designed to operate on the initial input box in the provided

I have a question regarding echoing rows of $data inside input boxes. I am using a JavaScript function that is supposed to copy the input value to the clipboard when the input box is clicked. However, I am encountering an issue - the function only works ...

javascript guide to dynamically update the glyphicon based on value changes

I am attempting to implement an optimal level feature where a glyphicon arrow-up will be displayed if a value falls within the optimum range, and it will switch to a glyphicon arrow-down if the value is lower. <div class="card-body" ng-repeat="item i ...

Is your Javascript color changer only changing the color on the second click?

My current challenge involves making my navbar highlight the active tab. The JavaScript I've written isn't functioning as expected - it only works on the second click, and even then, only if you double click. function changeNavColor(id){ var ...

Question about React.js: What is the best way to add multiple classes to a component by using a ternary operator?

I am looking to apply multiple classes to a component by utilizing a ternary operator. In our shared ts theme file, we have the general button styles defined, but for this specific component, I want to adjust the sizes based on screen width. To achieve thi ...

Navigating - Utilizing dot-notation to reach the top-level function in Express

If we want to use express in a basic javascript file, all we need to do is add the following two lines of code at the beginning (after installing it through npm): var foo = require('express'); var app = foo(); According to the express API guide ...

Discovering techniques to access nested objects in JavaScript

My initial object state looks like this: answersCount: { Colors: { Green: 0, Brown: 0, Blue: 0, Red: 0 }, Letters: { A: 0, B: 0, C: 0, D: 0, }, Briggs: { EI: 0, SN: 0, T ...

Removing an item from an ng-repeat loop while also dealing with a FormController within

I am encountering a significant issue with form inputs nested within the ng-repeat directive. I require an input that is an array and can vary in size; allowing users to add or remove parts of the form. Within the ng-repeat directive, there is an ng-form ...

Photo uploading in ASP.NET MVC - encountering null HttpPostedFileBase issue

QUESTION: I'm having an issue where the Photo1 value is null in the controller post method despite uploading it. Can someone help with this? This is my model class: class ProductVM{ public string Name { get; set;} public string Color {get; ...