- 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 r ecurly.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.
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+.
For Recurly related questions or previous versions of Recurly.js documentation, please contact support@recurly.com for help with your account or other general questions.