Last updated 2 days ago

Getting started

FramePay allows you to build your checkout flow by offloading strict PCI Compliance requirements directly to Rebilly while maintaining the same look and feel your customers are used to. Once the required payment card or bank account information is collected, FramePay generates a payment token you can use to complete the checkout process.

It supports all of the payment methods and types of payments including bank payments (ACH/IBAN), PayPal payments, and 3D Secure 1 and 2.

HTMLJavaScriptCSS
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
<link href="https://framepay.rebilly.com/rebilly.css" rel="stylesheet">
<script src="https://framepay.rebilly.com/rebilly.js"></script>

<div>
    <form>
        <fieldset>
            <div class="field">
                <input data-rebilly="firstName" placeholder="First Name" type="text">
            </div>
            <div class="field">
                <input data-rebilly="lastName" placeholder="Last Name" type="text">
            </div>
            <div class="field" id="mounting-point"></div>
        </fieldset>
        <button>Make Payment</button>
    </form>
</div>

<link href="/examples/framepay-example-0-basic.css" rel="stylesheet">
<script src="/examples/framepay-example-0-basic.js"></script>
(function () {
    Rebilly.initialize({
        publishableKey: 'pk_sandbox_Lvl5rm8lLrtAV6iSL3CIdYLAburumF4Ld8b1KDs'
    });

    var form = document.querySelector('form');

    Rebilly.on('ready', () => {
        var card = Rebilly.card.mount('#mounting-point');
    });


    form.addEventListener('submit', (e) => {
        e.preventDefault();
        e.stopPropagation();

        Rebilly.createToken(form)
            .then(result => {
                console.log('Framepay success', result);
                window.parent.postMessage('success', '*')
            })
            .catch(error => {
                console.log('Framepay error', error);
                window.parent.postMessage('error', '*')
            });
    });
})();
* {
    font-family: Roboto, Open Sans, Segoe UI, sans-serif;
}

body {
    background-color: #EDF3FE;
    padding: 2em 2em;
    font-family: Roboto;
}


fieldset {
    border: none;
    margin: 0 0 40px 0;
    padding: 0;
}

.field + .field {
    margin-top: 10px;
}

label {
    display: block;
    margin-bottom: 8px;
}

input,
button {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    outline: none;
    border-style: none;
}

input {
    border: none;
    border-radius: 4px;
    font-size: 15px;
    margin: 0;
    outline: 0;
    padding: 10px;
    width: 100%;
    box-sizing: border-box;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    background-color: #fff;
    color: #8a97a0;
    -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.03) inset;
    -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.03) inset;
    box-shadow: 0 1px 0 rgba(0, 0, 0, 0.03) inset;
}

button {
    position: relative;
    border: none;
    padding: 8px 16px;
    color: #FFF;
    margin: 0 auto;
    border-radius: 8px;
    background: #1abc9c;
    font-size: 18px;
    text-align: center;
    font-style: normal;
    width: 100%;
    box-shadow: 0 10px 30px 0 rgba(26, 188, 156, 0.5);
    -moz-box-shadow: 0 10px 30px 0 rgba(26, 188, 156, 0.5);
    -webkit-box-shadow: 0 10px 30px 0 rgba(26, 188, 156, 0.5);
    -o-box-shadow: 0 10px 30px 0 rgba(26, 188, 156, 0.5);
    -ms-box-shadow: 0 10px 30px 0 rgba(26, 188, 156, 0.5);
    -webkit-transition: all 0.4s;
    -o-transition: all 0.4s;
    -moz-transition: all 0.4s;
    transition: all 0.4s;
}

button:hover {
    background: #000000;
    box-shadow: 0 10px 30px 0 rgba(0, 0, 0, 0.2);
    -moz-box-shadow: 0 10px 30px 0 rgba(0, 0, 0, 0.2);
    -webkit-box-shadow: 0 10px 30px 0 rgba(0, 0, 0, 0.2);
    -o-box-shadow: 0 10px 30px 0 rgba(0, 0, 0, 0.2);
    -ms-box-shadow: 0 10px 30px 0 rgba(0, 0, 0, 0.2);
    cursor: pointer;
}


.rebilly-framepay.rebilly-framepay-valid {
    border-color: rgba(0, 221, 26, .3);
}

.rebilly-framepay.rebilly-framepay-focus {
    /*border-color: rgba(0, 221, 26, .3);*/
}

.rebilly-framepay.rebilly-framepay-invalid {
    border-color: rgba(221, 0, 4, .3);
}

To create a checkout flow using FramePay you will have to complete these steps:

  1. Set up FramePay
  2. Set up your form
  3. Collect customer information and create a token
  4. Finish the checkout flow

Set up FramePay

FramePay is part of Rebilly.js. Simply include the line below into your checkout page to enable it.

<script src="https://framepay.rebilly.com/rebilly.js"></script>

The library is then exposed in the global scope as Rebilly.

Adding default element styles

By default FramePay does not inject CSS styles for the elements that are being generated into your form. However we provide a CSS file you can use to give elements a default look.

<link href="https://framepay.rebilly.com/rebilly.css" rel="stylesheet">

Set up your form

FramePay injects UI elements into your form that are hosted by Rebilly which allows it to securely collect payment instrument data from your customers.

Start by creating your payment form as you would usually. Then create empty DOM elements within your form to determine where FramePay should mount UI elements.

Payment card example:

<form method="post" action="/process">
    <div class="field">
        <label>Payment Card</label>
        <div id="payment-card">
            <!-- FramePay will inject the payment card field here -->
        </div>
        <!-- Provide an automatic way to inject the
            payment token as a hidden field -->
        <input type="hidden" data-rebilly="token" name="rebilly-token">
    </div>
    <button>Checkout</button>
</form>

After the page has loaded you need to initialize FramePay with your Rebilly publishable API key and mount the payment card element at the desired location.

// initialize with your publishable key
Rebilly.initialize({publishableKey: 'pk_sandbox_1234567890'});
Rebilly.on('ready', () => {
    // mount a combined card element on the #payment-card `<div>` in the form above
    Rebilly.card.mount('#payment-card');
});
Use your own publishable key
You must replace the key `pk_sandbox_1234567890` with your own. We recommend starting with a sandbox key. To create a publishable key, visit Rebilly.

By default a card element will generate a combined field that lets the customers enter their payment card number, expiry and CVV in a single input. However, you can chose to separate them by mounting into three separate locations. See the library reference for a list of supported field types.

Inline validation is automatic but no error messages are displayed unless you subscribe to the change event on the element and display them.

card.on('change', function ({valid, completed, source, error}) {
    if (error) {
        // event.error exposes {code, message, type, details}
        console.log(error.message);
    }
    if (valid) {
        // field input became valid
    }
});

Alternatively you can display error messages only when submitting the form.

Error Handling
Wrap your code with a `try/catch` block to detect any thrown errors that would prevent proper execution of FramePay. Errors that relate to validation and allow execution will be passed to the `createToken().catch()` method and other event handler you defined for elements.

Collect customer information and create a token

To collect the customer's information and the payment card data, define an event handler for the form submit event. Any input fields with a data-rebilly attribute will be parsed automatically and sent alongside the elements' data.

See the list of all data-rebilly fields that can be automatically saved by FramePay for more details.

Trigger Rebilly.createToken to generate and inject the payment token into your form. The method returns a Promise with a single argument representing the API result of the operation. Validation or network errors can be caught using a catch() handler and displayed to the customer.

var form = document.querySelector('form');
form.addEventListener('submit', function (event) {
    event.preventDefault();
    Rebilly.createToken(form)
        .then(function (token) {
            // we have a token field in the form
            // thus we can submit directly
            form.submit();
        })
        .catch(function (error) {
            // see error.code and error.message
        });
});

Alternatively you can exclude the data-rebilly="token" field and add the payment token information to the form dynamically before submitting it to your server.

Finish the checkout flow

Once the payment token has been added to the form and submitted to your server you can use one of Rebilly's backend SDKs to finish the checkout flow.

Create a new customer, a payment instrument and finally a transaction.

Rebilly API SDKs

Rebilly offers SDKs for these programming languages:

View examples

Take a look at example implementations of FramePay for payment cards, bank accounts and other payment methods supported by Rebilly.

Update your customer's payment card information

Keeping customers' payment card information up to date is very important. With FramePay, updating payment card information is simple, safe, and secure. Use a separated fields form to update the expiration date, CVV, or billing address.

The process is similar to create a payment card by using the generated FramePay token. The token is used to update the desired payment card.

Using with ReactJS

Supported versions: 14,15,16+ We offer a wrapper component for ReactJS, called framepay-react.


framepay-react is the easiest way to integrate framepay into your React project. However, if you prefer to use framepay directly, you can look at the example framepay-preact-direct-integration

Using with VueJS

We offer a wrapper component for VueJS, called framepay-vue.