{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["code-walkthrough","download-button","step","admonition"]},"redocly_category":"Documentation","type":"markdown"},"seo":{"title":"End-to-end FramePay integration","description":"Learn how to integrate the FramePay library and use a tokenized payment data to complete a purchase transaction.","siteUrl":"https://www.rebilly.com","image":"/assets/rebillysocial.94fb32fc280c9e84b963c440ec462771d25f4e6fdaaa6c59de41e8135113b46b.db81178d.png","lang":"en-US","llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]},"keywords":"Developer docs, FramePay"},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"CodeWalkthrough","attributes":{"__idx":1,"preview":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This is an interactive example of an end-to-end FramePay integration that uses a sample Express server file."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Complete the payment flow using this test card number: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["4111 1111 1111 1111"]},"."," ","Use any future expiration date and any 3 digits for the CVC number."," ","For more test cards, see ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"/docs/tutorials/test-payment-cards"},"children":["Test cards, IBANs, and ACH details"]},"."]},{"$$mdtype":"Tag","name":"iframe","attributes":{"src":"/examples/framepay-checkout/checkout.html","style":{"margin":"8px auto","width":"100vh","height":"480px","border":"0","borderRadius":"12px"},"scrolling":"yes","loading":"lazy"},"children":[]}],"filters":{},"filesets":[{"files":[{"path":"docs/dev-docs/_code-samples/end-to-end-framepay-example/server.js","content":[{"start":0,"condition":{"steps":["install-dependencies"]},"children":["const RebillyAPI = require(\"rebilly-js-sdk\").default;","const express = require(\"express\");"]},"",{"start":5,"condition":{"steps":["set-up-server"]},"children":["const app = express();","const port = 3000;","app.use(express.static(\"client\"));","app.use(express.json());"]},"",{"start":12,"condition":{"steps":["provide-credentials"]},"children":["const API_SECRET_KEY = \"API_SECRET_KEY\";","const ORGANIZATION_ID = \"ORGANIZATION_ID\";","const WEBSITE_ID = \"WEBSITE_ID\";"]},"",{"start":18,"condition":{"steps":["initialize-rebilly-js-sdk"]},"children":["const api = RebillyAPI({","    apiKey: API_SECRET_KEY,","    organizationId: ORGANIZATION_ID,","    sandbox: true,","});"]},"",{"start":26,"condition":{"steps":["add-an-endpoint"]},"children":["app.post(\"/create-transaction\", async (req, res) => {","    try {","        const { paymentToken, billingAddress: primaryAddress, currency, amount } = req.body;"]},"",{"start":32,"condition":{"steps":["create-a-customer"]},"children":["        const { fields: customer } = await api.customers.create({","            data: {","                paymentToken,","                primaryAddress,","            },","        });"]},"",{"start":41,"condition":{"steps":["create-a-sale-transaction"]},"children":["        const { fields: transaction } = await api.transactions.create({","            data: {","                type: \"sale\",","                websiteId: WEBSITE_ID,","                customerId: customer.id,","                currency,","                amount,","            },","        });"]},"",{"start":53,"condition":{"steps":["handle-the-response"]},"children":["        res.status(201).send(transaction);","    } catch (error) {","        const message = err.details ?? \"Internal Server Error\";","        const code = err.status ?? 500;","        res.status(500).send({ code, message });","    }","});"]},"","// Redirect to /checkout.html when the app loads up on stackblitz","app.get(\"/\", async (req, res) => {","    res.redirect(301, \"/checkout.html\");","});","",{"start":68,"condition":{"steps":["start-the-express-server"]},"children":["app.listen(port, () => {","    console.log(`App listening at port: ${port}`);","});"]},""],"metadata":{"steps":["install-dependencies","set-up-server","provide-credentials","initialize-rebilly-js-sdk","add-an-endpoint","create-a-customer","create-a-sale-transaction","handle-the-response","start-the-express-server"]},"basename":"server.js","language":"javascript"}],"downloadAssociatedFiles":[]},{"files":[{"path":"docs/dev-docs/_code-samples/end-to-end-framepay-example/client/checkout.html","content":["<!doctype html>","<html lang=\"en\">","    <head>","        <meta charset=\"UTF-8\" />","        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />","        <title>FramePay integrated checkout example</title>",{"start":6,"condition":{"steps":["include-the-framepay-stylesheet"]},"children":["        <link rel=\"stylesheet\" href=\"https://framepay.rebilly.com/framepay.css\" />"]},{"start":9,"condition":{"steps":["include-the-framepay-script"]},"children":["        <script src=\"https://framepay.rebilly.com/framepay.js\"></script>"]},{"start":12,"condition":{"steps":["add-css-for-checkout-form"]},"children":["        <link rel=\"stylesheet\" href=\"styles.css\" />"]},"        <script src=\"client.js\" defer></script>","    </head>","    <body>","        <div class=\"container\">","            <div class=\"product\">","                <span class=\"product-name\">Sample product</span>","                <span class=\"product-total\">$100.00</span>","            </div>",{"start":23,"condition":{"steps":["create-your-checkout-form"]},"children":["            <form id=\"checkout-form\" class=\"form\">","                <div class=\"error-message hidden\"></div>","                <div class=\"field\">","                    <input required data-rebilly=\"firstName\" placeholder=\"First Name\" />","                </div>","                <div class=\"field\">","                    <input required data-rebilly=\"lastName\" placeholder=\"Last Name\" />","                </div>","                <div class=\"field\">",{"start":33,"condition":{"steps":["include-the-html-mounting-points"]},"children":["                    <div id=\"mounting-point\"></div>"]},"                </div>","                <div class=\"action\">","                    <button>Make payment</button>","                </div>","            </form>"]},"        </div>","    </body>","</html>",""],"metadata":{"steps":["include-the-framepay-stylesheet","include-the-framepay-script","add-css-for-checkout-form","create-your-checkout-form","include-the-html-mounting-points"]},"basename":"checkout.html","language":"html"}],"downloadAssociatedFiles":[]},{"files":[{"path":"docs/dev-docs/_code-samples/end-to-end-framepay-example/client/client.js","content":[{"start":0,"condition":{"steps":["initialize-framepay"]},"children":["Framepay.initialize({","    publishableKey: \"publishableKey\","]},"",{"start":5,"condition":{"steps":["optional-style-the-card-input"]},"children":["    icon: {","        color: \"#2c3e50\",","    },","    style: {","        base: {","            fontSize: \"16px\",","            boxShadow: \"none\",","        },","    },","});"]},"",{"start":18,"condition":{"steps":["setup-dom-elements"]},"children":["const form = document.getElementById(\"checkout-form\");","const errorMessageBox = document.querySelector(\".error-message\");","const btnSubmit = document.querySelector(\".action button\");"]},"",{"start":24,"condition":{"steps":["mount-the-card-field"]},"children":["Framepay.on(\"ready\", function () {","    Framepay.card.mount(\"#mounting-point\");","});"]},"",{"start":30,"condition":{"steps":["handle-the-form-submit-event"]},"children":["form.addEventListener(\"submit\", async (e) => {","    e.preventDefault();","    e.stopPropagation();","","    try {","        btnSubmit.disabled = true;"]},"",{"start":39,"condition":{"steps":["create-a-payment-token"]},"children":["        const { id: paymentToken, billingAddress } = await Framepay.createToken(form);"]},"",{"start":43,"condition":{"steps":["send-token-to-server"]},"children":["        const purchase = {","            paymentToken,","            billingAddress,","            currency: \"USD\",","            amount: 100,","        };","","        const response = await fetch(\"/create-transaction\", {","            method: \"POST\",","            headers: {","                \"Content-Type\": \"application/json\",","            },","            body: JSON.stringify(purchase),","        });"]},"",{"start":60,"condition":{"steps":["handle-the-api-response"]},"children":["        const transaction = await response.json();","        const approvalUrl = transaction?._links.find(({ rel }) => rel === \"approvalUrl\");","","        if (approvalUrl) {","            window.location = approvalUrl.href;","        } else {","            window.location = \"/thank-you.html\";","        }"]},"",{"start":71,"condition":{"steps":["handle-errors-and-button-state"]},"children":["    } catch (error) {","        console.log(error);","        errorMessageBox.innerText = \"Something went wrong, please try again.\";","        errorMessageBox.classList.remove(\"hidden\");","    } finally {","        btnSubmit.disabled = false;","    }","});"]},""],"metadata":{"steps":["initialize-framepay","optional-style-the-card-input","setup-dom-elements","mount-the-card-field","handle-the-form-submit-event","create-a-payment-token","send-token-to-server","handle-the-api-response","handle-errors-and-button-state"]},"basename":"client.js","language":"javascript"}],"downloadAssociatedFiles":[]},{"downloadAssociatedFiles":[{"path":"docs/dev-docs/_code-samples/end-to-end-framepay-example/client/styles.css","content":["/* Variables */",":root {","    --color-primary: #0044d4;","    --color-text: #2c3e50;","    --color-border: #ccc;","    --color-danger: #e74c3c;","}","* {","    box-sizing: border-box;","}","","body {","    color: var(--color-text);","    font:","        16px -apple-system,","        Avenir,","        Helvetica,","        Arial,","        sans-serif;","    -webkit-font-smoothing: antialiased;","    background-color: #ffffff;","    margin: 0;","    padding: 0;","    background: #eee;","}",".container {","    max-width: 500px;","    width: 100%;","    background-color: #fff;","    padding: 30px 20px;","    margin: 40px auto;","    box-shadow: 0 0 30px rgba(0, 0, 0, 0.1);","}","","/* Product information */",".product {","    display: flex;","    align-items: center;","    justify-content: space-between;","    margin-bottom: 20px;","}",".product-name {","    font-weight: 600;","    font-size: 18px;","}",".product-total {","    font-weight: bold;","    font-size: 24px;","}","","/* Form elements */",".error-message {","    margin-bottom: 20px;","    padding: 15px;","    background-color: var(--color-danger);","    text-align: center;","    font-weight: bold;","    color: #fff;","}",".form .field + .field,",".form .field + .action {","    margin-top: 10px;","}",".form input,",".form button {","    -webkit-appearance: none;","    -moz-appearance: none;","    appearance: none;","    outline: none;","    border-style: none;","}",".form input {","    border: none;","    font-size: 16px;","    margin: 0;","    outline: 0;","    padding: 15px 20px;","    width: 100%;","    color: var(--color-text);","    border: 1px solid var(--color-border);","}",".form input:focus {","    color: var(--color-text);","    border-color: var(--color-primary);","}",".form input::placeholder {","    color: #aaa;","}",".form button {","    display: block;","    padding: 15px;","    font-weight: bold;","    font-size: 18px;","    background: var(--color-primary);","    color: #fff;","    width: 100%;","    cursor: pointer;","}",".form button:disabled {","    opacity: 0.5;","}","","/* FramePay-specific styling */",".form .rebilly-framepay {","    padding: 15px 20px;","    height: 55px;","    border: 1px solid var(--color-border);","    border-radius: 0;","    box-shadow: none;","}","",".form .rebilly-framepay.rebilly-framepay-focus {","    color: var(--color-text);","    border-color: var(--color-primary);","    box-shadow: none;","}","","/* Thank you page */",".thank-you {","    text-align: center;","}","",".thank-you h1 {","    color: var(--color-primary);","    margin-bottom: 20px;","}","",".thank-you p {","    margin-bottom: 15px;","    font-size: 18px;","}","","#transaction-id {","    font-weight: bold;","    color: var(--color-primary);","    font-family: monospace;","}","",".btn-back {","    display: inline-block;","    margin-top: 20px;","    padding: 12px 24px;","    background: var(--color-primary);","    color: white;","    text-decoration: none;","    border-radius: 4px;","    font-weight: bold;","}","",".btn-back:hover {","    opacity: 0.9;","}","","/* Helpers */",".hidden {","    display: none;","}",""],"metadata":{"steps":[]},"basename":"styles.css","language":"css"}],"files":[]},{"downloadAssociatedFiles":[{"path":"docs/dev-docs/_code-samples/end-to-end-framepay-example/client/thank-you.html","content":["<!doctype html>","<html lang=\"en\">","    <head>","        <meta charset=\"UTF-8\" />","        <link rel=\"icon\" type=\"image/svg+xml\" href=\"favicon.svg\" />","        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />","        <link href=\"./style.css\" rel=\"stylesheet\" />","        <title>FramePay Example - Success</title>","    </head>","    <body>","        <div class=\"container\">","            <div class=\"thank-you\">","                <h1>Thank you!</h1>","                <p>We hope you enjoy your purchase.</p>","            </div>","        </div>","    </body>","</html>",""],"metadata":{"steps":[]},"basename":"thank-you.html","language":"html"}],"files":[]},{"downloadAssociatedFiles":[{"path":"docs/dev-docs/_code-samples/end-to-end-framepay-example/README.md","content":["# Integrate FramePay with a custom checkout form","","This example describes how to add the FramePay JavaScript library to a checkout page and use it to tokenize payment card information.","It also describes how to set up a server using the Rebilly JS SDK and use the token to complete a purchase transaction.","","To view the integration guide, see [End-to-end FramePay integration](https://www.rebilly.com/docs/dev-docs/end-to-end-framepay-example/).","","## Setup","","1. Install dependencies: `npm install`","","2. Configure credentials:","","> In production, it is recommended to use a secrets manager to store your secret key instead of including it alongside code.","","In `server.js`, update the following variables with your credentials: `REBILLY_API_SECRET_KEY`, `REBILLY_WEBSITE_ID`, `REBILLY_ORGANIZATION_ID`.","","3. Set payment parameters:","","In `client/client.js`, add your `publishableKey` value for the transaction.","","## Start the sample application","","1. Start a server: `node server.js`","","2. Open the application: [http://localhost:3000](http://localhost:3000).","","## Error handling","","Errors from the server are logged to your console.","Check the developer tools in your web browser for client-side errors.",""],"metadata":{"steps":[]},"basename":"README.md","language":"markdoc"}],"files":[]},{"downloadAssociatedFiles":[{"path":"docs/dev-docs/_code-samples/end-to-end-framepay-example/package.json","content":["{","  \"name\": \"node-starter\",","  \"version\": \"0.0.0\",","  \"description\": \"Basic and simplified integrated implementation of FramePay in a checkout page.\",","  \"main\": \"server.js\",","  \"scripts\": {","    \"start\": \"nodemon\"","  },","  \"dependencies\": {","    \"express\": \"^4.18.1\",","    \"rebilly-js-sdk\": \"^46.5.0\"","  },","  \"devDependencies\": {","    \"nodemon\": \"^2.0.19\"","  }","}",""],"metadata":{"steps":[]},"basename":"package.json","language":"text"}],"files":[]}],"steps":[{"id":"install-dependencies","heading":"Install dependencies"},{"id":"set-up-server","heading":"Set up the server"},{"id":"provide-credentials","heading":"Provide credentials"},{"id":"initialize-rebilly-js-sdk","heading":"Initialize the Rebilly JS SDK"},{"id":"add-an-endpoint","heading":"Add an endpoint"},{"id":"create-a-customer","heading":"Create a customer"},{"id":"create-a-sale-transaction","heading":"Create a sale transaction"},{"id":"handle-the-response","heading":"Handle the response"},{"id":"start-the-express-server","heading":"Start the Express server"},{"id":"include-the-framepay-script","heading":"Include the FramePay script"},{"id":"add-css-for-checkout-form","heading":"Optional: Add CSS for your checkout form"},{"id":"create-your-checkout-form","heading":"Create your checkout form"},{"id":"include-the-html-mounting-points","heading":"Include HTML mounting points"},{"id":"initialize-framepay","heading":"Initialize FramePay"},{"id":"optional-style-the-card-input","heading":"Optional: Style the card input"},{"id":"setup-dom-elements","heading":"Get DOM elements"},{"id":"mount-the-card-field","heading":"Mount the card field"},{"id":"handle-the-form-submit-event","heading":"Handle the form submit event"},{"id":"create-a-payment-token","heading":"Create a payment token"},{"id":"send-token-to-server","heading":"Send token to server"},{"id":"handle-the-api-response","heading":"Handle the API response"},{"id":"handle-errors-and-button-state","heading":"Handle errors and button state"},{"id":"run-the-example","heading":"Run the example"}],"inputs":{},"toggles":{}},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"end-to-end-framepay-integration","__idx":0},"children":["End-to-end FramePay integration"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This guide describes how to add the FramePay library to a checkout page and use it to tokenize payment card information."," ","It also describes how to set up a simple server using the Rebilly JS SDK and use the token to complete a purchase transaction."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This guide uses Node.js (",{"$$mdtype":"Tag","name":"a","attributes":{"href":"https://expressjs.com"},"children":["Express"]},") as the server-side language for the implementation."," ","The code described in this topic is available in the Rebilly ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"https://github.com/Rebilly/framepay-integrated-example"},"children":["framepay-integrated-example"]}," GitHub repository."]},{"$$mdtype":"Tag","name":"DownloadButton","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"details","attributes":{},"children":[{"$$mdtype":"Tag","name":"summary","attributes":{},"children":["Prerequisites"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To complete this guide, you must have an organization ID, a website ID, a secret API key, and a publishable API key."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You must also have a payment gateway configured in your Rebilly account."," ","For sandbox testing, the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["TestProcessor"]}," gateway is pre-configured."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If you already have your IDs and API keys, continue to ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"#step-1-set-up-the-server"},"children":["Step 1: Set up the server"]},"."," ","If you do not, see ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"/docs/dev-docs/set-up-environment"},"children":["Set up your environment"]},"."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"step-1-set-up-the-server","__idx":1},"children":["Step 1: Set up the server"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Set up an Express node app to authenticate the client."]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"install-dependencies","heading":"Install dependencies"},"children":[{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Install the required dependencies in your project directory:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"npm install express rebilly-js-sdk --save\n","lang":"bash"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For more information, see ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"/docs/dev-docs/js-sdk-quickstart/"},"children":["JS SDK quickstart guide"]},"."]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Declare Express and the Rebilly SDK as dependencies."]}]}]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"set-up-server","heading":"Set up the server"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Set up an Express.js web server that serves static files from a 'client' directory and can parse JSON request bodies."]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"provide-credentials","heading":"Provide credentials"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Provide your secret API key, Organization ID, and website ID."," ","For more information, see ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"/docs/dev-docs/end-to-end-framepay-example#prerequisites"},"children":["Prerequisites"]},"."]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"initialize-rebilly-js-sdk","heading":"Initialize the Rebilly JS SDK"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Initialize the Rebilly JS SDK with your secret key and organization ID."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For more information, see ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"/docs/dev-docs/end-to-end-framepay-example#prerequisites"},"children":["Prerequisites"]},"."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"step-2-create-a-transaction","__idx":2},"children":["Step 2: Create a transaction"]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"add-an-endpoint","heading":"Add an endpoint"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Add an endpoint on your server that creates a transaction."," ","This endpoint must receive the FramePay-generated token as the payload."]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"create-a-customer","heading":"Create a customer"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Create a customer using the billing address and the payment token."]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"create-a-sale-transaction","heading":"Create a sale transaction"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Create a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sale"]}," transaction and use the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["customerId"]},"."]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"handle-the-response","heading":"Handle the response"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Handle the response from the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST /create-transaction"]}," endpoint."]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"start-the-express-server","heading":"Start the Express server"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Start the Express.js server and listen for incoming requests."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"step-3-create-a-checkout-page","__idx":3},"children":["Step 3: Create a checkout page"]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For this guide, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["checkout.html"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client.js"]}," must be placed in a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client"]}," directory in the root of your project."]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"include-the-framepay-script","heading":"Include the FramePay script"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Expose the FramePay library in the global JS scope as ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Framepay"]},"."]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"add-css-for-checkout-form","heading":"Optional: Add CSS for your checkout form"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Add CSS styles for your checkout form."]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"create-your-checkout-form","heading":"Create your checkout form"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Create a checkout form on your page."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Define the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["data-rebilly"]}," attributes on your input fields."," ","This instructs the FramePay library to automatically gather data from your checkout form."]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"include-the-html-mounting-points","heading":"Include HTML mounting points"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Specify an empty placeholder ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["div"]}," with a unique ID."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This is where the FramePay library will render the card field by injecting an iframe."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"step-4-set-up-client-side-script","__idx":4},"children":["Step 4: Set up client-side script"]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"initialize-framepay","heading":"Initialize FramePay"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Initialize the FramePay library with a configuration object."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Provide your publishable API key to connect with the Rebilly API."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For more information, see ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"/docs/dev-docs/framepay-configuration-reference/"},"children":["FramePay configuration reference"]}," and ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"/docs/dev-docs/end-to-end-framepay-example#prerequisites"},"children":["Prerequisites"]},"."]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"optional-style-the-card-input","heading":"Optional: Style the card input"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Customize the card payment field to match the style of your checkout form."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To customize, add the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["style"]}," property in the configuration object."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For all available properties, see ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"/docs/dev-docs/framepay-configuration-reference/#style"},"children":["Style reference"]},"."]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"setup-dom-elements","heading":"Get DOM elements"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Create references to the form elements that will be used in the payment flow."]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"mount-the-card-field","heading":"Mount the card field"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Mount the payment card field."," ","For more information, see:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"/docs/dev-docs/events/#ready"},"children":["Framepay.on('ready', ...)"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"/docs/dev-docs/framepay-global-reference/#card-namespace"},"children":["Framepay.card.mount(...)"]}]}]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"handle-the-form-submit-event","heading":"Handle the form submit event"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Listen for the form submit event to determine when the user is ready to make the payment."]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"create-a-payment-token","heading":"Create a payment token"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To send the form data to the FramePay library, call ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Framepay.createToken()"]},"."]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["If the collected form data is valid, the library returns a successful result with a new payment token."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["If the collected form data is not valid, the library returns an error explaining why."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For more information, see ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"/docs/dev-docs/framepay-global-reference/#framepaycreatetoken"},"children":["Framepay.createToken(form)"]},"."]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"send-token-to-server","heading":"Send token to server"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When the FramePay library returns the payment token, you can complete the purchase by making a request to the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST /create-transaction"]}," endpoint."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Pass the token as part of the request payload, together with other properties."]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"handle-the-api-response","heading":"Handle the API response"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If no error occurs, inform your customer that the payment is successful."," ","This example redirects the customer to a thank you (success) page, or to an ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["approvalUrl"]}," if it exists."]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"handle-errors-and-button-state","heading":"Handle errors and button state"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Add error handling for issues that may occur during payment processing, and manage the submit button state to prevent multiple submissions."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"step-5-view-the-checkout-page","__idx":5},"children":["Step 5: View the checkout page"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This section describes how to view the checkout page in a web browser."]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"run-the-example","heading":"Run the example"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Run ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["server.js"]},". When the server is running, open a browser and visit ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["http://localhost:3000"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For more information, see ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"/docs/dev-docs/end-to-end-framepay-example#prerequisites"},"children":["Prerequisites"]},"."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"node server.js\n","lang":"bash"},"children":[]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"related-topics","__idx":6},"children":["Related topics"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"/docs/dev-docs/framepay-configuration-reference/"},"children":["FramePay configuration reference"]}]}]}]}]},"headings":[{"value":"End-to-end FramePay integration","id":"end-to-end-framepay-integration","depth":1},{"value":"Step 1: Set up the server","id":"step-1-set-up-the-server","depth":2},{"value":"Step 2: Create a transaction","id":"step-2-create-a-transaction","depth":2},{"value":"Step 3: Create a checkout page","id":"step-3-create-a-checkout-page","depth":2},{"value":"Step 4: Set up client-side script","id":"step-4-set-up-client-side-script","depth":2},{"value":"Step 5: View the checkout page","id":"step-5-view-the-checkout-page","depth":2},{"value":"Related topics","id":"related-topics","depth":2}],"frontmatter":{"seo":{"title":"End-to-end FramePay integration","description":"Learn how to integrate the FramePay library and use a tokenized payment data to complete a purchase transaction.","keywords":"Developer docs, FramePay","lang":"en-US"},"excludeFromSearch":true,"markdown":{"toc":{"hide":true}},"footer":{"hide":true}},"lastModified":"2026-03-24T10:16:15.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/docs/dev-docs/end-to-end-framepay-example","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}