Multiple payment methods
This topic describes how to combine and use multiple payment methods in the one checkout form.
If you have not used FramePay previously, before you complete this tutorial, add FramePay to a form with one payment method in isolation. For tutorials, see Get started with FramePay.
For most payment methods, input mounting is not required, you only provide the method name when creating the token. However, some payment methods, such as: payment card and bank account, require inputs that must be mounted in your checkout form.
This topic describes how to set up your FramePay form to support the following payment methods:
- Express method.
- Payment card (requires input mounting).
- Bank account (requires input mounting).
- Any other alternative payment method (does not require input mounting).
1. Obtain IDs and a publishable API key
When you first log in to Rebilly, you create an organization as part of the setup process. A default website is created when a new organization is created. For more information, see Organizations and websites.
- Log in or sign up to Rebilly.
- Obtain your organization ID and website ID:
- In the left navigation bar, press Settings .
- In the Management section, press My organization & websites.
- In the Organization details section, note the ID value.
- In the Website section, note the ID value.
- Obtain your publishable API key:
- In the left navigation bar, press Automations .
- In the Development section, press API keys.
- Optionally, if you have not created a publishable key:
- In top right of the screen, press Create API key.
- In the API key type section, select Publishable.
- Optionally, in the Organizations dropdown, select the organizations that can use the API key.
- Optionally, in the Allowed IPs field, enter the IP addresses that are permitted to use the API key.
- Press Save API key.
- Go to the API keys page.
- Select a publishable key and copy the Key value.
2. Set up multiple payment methods using FramePay
Initial set up
Set up the library and provide the HTML.
Include the FramePay stylesheet
This adds default styles to FramePay elements on the page.
Include the FramePay script
This exposes FramePay in the global JS scope as Framepay
.
Create your checkout form
FramePay automatically gathers data from your checkout form.
To enable this, you must use data-rebilly
attributes on your input fields.
Add mounting points to your form
Add an empty placeholder div
with a unique ID for the following payment methods:
- Express methods (Paypal in this example).
- Methods that require input elements (payment card and bank account in this case).
Configure FramePay
This step describes the basic setup for mounting.
Initialize
Initialize FramePay with a configuration object.
For more information, see FramePay configuration reference.
Rebilly data
To connect with the Rebilly API, in your configuration object, provide your: publishable API key, organization ID, and website ID.
Transaction data
Provide the transaction data in your configuration object.
Optional: Style FramePay inputs
Customize the card payment and bank account fields to match the look and feel of the rest of your form.
To customize, add the style
property in your configuration object.
For all available properties, see Style reference.
Mount the (pre-)selected payment method
After initialization, mount the pre-selected payment method (either card payment or bank account) in their container. Keep track of the current element instances with a cache. This example uses a mountedFrames
array as a cache.
Also mount the express methods element in their container.
Handle change when a customer selects a different payment method
Note: This step is not necessary for express methods.
When a customer selects a different payment method, destroy the element instances by invoking the .destroy()
method.
Then, re-mount the FramePay element for the payment method that was selected by the customer.
Get the payment token
Generate a payment token using FramePay.
Express methods
For express methods, when a customer completes the flow, Rebilly creates a payment token.
To retrieve it, listen to the token-ready
event.
For more information, see Framepay.on('token-ready', ...).
Non-express methods
For non-express methods, to send the form data to FramePay, call Framepay.createToken()
.
- If the collected form data is valid, you receive a successful result with a new payment token.
- If the collected form data is not valid, you receive an error explaining why.
For more information, see Framepay.createToken(form).
To specify the payment method selected by the customer, when creating the payment token, pass its value as the method
property in extraData
. This example includes:
method: 'payment-card'
for card payment.method: 'ach'
for bank account.method: 'China UnionPay'
for China UnionPay.
For a full list of supported methods, see the method
payload of the Create payment token operation.
Basic set up complete
To learn more about FramePay, see:
- HTML
- JavaScript
- CSS
1<!DOCTYPE html>2 <html>3 <head>4 <link href="https://framepay.rebilly.com/framepay.css" rel="stylesheet" />5 <script src="https://framepay.rebilly.com/framepay.js"></script>6 </head>78 <body>9 <div class="container mm-example">10 <div id="paypal-mount"></div>1112 <div class="divider"></div>1314 <form id="payment-form">15 <div class="field">16 <input data-rebilly="firstName" placeholder="First name" />17 </div>18 <div class="field">19 <input data-rebilly="lastName" placeholder="Last name" />20 </div>21 <div class="field">22 <input data-rebilly="emails" placeholder="Email address" />23 </div>2425 <div class="payment-methods">26 <div class="tabs">27 <div class="tab">28 <input type="radio" id="card" name="paymentMethod" value="payment-card" checked />29 <label class="tab-label" for="card">Payment Card</label>30 <div class="tab-content">31 <div id="mounting-point"></div>32 </div>33 </div>3435 <div class="tab">36 <input type="radio" id="ach" name="paymentMethod" value="ach" />37 <label class="tab-label" for="ach">Bank account</label>38 <div class="tab-content">39 <div>40 <div class="field">41 <label class="label">Account type</label>42 <div id="bank-account-type"></div>43 </div>44 <div class="field">45 <label class="label">Account number</label>46 <div id="bank-account-number"></div>47 </div>48 <div class="field">49 <label class="label">Routing number</label>50 <div id="bank-routing-number"></div>51 </div>52 </div>53 </div>54 </div>5556 <div class="tab">57 <input type="radio" id="cn-u-pay" name="paymentMethod" value="China UnionPay" />58 <label class="tab-label" for="cn-u-pay">59 China UnionPay60 </label>61 <div class="tab-content">62 <div class="flex align-items-center">63 <div class="text-grey">64 After submitting your order, you will be redirected to securely complete your purchase.65 </div>66 </div>67 </div>68 </div>69 </div>70 </div>7172 <button id="pay-now">Make payment</button>73 </form>74 </div>75 </body>76 </html>
1let mountedFrames = [];23// Initialize FramePay4Framepay.initialize({5 // Use your own publishable key6 publishableKey: 'pk_sandbox_7FB1AJwXpG7qOrQukcKcBV_jBJ5622bGmTlknWH',7 organizationId: '97f171a4-55a7-4f9d-a5b3-4da67cb5ee06',8 websiteId: 'rebilly.com',9 transactionData: {10 currency: 'USD',11 amount: 10,12 },13 style: {14 buttons: {15 base: {16 color: '#363636',17 background: '#ffffff',18 fontSize: '14px',19 borderColor: '#dbdbdb',20 height: '36px',21 ':hover': {22 background: '#ffffff',23 borderColor: '#b5b5b5',24 },25 },26 focus: {27 background: '#ffffff',28 borderColor: '#000000',29 },30 active: {31 background: '#209cee',32 borderColor: '#209cee',33 },34 },35 },36});3738Framepay.on('ready', function () {39 // Mount any express methods40 Framepay.paypal.mount('#paypal-mount');4142 // Mount card payment and cache its element instance43 const card = Framepay.card.mount('#mounting-point');44 mountedFrames.push(card);45});4647function getSelectedMethod() {48 return document.querySelector('input[name="paymentMethod"]:checked').value;49}5051document.querySelectorAll('input[name="paymentMethod"]').forEach((radio) => {52 radio.addEventListener('change', function resetFramepay() {53 const method = getSelectedMethod();54 mountedFrames.forEach((item) => item.destroy());55 mountedFrames = [];5657 if (method === 'ach') {58 const type = Framepay.bankAccount.mount('#bank-account-type', 'bankAccountType');59 const number = Framepay.bankAccount.mount('#bank-account-number', 'bankAccountNumber');60 const routing = Framepay.bankAccount.mount('#bank-routing-number', 'bankRoutingNumber');61 mountedFrames.push(type, number, routing);62 }6364 if (method === 'payment-card') {65 const card = Framepay.card.mount('#mounting-point');66 mountedFrames.push(card);67 }68 });69});7071Framepay.on('token-ready', (token) => {72 alert(JSON.stringify(token, null, 2));73});7475// Add form submit event handler76const form = document.getElementById('payment-form');77form.addEventListener('submit', async (e) => {78 e.preventDefault();79 e.stopPropagation();8081 const extraData = {82 method: getSelectedMethod()83 };8485 try {86 const token = await Framepay.createToken(form, extraData);87 alert(JSON.stringify(token, null, 2));88 } catch (error) {89 alert(JSON.stringify(error, null, 2));90 }91});
1:root {2 --color-text: #2c3e50;3 --color-text-grey: #999;4 --color-body-bg: #ecf0f1;5}6html {7 font: 16px -apple-system, Helvetica, sans-serif;8 color: var(--color-text);9 background: var(--color-body-bg);10}11body {12 margin: 0;13 padding: 0;14}15.container {16 max-width: 500px;17 width: 100%;18 padding: 20px;19 margin: 0 auto;20 box-sizing: border-box;21}2223/* Form elements */24.mm-example .payment-methods {25 margin-top: 1.5rem;26}27.mm-example #paypal-mount {28 margin-top: 1rem;29}30.mm-example .field + .field {31 margin-top: 0.75rem;32}33.mm-example .label {34 display: block;35 font-weight: bold;36 font-size: 0.875rem;37 margin-bottom: 0.5rem;38}3940.mm-example input, .mm-example button {41 -webkit-appearance: none;42 -moz-appearance: none;43 appearance: none;44 outline: none;45 border-style: none;46}47.mm-example input {48 border: 1px solid #dbdbdb;49 border-radius: 4px;50 padding: 10px;51 width: 100%;52 box-sizing: border-box;53 background-color: #ffffff;54 color: #8a97a0;55 box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.1);56 transition: all 0.4s;57}58.mm-example input:focus {59 border-color: #3273dc;60 box-shadow: 0 0 0 0.125em rgba(50, 115, 220, 0.25);61 color: #363636;62}63.mm-example button {64 position: relative;65 display: block;66 padding: 15px;67 color: #fff;68 margin-top: 1rem;69 border-radius: 4px;70 background: #23d160;71 font-size: 1.125rem;72 text-align: center;73 font-style: normal;74 width: 100%;75 transition: all 0.4s;76}77.mm-example button:hover {78 background: #20bc56;79 cursor: pointer;80}8182/* Accordion styles */83/* CSS-only (no-js) accordion */84.tabs {85 border-radius: 8px;86 overflow: hidden;87 box-shadow: 0 4px 4px -2px rgba(0, 0, 0, 0.5);88 margin-top: 1rem;89}90.tab {91 width: 100%;92 overflow: hidden;93}94.tab > input[type='radio'] {95 position: absolute;96 opacity: 0;97 z-index: -1;98 width: 1px;99 height: 1px;100}101.tab-label {102 display: flex;103 justify-content: space-between;104 padding: 15px;105 color: #fff;106 background: var(--color-text);107 font-weight: bold;108 cursor: pointer;109}110.tab-label:hover {111 background: #1a252f;112}113.tab-label::after {114 content: '\276F';115 width: 1em;116 height: 1em;117 text-align: center;118 transition: all 0.35s;119}120.tab-content {121 max-height: 0;122 padding: 0 1em;123 background: white;124 transition: all 0.35s;125}126input:checked + .tab-label {127 background: #1a252f;128}129input:checked + .tab-label::after {130 transform: rotate(90deg);131}132input:checked ~ .tab-content {133 max-height: 100vh;134 padding: 1em;135}136137/* FramePay-specific styling */138.rebilly-framepay.rebilly-input {139 background: #ffffff;140 height: 40px;141 border: 1px solid #dbdbdb;142 padding: 0 10px;143 box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.1);144 transition: all 0.4s;145}146.rebilly-framepay.rebilly-input.rebilly-framepay-focus {147 border-color: #3273dc;148 box-shadow: 0 0 0 0.125em rgba(50, 115, 220, 0.25);149}150.rebilly-framepay.rebilly-framepay-buttons {151 border: none;152 box-shadow: none;153 padding: 0;154}155156/* Helpers */157.flex {158 display: flex;159}160.align-items-center {161 align-items: center;162}163.text-grey {164 color: var(--color-text-grey);165}166167/* Divider */168.divider {169 position: relative;170 text-align: center;171 margin: 1.25rem 0;172}173.divider::before {174 content: '';175 position: absolute;176 left: 0;177 top: 50%;178 height: 1px;179 background: #ccc;180 width: 100%;181 z-index: -1;182}183.divider::after {184 content: 'OR';185 font-size: 0.8125rem;186 display: inline-block;187 padding: 0 0.875rem;188 background: var(--color-body-bg);189 color: var(--color-text-grey);190}
Interactive example
This is an interactive example of a basic checkout form which uses FramePay to tokenize payments from multiple methods