• Content

Customize Your Checkout Process and Accept Payments Securely

Securely accept sensitive payment details within your checkout process with a fully customizable user experience. The Recurly.js JavaScript library secures your checkout forms. Create subscriptions, process one-time transactions, and update customer billing information worry-free.

PCI Compliance through Hosted Fields

Recurly provides transparent iframes that allow you to deliver a customized customer checkout experience, while ensuring you meet the latest PCI DSS SAQ A compliance requirements.


How It Works

When a customer submits your payment form, Recurly.js sends customer payment information to be encrypted and stored at Recurly and gives you an authorization key to complete the subscription process using our API.

With this authorization key (or token), you can do anything with our API that requires payment information. Because you never handle any sensitive payment information, your PCI scope is drastically reduced.


Getting Started

To begin, you’ll include the Recurly.js script on your page.

<script src="https://js.recurly.com/v4/recurly.js"></script>
<link href="https://js.recurly.com/v4/recurly.css" rel="stylesheet" type="text/css">

This exposes a single global object, recurly.

It is not necessary to include recurly.css, but we highly recommend it while you’re getting set up. It provides some helpful default styles to Recurly payment fields.

Self-Hosting Recurly.js

The Recurly-hosted version of recurly.js is designed and updated to maintain compatibility with system update deployments that take place from time-to-time. Locally hosted versions of recurly.js run the risk of encountering issues with system interaction and incompatibility which may result in avoidable service interruptions on your client page. It is for this reason, we highly recommend against and do not support locally hosted copies of recurly.js.

Framework Support

Due to the necessity of gathering customer payment data within iframe elements, and the nature of reactive framework re-rendering requirements, Recurly does not at this time provide native support for reactive frameworks like React and Angular.

Configure

Simply call recurly.configure anywhere on your page, passing your public key. This identifies your site to Recurly servers. You can find your public key in the API Access section of your admin app.

recurly.configure('sc-ABCDEFGHI123456789');

Use Your Site’s Public Key

Be sure to replace sc-ABCDEFGHI123456789 with your own public key.

recurly.configure accepts other options not detailed here. You may refer to the source for more detail.

Build a card form

Build a form however you like. Use the data-recurly attribute to identify input field targets to Recurly.js. For this, we recommend using simple div elements.

There are two ways to display card fields to your customers: a combined card field, and individual card fields.

Combined card field

This is the simplest and most streamlined way to accept customer card date. Recurly will inject a single field that will accept all card data. This field is responsive to various device widths and includes helpful UX enhancements to make card entry as smooth as possible.

<form id="recurly-js-sample-combined-card-form">
  <div data-recurly="card"></div>
</form>
<form>
  <input type="text" data-recurly="first_name">
  <input type="text" data-recurly="last_name">
  <div data-recurly="card"></div>
  <input type="hidden" name="recurly-token" data-recurly="token">
  <button>submit</button>
</form>

Individual card fields

If you would like to display card fields separately from each other. This is helpful when the combined field does not fit your design needs.

<form>
  <input type="text" data-recurly="first_name">
  <input type="text" data-recurly="last_name">
  <div data-recurly="number"></div>
  <div data-recurly="month"></div>
  <div data-recurly="year"></div>
  <div data-recurly="cvv"></div>
  <input type="hidden" name="recurly-token" data-recurly="token">
  <button>submit</button>
</form>

To collect card payment information from your customers, you’ll create a form similar to this one. Recurly.js uses the data-recurly attributes on the input tags to gather customer information before sending it to our servers.

In order for recurly.js to inject the card payment hosted fields into your form, the target elements must be present in the document at the time you make the recurly.configure call.

Note that card data is not present in the form but merely given a placeholder element. This is because Recurly.js must inject those fields onto the page within iframes to ensure strict security of customer card data.

This particular form contains the minimum required input fields, and the table below documents all possible input fields.

Card fields

Field Name Example Description
card 4111-1111-1111-1111 08/22 123 Combined card field. Required if using the combined card field
number 4111-1111-1111-1111 Credit card number. Required if using individual card fields
month 8 or 08 Card expiration month as a number. Required if using individual card fields
year 22 or 2022 Card expiration year as a number. Required if using individual card fields
first_name Ben Cardholder first name. Required
last_name du Monde Cardholder last name. Required
cvv 123 Card security code

Depending on how you’ve configured your billing address requirements, some of the following fields may be required.

Billing address fields

Field Name Example Description
address1 1313 Main St. First line of a street address.
address2 Unit 1 Second line of a street address.
city Hope Town or locality.
state WA Province or region.
postal_code 98552 Postal code.
country US ISO 3166-1 alpha-2 country code.
phone 555-867-5309 Phone number.
vat_number SE0000 Customer VAT number. Used for VAT exclusion

Styling Card Fields

Style Configuration

Since card fields must be injected within iframes, any style properties within those iframes must be passed to recurly.configure. See the code example at right.

Styling the combined card field

Options unique to the combined card field are detailed in the following table. When passed into your recurly.configure call, each property must be nested within fields.card.

Combined card field properties

Property Default Description
displayIcon true If false, the card brand icon will be hidden
inputType 'text' Modifies the input type of the card field: text - text input for all fields. mobileSelect - if the user is using a mobile device, a native expiry select interface will appear when entering the expiration date. select - Expiration date will be input using a select field on all devices. Mobile devices will display an optimized interface.
selector   Specify a custom target selector (e.g. '#recurly-card')
style {} See common field style properties section below.
style.fontColor '#545457' Font color for each input element
style.fontFamily 'Source Sans Pro' font-family for each input element
style.fontSize '16px' font-size for each input element
style.placeholder {} Object
style.placeholder.color '#a3a3a7' Font color applied to all placeholder text
style.placeholder.content {} Object
style.placeholder.content.number 'Card number' Placeholder content for the number input.
style.placeholder.content.expiry 'MM / YY' Placeholder content for the expiry input.
style.placeholder.content.cvv 'CVV' Placeholder content for the card verification value input.
style.invalid {} Object. Style to apply to input elements when they contain an invalid value. See common field style properties section below.
style.invalid.fontColor '#a3a3a7' Font color applied to invalid input elements.
tabIndex   tabindex property to be applied to the outer iframe.

Styling the individual card Fields

Options unique to the individual card fields are detailed in the following table. When passed into your recurly.configure call, each property must be nested within fields.all or a respective fields.number, fields.month, fields.year, or fields.cvv object.

Individual card field properties

Property Default Description
format true Enables contextual input formatting, injecting spaces to match the card brand, and forcing numeric input on expiry and cvv.
inputType text Modifies the input type of the expiry fields. 'text' - normal text input. 'mobileSelect' - if the user is using a mobile device, a native select interface will appear. 'select' - A select field will display on all devices
selector   Specify a custom target selector (e.g. '#recurly-number')
style {} See common field style properties section below.
style.padding   padding
style.placeholder.color   Font color applied to the placeholder text.
style.placeholder.content '' Placeholder content (e.g. 'Card number', 'CVV')
tabIndex   tabIndex property to be applied to the outer iframe.

Common field style properties

Property Default Reference
style.fontColor 'black' color
style.fontFamily 'source sans pro' font-family
style.fontFeatureSettings 'normal' font-feature-settings
style.fontKerning 'auto' font-kerning
style.fontSize 'normal' font-size
style.fontSmoothing 'normal' font-smoothing
style.fontStretch '100%' font-stretch
style.fontStyle 'normal' font-style
style.fontVariant 'normal' font-variant
style.fontWeight 400 font-weight
style.letterSpacing 'normal' letter-spacing
style.lineHeight 'normal' line-height
style.textAlign 'start' text-align
style.textDecoration 'none solid rgb(84, 84, 87)' text-decoration
style.textRendering 'auto' text-rendering
style.textShadow 'none' text-shadow
style.textTransform 'none' text-transform

Example Style Configuration

recurly.configure({
  publicKey: 'my-public-key',
  fields: {
    // affects all fields
    all: {
      style: {
        fontFamily: 'Helvetica, sans-serif'
      }
    },

    // affects the combined card field
    card: {
      displayIcon: true,
      style: {
        fontSize: '1em',
        placeholder: {
          color: 'gray !important',
          fontWeight: 'bold',
          content: {
            number: 'Card number',
            cvv: 'CVC'
          }
        },
        invalid: {
          fontColor: 'red'
        }
      }
    },

    // affects individual card field types
    number: {
      // Custom target selector
      selector: '#recurly-number',
      // Format the card number
      format: true
    },
    month: {
      // Display a month select on mobile devices
      inputType: 'mobileSelect',
      style: {
        placeholder: {
          content: 'MM'
        }
      }
    },
    year: {
      style: {
        placeholder: {
          content: 'YYYY'
        }
      }
    },
    cvv: {}
  }
});

CSS Classes

Since Recurly.js must inject card data fields into iframes, the default browser appearance for those fields will likely not match the appearance of the other fields in your payment form. We provide the following CSS classes to achieve a look and feel similar to your form. Using these classes, you may specify field size, colors, and a full range of appearance customization to make the injected card fields blend into your payment form.

Class Name Description
recurly-hosted-field Default styles for the div surrounding each field iframe.
recurly-hosted-field-focus Applied when the user focuses on a field.
recurly-hosted-field-card Default styles for the div surrounding the combined card field iframe.
recurly-hosted-field-number Default styles for the div surrounding the number field iframe.
recurly-hosted-field-month Default styles for the div surrounding the month field iframe.
recurly-hosted-field-year Default styles for the div surrounding the year field iframe.
recurly-hosted-field-cvv Default styles for the div surrounding the cvv field iframe.

Custom Fonts

You may specify font and placeholder text for card fields through recurly.configure. The example call above demonstrates all available style attributes you may send to recurly.configure.

Custom fonts are sourced from Google Web Fonts. Simply use the name of the font as it appears on the Google Web Fonts site.

Responsive Styles

All of the built in field classes will support and respond to media queries. You may call recurly.configure again to change style properties within each field – thus you may change any property if the window size changes.


Getting a Token

Interrupt the form submit to send billing info to Recurly and get a secure token in exchange. Once you have the token, submit the form to your server.

$('form').on('submit', function (event) {
  var form = this;
  event.preventDefault();
  recurly.token(form, function (err, token) {
    if (err) {
      // handle error using err.code and err.fields
    } else {
      // recurly.js has filled in the 'token' field, so now we can submit the
      // form to your server; alternatively, you can access token.id and do
      // any processing you wish
      form.submit();
    }
  });
});

Recurly.js works with tokens, which represent secure and temporary storage for your customer’s sensitive billing information. They are stored directly on Recurly servers to reduce your PCI exposure.

When your customers submit your billing form, you’ll need to interrupt the submit and ask Recurly.js to create a token from the form. You may have noticed an additional hidden field in the form above, token. When you ask Recurly.js for a token during submit, it will automatically populate this field for you. After you get the token, you will submit it to your servers and use it there to talk to any endpoint in our API that accepts a billing_info.

This example demonstrates jQuery as an event-binding and DOM library; however, you may use any library you choose, or interact directly with the DOM (hard mode).

Reference

recurly.token

You must call recurly.token with your form element.

  recurly.token(document.querySelector('form'), tokenHandler);

Using a handler function like this one:

function tokenHandler (err, token) {
  if (err) {
    // handle error using err.code and err.fields
  } else {
    // handle success using token.id
  }
}

Sends billing information to Recurly to store as a token, sending that token id back to you.

Param Type Description
form HTMLFormElement Parent form containing data-recurly fields.
callback Function Callback function to accept the returned token.

A callback is always required.

Callback Arguments

Param Type Description
err RecurlyError or null A RecurlyError if an error occurred; otherwise null.
token Object An object containing a token id.
token.type String ‘credit_card’
token.id String A token id.

Returns

Nothing.


Using a Token

Create a new purchase with a token using one of our client libraries or API v3

Ruby

Node.js

Python

Java

Dotnet

purchase = {
  currency: "USD",
  account: {
    code: account_code,
    billing_info: {
      token_id: rjs_token_id
    },
  },
  subscriptions: [
    { plan_code: plan_code }
  ]
}

invoice_collection = @client.create_purchase(body: purchase)
let purchaseReq = {
  currency: 'USD',
  account: {
    code: accountCode,
    billingInfo: {
      tokenId: rjsTokenId
    }
  },
  subscriptions: [
    { planCode: planCode },
  ]
}

let invoiceCollection = await client.createPurchase(purchaseReq)
purchase = {
    "currency": "USD",
    "account": {
        "code": account_code,
        "billing_info": {"token_id": rjs_token_id},
    },
    "subscriptions": [{"plan_code": plan_code}],
}
invoice_collection = client.create_purchase(purchase)
PurchaseCreate purchase = new PurchaseCreate();
purchase.setCurrency("USD");

AccountPurchase account = new AccountPurchase();
account.setCode(accountCode);
purchase.setAccount(account);

BillingInfoCreate billing = new BillingInfoCreate();
billing.setTokenId(rjsTokenId);
account.setBillingInfo(billing);

List<SubscriptionPurchase> subscriptions = new ArrayList<SubscriptionPurchase>();
SubscriptionPurchase sub = new SubscriptionPurchase();
sub.setPlanCode(planCode);
subscriptions.add(sub);
purchase.setSubscriptions(subscriptions);

InvoiceCollection collection = client.createPurchase(purchase);
var purchaseReq = new PurchaseCreate()
{
    Currency = "USD",
    Account = new AccountPurchase()
    {
        Code = accountCode,
        BillingInfo = new BillingInfoCreate()
        {
            TokenId = rjsTokenId
        }
    },
    Subscriptions = new List<SubscriptionPurchase>()
    {
        new SubscriptionPurchase() { PlanCode = planCode }
    }
};

InvoiceCollection collection = client.CreatePurchase(purchaseReq);

Once Recurly.js has stored your customer’s sensitive data and given you a token reference, you will have 20 minutes to use it in our API. Expired tokens are permanently removed from the Recurly servers. Since tokens may be used to create charges in Recurly, be sure to keep them safe and only transmit them over a secure connection. Note that tokens do not expire after their first use. They can be reused as many times as you need during that 20 minute period.

Tokens expire after 20 minutes.

Tokens can be used to populate any account Billing Info data through our API. Simply assign it to the Billing Info’s token_id property and we’ll do the rest.

These endpoints accept tokens within Billing Info.

If you use a token, no other attributes will be allowed on that Billing Info for that request.


Events

Listen to events using the Emitter methods

// Listen to the 'change' event
recurly.on('change', changeHandler);

// But we're feeling indecisive today. Let's detach this event
recurly.off('change', changeHandler);

// .once will listen for one event then detach itself
recurly.once('field:submit', function () {
  $('#my-payment-form').submit();
});

function changeHandler (state) {
  // state.fields
}

A Recurly instance is an event emitter, and will emit events throughout the lifecycle of your customer’s interaction with your payment form. Events can be attached using the recurly.on method and removed using recurly.off. The example to the right shows the various ways that you can attach and remove events.

change

This event is emitted whenever a customer changes the state of hosted card fields, those that you may not otherwise observe directly with DOM events. For example, if your customer types ‘4’ into the number field, then the state of the number field will change, and the change event will emit.

The change event emits a RecurlyState object, whose values are demonstrated to the right. This will give you useful insight into the entire state of the recurly-controlled components of your payment form.

field:submit

This event is emitted when a user presses the enter key while they are focused on a hosted field. Since this action typically submits a form, we recommend performing a payment form submission when this event is emitted.

Note that you can detect the brand of the credit card entered using the “brand” field in the state object above.

Example RecurlyState object

{
  fields: {
    card: {
      brand: 'visa',
      cvv: {
        empty: false,
        focus: false,
        valid: true
      },
      empty: true,
      expiry: {
        empty: false,
        focus: false,
        valid: true
      },
      firstSix: '411111',
      focus: false,
      lastFour: '1111',
      number: {
        empty: false,
        focus: false,
        valid: true
      },
      valid: false
    },
    number: {
      valid: false,
      firstSix: '',
      lastFour: '',
      brand: 'unknown',
      empty: true,
      length: 0,
      focus: false
    },
    month: {
      valid: false,
      empty: true,
      length: 0,
      focus: false
    },
    year: {
      // same as month
    },
    cvv: {
      // same as month
    }
  }
}

Apple Pay

Use Recurly.js to process Apple Pay transactions

Recurly.js supports Apple Pay out of the box. To get started, ensure your site is configured to accept Apple Pay transactions.

Setting up your Apple Pay integration in Recurly.js involves two parts: a) displaying the button, and b) invoking the purchase flow.

Displaying The Button

Your button styling needs to adhere to Apple’s specifications.

See Apple’s documentation on Displaying the Apple Pay Button for guidelines on display and styling the button.

Invoking The Purchase Flow

Configure a new instance of recurly.ApplePay as follows.

var applePay = recurly.ApplePay({
  country: 'US',
  currency: 'USD',
  label: 'My Subscription', // This text will be displayed on the Apple Pay payment sheet as "My Subscription"
  total: '29.00'
});

// When the ApplePay instance is ready, bind the Apple Pay button click
// to applePay.begin
applePay.ready(function () {
  $('#my-apple-pay-button').on('click', function () {
    applePay.begin();
  });
});

// Handle errors. These may occur at any point in the Apple Pay flow
applePay.on('error', function (err) {
  // err.code, err.message
  console.error('Apple Pay error', err);
});

// This will fire when the flow is completed and a token has been generated
applePay.on('token', function (token) {
  console.log('Apple Pay succeeded. Token:', token.id);
  // Submit the token to your server
});

Additional configuration

If you are using the recurly.Pricing class to calculate checkout prices, you may pass your pricing instance instead of providing a total.

var pricing = recurly.Pricing();

var applePay = recurly.ApplePay({
  // ...
  pricing: pricing
});

To provide additional customer data to tokens generated by recurly.ApplePay, you may pass a form reference. recurly.ApplePay will collect customer data from the form just as would occur during credit card tokenization. See Getting a Token for more information on building such a form.

var applePay = recurly.ApplePay({
  // ...
  form: document.querySelector('#my-payment-form')
});

Integration Notes

  • Recurly.js will automatically pull in the billing info from the customer’s Apple account if their Apple Pay setup is complete with full billing information in their Apple Wallet. If the user does NOT have a billing name or address attached to their card in their Apple Wallet, the Apple Pay flow will prompt the customer for a billing address.
  • If you choose to include a Recurly.js payment form, any billing name or address fields entered on that form will be used instead of the address in the user’s Apple Wallet; the token request will contain the fields entered on the payment form. If the form is completely empty of name and address inputs, the token request will contain the name and address chosen by the user during the Apple Pay flow.

Reference

recurly.ApplePay

Arguments

Param Type Description
options Object  
options.country String Your ISO 3166 country code (ex: ‘US’). This is your country code as the merchant.
options.currency String ISO 4217 purchase currency (ex: ‘USD’)
options.label String Purchase description to display in the Apple Pay payment sheet.
[options.total] String Total cost to display in the Apple Pay payment sheet. Required if options.pricing is not provided.
[options.pricing] Pricing If provided, will override options.total and provide the current total price on the Pricing instance when the Apple Pay flow is initiated.
[options.form] HTMLElement If provided, tokens generated by the recurly.ApplePay` instance will include customer billing address from the form, overriding any billing address gathered from Apple Pay. See Getting a Token for all compatible fields.

Returns

A new recurly.ApplePay instance

applePay.ready

Arguments

Param Type Description
callback Function Called when the ApplePay instance has completed initialization. Will immediately invoke if the instance is already initialized. The callback is called with no arguments.

Returns

Nothing.

Events

token

This event is fired when the customer has completed the Apple Pay payment sheet flow. Recurly has received the payment details, and generated this token to be used in our API.

Signature

Param Type Description
token Object  
token.id String Token identifier to be sent to the API

error

This event is emitted when any error is encountered, whether during setup of the Apple Pay payment sheet, or during payment authorization. It will be useful to display errors to your customer if a problem occurs during the Apple Pay flow.

Signature

Param Type Description
error RecurlyError An error describing the issue that occurred.

Error codes

See Errors


Bank Accounts

Tokenize your users’ bank account information

Just as with a card form, use the data-recurly attribute to identify fields to Recurly.js. Since Recurly.js does not need to inject fields for bank accounts, all fields may be displayed as inputs on your payment form.

<form>
  <input type="text" data-recurly="routing_number">
  <input type="text" data-recurly="account_number">
  <input type="text" data-recurly="account_number_confirmation">
  <input type="text" data-recurly="account_type">
  <input type="text" data-recurly="name_on_account">
  <input type="hidden" name="recurly-token" data-recurly="token">
  <button>submit</button>
</form>

Bank Account inputs

Field Name Example Description
routing_number 123456789 Routing number. Required
account_number 987654321 Account number. Required
account_number_confirmation 987654321 Account number confirmation. Required
account_type checking or savings Account type. Required
name_on_account Pat Smith Full name on account. Required

Getting a Token

recurly.bankAccount.token

You may call recurly.bankAccount.token with a form element

recurly.bankAccount.token(document.querySelector('form'), tokenHandler);

Or with an Object

const billingInfo = {
  // required attributes
  routing_number: '123456780',
  account_number: '111111111',
  account_number_confirmation: '111111111',
  account_type: 'checking',
  name_on_account: 'Pat Smith',

  // optional attributes
  address1: '123 Main St.',
  address2: 'Unit 1',
  city: 'Hope',
  state: 'WA',
  postal_code: '98552',
  country: 'US',
  vat_number: 'SE0000'
};

recurly.bankAccount.token(billingInfo, tokenHandler);

Both methods require using a handler function like this one

function tokenHandler (err, token) {
  if (err) {
    // handle error using err.code and err.fields
  } else {
    // handle success using token.id
  }
}

This sends bank account billing information to Recurly to store as a token, returning that token id back to you via callback.

Arguments (form)

Param Type Description
form HTMLFormElement Parent form containing data-recurly fields
callback Function Callback function to accept the returned token

Alternatively, you can call recurly.bankAccount.token with a plain JavaScript object. This allows a more direct interface to the payment flow, eliminating any need to use the DOM.

Arguments (object)

Param Type Description
options Object An object with billing information properties matching those [outlined above].
callback Function Callback function to accept the returned token

A callback is always required

Callback Arguments

Param Type Description
err RecurlyError or null A RecurlyError if an error occurred; otherwise null.
token Object An object containing a token id.
token.type String ‘bank_account’
token.id String A token id.

Returns

Nothing.


PayPal

Use Recurly to process PayPal transactions using PayPal Business or Braintree.

A PayPal transaction is handled entirely within the PayPal checkout flow in a new window. Your customer will authorize a transaction within PayPal. Recurly will then record the authorization and return a Recurly token to you as it does for other payment methods.

You will need to use the token within our API before it expires, and expired tokens cannot be retrieved.

First, place a button on your page specifically for checking out with PayPal.

<button>Checkout with PayPal</button>

Next, create a new recurly.PayPal instance

var paypal = recurly.PayPal({
  display: { displayName: ' My product ' }
});

If you’re processing PayPal transactions with Braintree, you’ll pass a client authorization during instantiation:

var paypal = recurly.PayPal({
  braintree: { clientAuthorization: MY_CLIENT_AUTHORIZATION }
});

Your instance must then be setup to handle error scenarios and start the checkout flow.

paypal.on('error', function (err) {
  // err.code
  // err.message
  // [err.cause] if there is an embedded error
});

Next we must bind a listener to a user action on the button and have it trigger the start function on your recurly.PayPal instance. This will open the PayPal checkout flow.

As with the rest of Recurly.js, there are no external dependencies. The example uses jQuery to demonstrate binding events, but this can be done any way you wish.

$('#paypal-button').on('click', function () {
  paypal.start();
});

The start function must be called within a user-initiated event like ‘click’ or ‘touchend’

Finally, add a function to receive the token once your customer completes the checkout flow. At this point you will send the token id to your server to be used in the Recurly API to create a billing info for an account.

paypal.on('token', function (token) {
  // token.id
});

Reference

recurly.PayPal

Arguments

Param Type Description
options Object Optional.
options.braintree Object Optional. Braintree configuration.
options.braintree.clientAuthorization String If using Braintree to process PayPal transactions, provide your client authorization code here.

Returns

A new PayPal instance

payPal.start

Arguments

Param Type Description
options Object Optional.
options.description String Optional. In legacy PayPal flows, this description will be displayed during the checkout flow.

Returns

Nothing.

Events

error

This event is emitted when any error is encountered, whether during setup of the PayPal flow, or during the checkout process. It will be useful to display errors to your customer if a problem occurs during PayPal checkout.

Signature

Param Type Description
error RecurlyError An error describing the issue that occurred.

Error codes

See Errors

cancel

This event is emitted when the customer has canceled the PayPal checkout flow before completion. You may wish to reset parts of your checkout experience if this occurs.

Signature

None.

token

This event is fired when the customer has completed the PayPal checkout flow. Recurly has received the payment details, and generated this token to be used in our API.

Signature

Param Type Description
token Object  
token.type String ‘paypal’
token.id String Token identifier to be sent to the API

Pricing

Recurly automates complicated subscriptions, with many factors influencing total subscription price. With this in mind, Recurly.js provides a robust recurly.Pricing class designed to make determining actual subscription costs as simple and flexible as possible.

A Recurly.js pricing instance can be attached to the form we created above, or to any other section of your page meant to display subscription pricing. Let’s get to the specifics!

Reference

recurly.Pricing

var pricing = recurly.Pricing();

Creates a Pricing instance.

No Arguments

Returns

A new recurly.Pricing instance

pricing.attach

Given the following example HTML structure

<section id="pricing">
  <select data-recurly="plan">
    <option value="basic">Basic</option>
    <option value="notbasic">Not Basic</option>
  </select>
  <input type="text" data-recurly="coupon">
</section>

Use pricing.attach to bind the <section> to the pricing calculator.

var pricing = recurly.Pricing();

pricing.attach(document.querySelector('#pricing'));

This is the simplest way to use the pricing module. Simply pass a container element, and the pricing module will use all elements with a valid data-recurly attribute to determine price. When a value changes, the pricing module will automatically update its values. This allows your customers to manipulate a pricing form at will, and you will be able to react dynamically in any number of ways.

Arguments

Param Type Description
container HTMLElement Parent element containing all data-recurly elements

Returns

Nothing.

Elements

Elements bound to a pricing module may be for either input or output.

Input elements should be user-manipulable elements like input or select. If you want to input a value but not let a customer manipulate it, use an <input type="hidden">.

Input Elements

Field Name Example Value Description
plan basic Plan code.
plan_quantity 1 Plan quantity. Defaults to 1 if not specified.
coupon 15_off Coupon code.
addon 1 Addon quantity. To identify the addon being modified, use the data-recurly-addon attribute to set the addon code.
currency USD ISO-4217 currency code.
country US ISO 3166-1 alpha-2 country code.
postal_code 90210 Customer postal code. Used primarily to compute taxes.
tax_code digital Product tax code.
vat_number SE0000 Customer VAT number. Used for VAT exclusion.
tax_amount.now ‘0.99’ Specific tax amount to apply to the amount due now. Supplying this value will disable automated tax calculations.
tax_amount.next ‘1.99’ Specific tax amount to apply to the next billing cycle cost. Supplying this value will disable automated tax calculations.
gift_card 518822D87268C142 Gift card’s redemption code.

Output elements should be plain text elements like output, span, or div.

Output Elements

Field Name Example Value Description
total_now 100.00 Total subscription cost due now.
subtotal_now 90.00 Subtotal of the following pricing components.
addons_now 10.00 Total addon cost.
discount_now 5.00 Amount discounted with coupon use.
setup_fee_now 5.00 Subscription setup fee total.
tax_now 15.00 Total subscription taxation.
gift_card_now 75.00 The gift card amount that will be applied to the purchase today.
gift_card_next 25.00 The remainder gift card amount that will be applied to the next renewal.
currency_code USD, EUR ISO-4217 currency code.
currency_symbol $, Symbolic representation of currency_code.

data-recurly values ending in _now like subtotal_now have counterparts ending in _next. As you might expect, these correspond to the next billing cycle cost. These values are especially useful for plans with trial periods.

Events

Pricing instances emit events when various values are set or the price changes.

A Pricing instance itself behaves as an event emitter, where events can be attached using the pricing.on method and removed using pricing.off, similar to how events are managed on recurly.

change

This event is emitted whenever a pricing module has updated any of its pricing values. You can use this event to update your pricing display, compute total shopping costs, aggregate to analytics, etc.

Change emits a price object, shown in detail to the right.

set.*

set.* events are emitted when specific pricing objects change on a pricing module. For example, when a customer changes their plan, the pricing module will send set.plan. This is especially useful for updating checkout previews based on what the customer has selected as one example.

Param Type
set.plan Plan object.
set.price Price object.
set.addon Addon object.
set.coupon Coupon object.
set.address Address object.
set.currency Currency code.
set.tax Tax object.
set.gift_card Gift card object.

Pricing API

var pricing = recurly.Pricing();

pricing
  .plan('basic', { quantity: 1 })
  .currency('USD')
  .addon('addon1', { quantity: 2 })
  .coupon('coop')
  .giftcard('518822D87268C142')
  .address({
    country: 'US',
    postal_code: '90210'
  })
  .tax({
    tax_code: 'digital',
    vat_number: '',
    amounts: {
      now: '0.99',
      next: '1.99'
    }
  })
  .catch(function (err) {
    // err.code
  })
  .done(function (price) {
    // price object as emitted by 'change' event
  });

The pricing module can be manipulated with a set of direct method calls. This is useful if you would like to set up a complex pricing schema for your customers, or would just like to use a more programmatic method of determining subscription price. Events fire just as they normally would when using pricing.attach.

Note that Recurly.js’s DOM binding is one-way. Thus if you use the Pricing API on a pricing instance already attached to a container, the elements within will not update with your Pricing API calls. If you would like two-way DOM binding, we suggest using a framework such as AngularJS and using the Pricing API without attaching it to a container.

The example to the right demonstrates all the ways that a pricing module can be manipulated directly.

PricingPromise

Each Pricing API method will return a PricingPromise. This allows you to chain many asynchronous calls together without having to manage a complex chain of callbacks.

You don’t need to worry much about the internals of a PricingPromise, as it is designed to stay out of your way and facilitate asynchronous calls for you.

The catch method, as shown in the example, is used to handle error scenarios, such as when an addon cannot be applied to the selected plan.

At the end of a chain of pricing method calls, be sure to call .done() as this tells the pricing module to begin calculating, and gives you the subscription price.

Example Pricing State Object

emitted by the change event

{
  now: {
    subtotal: '25.00',
    addons: '0.00',
    discount: '0.00',
    setup_fee: '25.00',
    tax: '0.00',
    total: '25.00'
  },
  next: {
    subtotal: '10.00',
    addons: '0.00',
    discount: '0.00',
    tax: '0.00',
    total: '10.00'
  },
  base: {
    plan: {
      setup_fee: '25.00',
      unit: '10.00'
    },
    addons: {
      thing1: '14.00', // cost of one 'thing1' addon
      thing2: '8.00'
    },
  },
  currency: {
    code: 'USD',
    symbol: '$'
  }
}

3D-Secure

Strong customer authentication for your users.

Recurly.js provides a set of utilities that allow you to support 3-D Secure authentication on your checkout page seamlessly. For more information on 3-D Secure, see our introduction to Strong Customer Authentication.

Recurly’s support for 3-D Secure utilizes both Recurly.js and our API. For a complete guide to this integration and get started, start with our Strong Customer Authentication (SCA) Integration Guide.

Reference

recurly.Risk

Arguments

None.

Returns

A new Risk instance

recurly.ThreeDSecure

Arguments

Param Type Description
options Object  
options.actionTokenId String three_d_secure_action_token_id returned by the Recurly API when 3-D Secure authentication is required for a transaction

Returns

A new ThreeDSecure instance.

threeDSecure.attach

Arguments

Param Type Description
container HTMLElement A DOM element to contain any UI elements necessary to fulfill the 3-D Secure authentication process. We recommend this element be a minimum size of 250px (W) x 400px (H), and contain an interstitial message to explain that 3-D Secure authentication will be required to complete the transaction.

Returns

Nothing

EVENTS

token

This event is fired when your customer has completed the 3-D Secure flow. Recurly has received the authentication details, and generated this token to be used in our API.

Signature

Param Type Description
token Object  
token.type String ‘three_d_secure_action_result’
token.id String Token identifier to be sent to the API

error

This event is emitted when any error is encountered, whether during setup of the 3-D Secure flow, or during authentication. It will be useful to display errors to your customer if a problem occurs during the 3-D Secure flow.

Signature

Param Type Description  
error RecurlyError   An error describing the issue that occurred.

Error codes

See Errors

Example

var risk = recurly.Risk();
var threeDSecure = risk.ThreeDSecure({
  actionTokenId: myActionTokenId
});

threeDSecure.on('token', function (token) {
  // handle passing the action result
  // token back to your server

  // token.type => 'three_d_secure_action_result'
  // token.id

  // optionally, you may call threeDSecure.remove() to remove the element
});

threeDSecure.on('error', function (error) {
  // handle error scenarios.

  // error.code
  // error.message

  // optionally, you may call threeDSecure.remove() to remove the element
});

threeDSecure.attach(document.querySelector('#my-auth-container'));

Fraud

Recurly.js provides a fraud protection suite with support for our Fraud Management toolkit, Kount integration, and Braintree gateway integration.

With fraud protection enabled, tokens created with Recurly.js will include device data we use to analyze fraud risk and flag subsequent transactions accordingly. Configuration is simple.

Configuring Fraud Protection

Once you have enabled fraud protection on your site, modify your Recurly.js configuration call according to your fraud protection setup.

Recurly Fraud Management & Kount Integration

Recurly.js will handle all device data collection when configured as follows.

recurly.configure({
  // ...
  fraud: {
    kount: { dataCollector: true }
  }
  // ..
});

This will enable device data collection and automatically apply it to your tokens.

Braintree Gateway Fraud Integration

First, you will need to collect device data using the Braintree JavaScript client. This is required by Braintree.

// Collect device data using braintree client
// ...

var deviceData = braintreeInstance.deviceData;

recurly.configure({
  // ...
  fraud: {
    braintree: { deviceData: deviceData }
  }
  // ..
});

This will apply Braintree fraud data to your tokens generated by Recurly.js. Transactions created with those tokens will pass the fraud data to Braintree for fraud analysis.


Validation

Recurly.js bundles a few helpful methods for validating payment information prior to processing. These methods are used when generating tokens, but you can also use them to enhance your form validations and checkout flow.

It is also possible to inspect the validation state of hosted fields as your customer types, by listening to the ‘change’ event.

Reference

recurly.bankAccount.bankInfo

Retrieves bank info based from a given routing number.

recurly.bankAccount.bankInfo({ routingNumber: '123456780' }, function (err, bankInfo) {
  if (err) {
    // err.code, err.message
  } else {
    // bankInfo.bank_name
  }
});

Arguments

Param Type Description
options Object  
options.routingNumber String The routing number for a bank (ex: ‘123456780’)
callback Function  

Callback signature

Param Type Description
err RecurlyError or undefined Error. Usually invalid-routing-number
bankInfo Object  
bankInfo.bank_name String Bank institution name (ex: Bank of Recurly)

Errors

Errors are encapsulated by a RecurlyError, which contains a few standard properties to help you diagnose error cases and inform your customers accordingly.

Errors will be thrown if the exception will prevent proper execution. If an error can be recovered, it will be passed to the proper error handling event listener, callback, or PricingPromise handler for you to inspect.

Best Practices

The message property contains diagnostic information intended to help you diagnose problems with the form, and we do not recommend displaying its contents to your customers.

To provide the best customer experience, we recommend that you provide your own error text to be displayed, based on the error code you receive.

Error Codes

Configuration

Code Description
not-configured This error appears when you try to perform an operation without first calling recurly.configure.
missing-public-key When you call recurly.configure, you must do so with a publicKey property.
invalid-public-key Check the publicKey to ensure it matches that of your admin app’s API Access section.
missing-hosted-field-target This is thrown when the target element for a hosted payment field cannot be found on the page. Check the error message to check the selector being used, then check your page to ensure the element is present when recurly.configure is called.

Tokenization

Code Description
validation A request validation error has occurred. This can indicate many possible issues, and you should check the fields property to determine which fields caused the error.
invalid-parameter Occurs when a tokenization parameter does not pass our internal validations. Check the fields property to determine which fields caused the error.
api-error A request to the Recurly API has encountered an issue. This too can indicate many possible issues, and we recommend inspecting the message and fields properties for more information.

Pricing

Code Description
not-found This happens when a nonexistent plan is requested.
missing-plan A Pricing instance will emit this if a plan has not been specified before trying to set a proeprty that depends on a plan, such as a coupon or addon.
invalid-addon Occurs when an addon is added to a Pricing instance but is not valid for the instance’s selected plan.
invalid-currency Similarly, if a currency is requested which is not valid for the selected plan.
gift-card-currency-mismatch Occurs when a gift card is redeemed with a currency that doesn’t match the instance’s configured currency.

Apple Pay

Code Description Additional Properties
apple-pay-init-error A configuration issue has prevented initialization err the originating RecurlyError.
apple-pay-not-configured Your site does not have a gateway which supports Apple Pay  
apple-pay-configuration-invalid There is an issue with your Apple Pay authentication information. Check your certificate and key values in your gateway configuration.  
apple-pay-merchant-validation-error Apple encountered an error validating your merchant credentials  
apple-pay-payment-failure An error has occurred during tokenization, preventing the payment authorization  

PayPal

Code Description
paypal-not-configured In order to perform a PayPal transaction, your site must be configured to accept PayPal reference
paypal-canceled The customer canceled the PayPal agreement flow.
paypal-error A generic PayPal error has occurred. Inspect message to learn more.
invalid-routing-number The bank routing number is not valid

3-D Secure

Code Description Additional Properties
3ds-auth-error 3-D Secure authentication has failed because the customer could not be authenticated. We recommend prompting the user to try a different payment method. cause the originating Error.
3ds-result-tokenization-error An error occurred while attempting to tokenize the 3-D Secure authentication result. cause the originating RecurlyError.
3ds-vendor-load-error A third-party dependency had an issue loading. Dependencies are utilized when required by your payment gateway. vendor the dependency provider.
3ds-auth-determination-error The authentication method necessary to fulfill 3-D Secure requirements could not be determined  

Example RecurlyError object

{
  name: 'validation',
  code: 'validation',
  message: 'There was an error validating your request.',
  fields: [
    'number',
    'year'
  ]
}

Examples

Integration examples

We’ve prepared a full suite of example integrations for Ruby, Node.js, Python, and PHP using popular web frameworks for each language. These examples demonstrate the simplest method of integration, with a no-frills UI.

Code on GitHub


Upgrading

Upgrading from previous version of Recurly.js


Upgrading from v3

Recurly.js v4 introduced the concept of hosted fields. These are a more secure method of capturing customer card data, ensuring that their payment information is never exposed to your payment form. This is a huge benefit for security and reduced PCI compliance exposure.

First, you will need to update your payment form. The credit card fields number, month, year, and cvv will need to be removed and replaced with a container element in the form <div data-recurly="card"></div>. We recommend using the card field since it includes a handful of validation and UX improvements, but it is also possible to use separate fields for the number, month, year, and cvv. This is explained more completely in the Getting Started section.

Your recurly.token call may also need to be updated. It is now necessary to pass a reference to your checkout <form> that contains the hosted fields. Your callback function requires no modification. More info is available in the Getting a Token section.

You’ll notice that the hosted fields won’t look like the rest of your payment form inputs. That is because they are in fact iframes, and will need to be styled in order to get them to look right. We provide a stylesheet that works as a good baseline for styling the hosted fields to your needs (See the Getting Started section). To tweak styles further, and to cover styles for when the field is invalid, etc, see the Styling Card Fields section.

We are happy to assist further in your upgrade path. Feel free to reach out to us for Support.

Upgrading from versions prior to v3

Since version 3, Recurly.js shifted to credit card tokenization as its method of billing info capture. Given the significant changes, upgrading from an earlier version of Recurly.js will require a full rewrite of your integration. Please see the Getting Started section to begin.


Support

Recurly.js supports Chrome, Firefox, Safari, iOS, Edge, and IE 11+.

We’re also here to lend a hand on any Recurly.js integration questions! You can get help from us in a handful of ways:

  • Find us and other fellow developers in #recurly on freenode to chat in real-time.
  • Browse and post questions on Stackoverflow. We check these regularly.
  • Take a look at the code on GitHub. We welcome bug reports through Issues and contributions through Pull Requests.

For other Recurly related questions, please contact support@recurly.com for help with your account or other general questions.

For copies of documentation for previous versions of Recurly.js, please contact support.