Refresh your customers’ cards CVC

PCI DSS, the certification that allows platforms like ProcessOut to store card numbers in their systems, enforce the deletion of the cardholder CVC once an initial authorization is performed successfully. This means that although the first payment of your customer will contain the CVC, subsequent transactions won’t be able to make use of it. While this guarantees the security of the customer’s card information, it can prevent some transactions from properly being accepted by your users’ banks. Asking for the card’s CVC code again can help solve this issue.

Setting up

Refreshing a CVC is very similar to creating a card token ↗ using ProcessOut.js, the main difference being you’ll re-use an already existing Card token to be refreshed.

Let’s first set up the form that’ll be used to collect the CVC code. Similarly to payment fields, the CVC field isn’t an actual input box, but only a div. To ensure PCI-compliancy, ProcessOut hosts the credit card fields on its servers so no critical data ever touches your server and no XSS impacts your customer’s security.

<form action="/your-cvc-refresh-endpoint" method="POST" id="payment-form">
  <div data-processout-input="cc-cvc"

  <input type="submit" class="submit" value="Refresh CVC">

For the payment form to be interactable, you will need to load ProcessOut.js. It is important to always load it from our CDN like shown below. Please note that ProcessOut.js has no dependency, meaning it can work without jQuery.

<script src=""></script>

Now that ProcessOut.js is loaded, we can start using it. Let’s first instanciate a new ProcessOut instance in a different script tag as soon as the DOM is fully loaded, and setup our form:

<script type="text/javascript">
  document.addEventListener("DOMContentLoaded", function() {
    var client = new ProcessOut.ProcessOut("proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x");
    var formElement = document.getElementById("payment-form");
    client.setupFormCVC(formElement, processoutReadyHandler, function(err) {
      console.log("Woops, couldn't setup the form: "+err);

Note: Remember to replace the project ID in the example with your own. When testing, prepend your project ID with test- like so: test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x.

We also still have to add the handler, which we’ll do next.

Bind the form and refresh the CVC

As soon as the form is fully loaded, setupForm will call processoutReadyHandler with the created CardForm object. We’ll use this object to handle the tokenization transparently.

Let’s bind the form submission and tokenize the card:

function processoutReadyHandler(form) {
  // The form is now fully loaded!
  formElement.addEventListener("submit", function(e) {
    // Cancel any default action

    // Let's tokenize the card
    client.refreshCVC("card_ZTHmJqWTQlzjYvIFLDZuGDIa94j4URkW", form, function(token) {
      // We now have the tokenized card token, let's send it back
      // to the server
      var field   = document.createElement("input");
      field.type  = "hidden";  = "token";
      field.value = token;

      // We add the token input so that it's sent back to  the server.
      // The only thing left to do is to submit the form
    }, function(err) {

    return false;

Customize the field and events

Because the way the hosted CVC field works the same as the ones used to tokenize a card, you can use the same tricks to customize the field as you like. Learn more about it here ↗

What’s next?

We’ve sent the card token back to our server. Let’s use it to capture a payment ↗ or to create a subscription ↗.