Spreedly iFrame Payment Form

There are a variety of ways to send payment data to Spreedly. If you wish to implement a custom checkout experience while still limiting your PCI compliance, the recommended approach is to use the iFrame payment form. Although it is a lower level library than Express, it allows almost unlimited UX customization and behavior while still storing card data in your Spreedly vault without it ever touching your server environment.

If you are looking for specific commands or options, please see the iFrame Javascript API reference

iFrame overview

Spreedly’s iFrame payment form is a Javscript library that provides two, Spreedly-managed, fields for collecting the credit card number and CVV (the two PCI-sensitive fields of a payment method). Your host page places and styles these two fields within the checkout form, and the iFrame returns a tokenized payment method to the host page when the payment method has been successfully submitted. While an invalid PAN will prevent the iFrame from returning a payment method token, an invalid CVV will not. The CVV iFrame field may be hidden if you do not require the CVV to process payments through your gateway.

The following shows a rendered checkout page using the Spreedly iFrame to serve the number and CVV fields. The only parts contained within Spreedly-served iFrames are the individual number and CVV input fields. All the labels and other fields are part of the host checkout page.

Before You Begin

You will need your environment key and access secret from id.spreedly.com, as well as your gateway token. Since invalid card numbers will fail silently until error handling is implemented, you may also find it helpful to have valid test card numbers at hand for easy reference. A more complete example of a payment page that uses iFrame can be found in the Sample Payment Frame.

Adding iFrame to your checkout page

To add iFrame to your checkout page, include the Javascript library in your host page:

<head>
  <script src="https://core.spreedly.com/iframe/iframe-v1.min.js"></script>
</head>

Then copy the following checkout form into the checkout page:

<form id="payment-form"
  action="https://yoursite.com/checkout"
  onsubmit='submitPaymentForm(); return false;'>

  <input type="hidden"  name="payment_method_token" id="payment_method_token">

  <label for="full_name">Name</label>
  <input type="text" id="full_name" name="full_name"><br/>

  <label>Credit Card Number</label>
  <div id="spreedly-number" style="width:225px; height:35px; border: 2px solid"></div><br/>

  <label for="spreedly-exp-month">Expiration Date</label>
  <input type="text" id="month" name="month" maxlength="2">
  <input type="text" id="year" name="year" maxlength="4"><br/>

  <label>CVV</label>
  <div id="spreedly-cvv" style="width:60px; height:35px; border: 2px solid "></div><br/>

  <input id="submit-button" type="submit" value="Pay Now" disabled>

</form>

This will create a very simple (and unstyled) payment form. However, the payment form will not yet contain the number or CVV fields nor will it be functional. It must first be configured before it can successfully tokenize your customers’ payment methods.

Configuration

Once the host form is on the page, the iFrame is initialized with the Spreedly Javascript module. Pass in the Spreedly environment key where your customers’ payment methods should be stored along with the id of the form HTML elements where the two card fields are to be placed.

In this example, payment methods will be tokenized in the C7cRfNJGODKh4Iu5Ox3PToKjniY Spreedly environment and the number and CVV form fields will render within the spreedly-number and spreedly-cvv elements, respectively. Here, spreedly-number and spreedly-cvv are the CSS ID selectors of the two divs from the above form.

Place the below snippet in a new script tag on the bottom of the checkout page:

Spreedly.init("C7cRfNJGODKh4Iu5Ox3PToKjniY", {
  "numberEl": "spreedly-number",
  "cvvEl": "spreedly-cvv"
});

Ready

The ‘Pay Now’ button is initially disabled to prevent submission of the form before the iFrames have finished loading. A 'ready’ event is triggered when the iFrames have been successfully initialized. Create a listener for this event to toggle the 'Pay Now’ button to an enabled state.

Spreedly.on("ready", function () {
  var submitButton = document.getElementById('submit-button');
  submitButton.disabled = false;
};

Reload your checkout page to see the number and CVV fields rendered in your form. Once the fields are rendered, you need to tell iFrame when to tokenize a customer’s card data.

Tokenize payment method

iFrame doesn’t automatically hook into any form events. Instead, you must explicitly tell it when you want to send the collected card data to Spreedly for tokenization.

The most straight-forward approach is to create a form onSubmit handler that sets the required fields for a payment method (name and expiration date, in addition to the number and CVV fields which are handled for you) and delegates to Spreedly.tokenizeCreditCard.

Implement a top-level function submitPaymentForm that gets the values from the name and expiration date fields, passes them to the iFrame, and requests tokenization. Note that this function and all other JavaScript functions should be placed in a script tag on the checkout page.

Place the below snippet in the previously created script tag, below the call to Spreedly.init:

function submitPaymentForm() {

  var requiredFields = {};

  // Get required, non-sensitive, values from host page
  requiredFields["full_name"] = document.getElementById("full_name").value;
  requiredFields["month"] = document.getElementById("month").value;
  requiredFields["year"] = document.getElementById("year").value;

  Spreedly.tokenizeCreditCard(requiredFields);
}

When the form’s submit button is clicked, the required values from the host page will be sent to the iFrame and subsequently submitted to Spreedly for tokenization in your Spreedly environment. If the card is successfully tokenized, the token will be sent back to the host page via an event, which you must send back to your backend environment for processsing.

Error handling

If a card is not successfully tokenized, an error event is generated. This sample will log errors to your browser’s Javascript console; you may wish to selectively surface some errors to the user.

Spreedly.on('errors', function(errors) {
  for (var i=0; i < errors.length; i++) {
    var error = errors[i];
    console.log(error);
  };
});

See Spreedly’s response codes documentation for more information. In particular, note that the 422 error code is returned both for requests with inadequate data (such as a missing name or CVV) and for declined cards.

Receiving the tokenized payment method

When a card has been tokenized by Spreedly, an event is fired that includes the generated payment method token as well as the details of the payment method record. It is up to you to receive the token and send it to your backend environment.

This example shows how to register for the onPaymentMethod event, and add the payment method token to the host form which is then submitted to your backend:

Spreedly.on('paymentMethod', function(token, pmData) {

  // Set the token in the hidden form field
  var tokenField = document.getElementById("payment_method_token");
  tokenField.setAttribute("value", token);

  // Submit the form
  var masterForm = document.getElementById('payment-form');
  masterForm.submit();
});

While this exmple shows how to submit the payment method token via a form submission, you could just as easily send the token back via AJAX.

At this point you should have a working payment form that tokenizes the payment method at Spreedly and sends the token to your backend environment. Spreedly has tokenized the payment method, but has not processed a transaction.

Executing the transaction

After the iFrame tokenizes your customer’s payment method and submits the checkout form, it is up to you to execute the actual transaction from your backend server environment. This is necessary because the browser is not a secure environment and should never contain your Spreedly access secret (which is required to invoke the transactional portion of the Spreedly API).

When the checkout form is submitted, extract the payment_method_token parameter and use it to execute a purchase (or auth) against the appropriate gateway using the direct API:

$ curl https://core.spreedly.com/v1/gateways/LlkjmEk0xNkcWrNixXa1fvNoTP4/purchase.json \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/json' \
  -d '{
        "transaction": {
          "payment_method_token": "56wyNnSmuA6CWYP7w0MiYCVIbW6",
          "amount": 100,
          "currency_code": "USD",
          "retain_on_success": true
        }
      }'

$ curl https://core.spreedly.com/v1/gateways/LlkjmEk0xNkcWrNixXa1fvNoTP4/purchase.xml \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/xml' \
  -d '<transaction>
        <payment_method_token>56wyNnSmuA6CWYP7w0MiYCVIbW6</payment_method_token>
        <amount>100</amount>
        <currency_code>USD</currency_code>
        <retain_on_success>true</retain_on_success>
      </transaction>'

You can review the Spreedly API reference docs for details of the direct API, including the authentication, purchase and authorize calls.

Securing iFrame

In order to achieve the highest levels of PCI-DSS v3 compliance with the iFrame, you need to disable the creation of payment methods via the direct API. After confirming you are not using the XML, JSON, JSONP, CORs or transparent direct methods of adding a payment method, enable the “Spreedly iFrame or Express Only option in the Environment Settings page of your environment.

This prevents direct API submission of payment methods which is required to detect malicious attacks and, in general, enforce adherence to the PCI standard. The only way payment methods can be added to this Spreedly environment will be through the iFrame (or Express) payment forms.

Customizing the iFrame

The form and flow you have in place now should be functional, but is rudimentary and unstyled. Next, learn how to customize the iFrame using the iFrame Javascript API reference, which includes the following topics:

Recache existing payment method

Due to PCI compliance requirements, Spreedly is unable to store a card’s CVV past the original transaction. If you have an existing payment method already tokenized in your Spreedly environment, you can have the customer update the CVV for a new transaction without having to re-enter the rest of their card details.

Simply set iFrame to operate in recache mode and handle the recache event:

Spreedly.on('ready', function(){
 Spreedly.setRecache("56wyNnSmuA6CWYP7w0MiYCVIbW6" , {
   'card_type': 'visa',
   'last_four_digits': '1234'
 });
});

// Invoke Spreedly.recache() to recache CVV. On success,
// the "recache" event will be triggered.
Spreedly.on("recache", function(token, paymentMethod) {

  // Send ping back to server for post-recache transaction processing
  var masterForm = document.getElementById('payment-form');
  masterForm.submit();
});

Find more information about recache in the iFrame reference docs.

Skipping name and expiration date validation

By default Spreedly validates the presence of a name and expiration date associated with a credit card. However, in some cases you may want to skip this validation if this is not metadata you are interested in collecting. If you’d like to skip either or both of these validations you can set the following parameters to true.

Spreedly.on('ready', function(){
  Spreedly.setParam('allow_blank_name', true
  Spreedly.setParam('allow_expired_date', true)
});

Examples

A more complete example of a payment page that uses iFrame can be found in the Sample Payment Frame.

Browser compatibility

Spreedly iFrame is compatible with the following browser versions:

  • Internet Explorer 10.0 and above
  • Google Chrome 30 and above
  • Firefox 30 and above
  • Safari 6 and above
  • iOS Safari 3.2 and above

Versioning

Spreedly iFrame is versioned by major numerical, e.g., v1. Backwards-incompatible new features will cause the major version number to increment and will only be deployed if you update the script reference on your checkout page (meaning you choose when to accept major upgrades).

Any critical bug fixes or security updates will be automatically and deployed as the current version number, making no action required by you to be running on a secure, stable version. For this reason, please do not store a copy of the javsacript library on your servers, always reference the version hosted on spreedly.com.

Previous versions

Documentation for previous versions of the iFrame can be found here. Please note, these versions are deprecated, upgrade as soon as possible.