CVC and AVS checks

When you process a card payment, you can add extra validation with 2 different types of checks:

  • AVS (Address Verification System): this uses the customer's name and billing address
  • CVC (Card Verification Code): this uses a number printed on the card separately from the main card number

These are described in more detail below. Note that you can use both checks together for the same payment.

AVS checks

AVS checks compare the customer's name, billing street address and ZIP or postal code with the information the bank has in its records. A successful match acts as extra evidence to the bank that the payment is legitimate. An AVS check can also result in a partial match where some of the fields match but others do not. For example, this might happen if the user types the details incorrectly or omits some of them completely. A partial match provides weaker verification than a full match but still may be acceptable to the bank.

Note that unlike CVC checks (described below), AVS checks do not require the customer to enter the check data for each payment, so you can reuse their stored billing details indefinitely. See the page about tokenizing a card to learn how to supply these details when you generate the card token.

The Card object has an avs_check field that contains its current AVS verification status as a string. The possible values are shown below. Note that these values are also shown in some Dashboard screens, such as
Vault and Transactions.

StatusDescription
pendingThe check has not completed yet
unavailableThe check could not be carried out
unknownThe status of the check was not reported by the Payment Service Provider
failedThe check failed
failed-nameThe name used for the check did not match
failed-addressThe address used for the check did not match
failed-postalThe ZIP or postal code used for the check did not match
failed-address-passed-postalThe ZIP or postal code matched but the address did not
failed-postal-passed-addressThe address matched but the ZIP or postal code did not
passedThe check passed

CVC checks

The CVC (also known by other names such as Card Verification Value and Card Security Code) is a 3 or 4 digit number that the issuing bank adds to cards to provide extra security. It is printed on the card rather than embossed like the other main details and is often located on the back of the card near the signature panel.

Entering a correct CVC during payment provides extra evidence that the customer made the payment manually. This usually increases payment performance because the bank can be more confident that the payment is legitimate. The check also helps to protect the merchant against fraudulent purchases.

You must use a secure field on the card details form to receive the CVC for a payment. See the page about tokenizing a card to learn how to do this.

The Card object has a cvc_check field that contains its current CVC verification status as a string. The possible values are shown below. Note that these values are also shown in some Dashboard screens, such as
Vault and Transactions.

StatusDescription
passedThe CVC was sent and was correct
failedThe CVC was sent but was incorrect
uncheckedThe CVC was sent but wasn't checked by the issuing bank
unavailableThe CVC wasn't sent as it either wasn't specified by the user, or the transaction is recurring and the CVC was previously deleted
requiredThe CVC wasn't available, but the card/issuer required the CVC to be provided to process the transaction
unknownSome payment providers sometimes don't have the final result of CVC checks, in which case the CVC check status will be unknown

Refreshing a CVC

PCI DSS rules require that the customer enters the CVC manually for each payment. This means that it must be deleted after a successful authentication. This is no problem when the card details are entered directly but it can create an issue if you are using a stored card token. In this case, the CVC will only be available for the first payment made from the token. Some banks might decline subsequent payments if you fail to provide a CVC for them.

You can avoid this problem by refreshing the CVC for a stored card during a payment. This involves asking the user to enter the CVC again, but it is much quicker for them to type a few digits than to type the full card details each time.

Setting up a form to refresh the CVC

The HTML form to refresh a CVC is a reduced version of the one you use to request the full card details. Most of the details are available from the stored card token, and so the form only needs to receive the CVC. See the page about tokenizing a card in the browser to learn how the card form works, especially with regards to security, styling, error handling and event handling.

The form in the sample below contains the CVC field and the Submit button but you might also want to add a hint to show the customer which card they are refreshing. For example, you could use the last_4_digits field of
the Card object when you generate the HTML on the server to show a reminder of the card number with all the other digits blanked out.

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

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

The code to set up the form is shown below. See the page about setting up your environment to learn how to include the processout.js library in your web page.

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

ProcessOut.setupFormCVC() calls the processoutReadyHandler callback function when the form is correctly set up. Use this function to set an event handler that will refresh the CVC and return the updated card token when the user submits the form.

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

    // 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";
      field.name  = "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
      formElement.submit();
    }, function(err) {
      alert(err);
    });

    return false;
  });
}

Refreshing a CVC with mobile SDKs

The code sample below shows how to refresh a CVC that you have already received from the customer using on both iOS and Android. You can use any suitable UI to collect CVC from a user.

let request = POCardUpdateRequest(
    cardId: "card_ZTHmJqWTQlzjYvIFLDZuGDIa94j4URkW", cvc: "<CVC>"
)
try await ProcessOut.shared.cards.updateCard(request: request)
// Coroutine function
ProcessOut.instance.cards.updateCVC(
    cardId = "card_ZTHmJqWTQlzjYvIFLDZuGDIa94j4URkW",
    request = POCardUpdateCVCRequest(cvc = "<CVC>")
).let { result ->
    when (result) {
        is ProcessOutResult.Success -> TODO()
        is ProcessOutResult.Failure -> TODO()
    }
}

// Callback function
ProcessOut.instance.cards.updateCVC(
    cardId = "card_ZTHmJqWTQlzjYvIFLDZuGDIa94j4URkW",
    request = POCardUpdateCVCRequest(cvc = "<CVC>"),
    callback = object : ProcessOutCallback<POCard> {
        override fun onSuccess(result: POCard) {
            TODO()
        }

        override fun onFailure(
            code: POFailure.Code,
            message: String?,
            invalidFields: List<POFailure.InvalidField>?,
            cause: Exception?
        ) {
            TODO()
        }
    }
)