How to Set up your Embedded Payment Page

The Embedded Payment Page (EPP) lets you host Orbital’s checkout directly inside your website or application. Both EPP and HPP use the same underlying checkout flow. The difference is how customers access it:

  • HPP (Hosted Payment Page): Customers are redirected to an Orbital-hosted URL.
  • EPP (Embedded Payment Page): The same page is loaded in an iframe inside your site.
FeatureHPPEPP
Redirect required✅ Yes❌ No
Checkout hosted by Orbital
Runs inside your site/app

What is Orbital Widget ?

Orbital Widget is a JavaScript library that simplifies the process of embedding external pages within an iframe for seamless integration, removing the need for redirects. With a few lines of code, you can integrate the widget into your site and provide a smoother user experience. Below is a step-by-step example of how you can integrate it in a React project or in Vanilla JavaScript.

Step 1: Install the Orbital Widget package

First, you need to add the widget to your project. You can either install it as a package or include it via a CDN script tag.

A) Install with npm/yarn

Open your project's terminal and run one of the following commands:

npm install @payperform/widget
yarn add @payperform/widget

B) Install with CDN

Alternatively, you can include the widget via a CDN script tag in your HTML file:

<script src="https://widgets.getorbital.io/index-latest.js"></script>
<script src="https://widgets.getorbital.io/index-{version}.js"></script>
📘

Quick Links

  • Embedded Payment Page Package: You can download the EPP package from npm
  • GitHub Widget Repository: The widget's source code is available on GitHub

Step 2: Step 2: Add the Integration Code to Your Frontend

Next, add the widget to your frontend. The code below will add a container <div> and include the logic to fetch a signature and initialize the widget.

import React, { useEffect, useState, useRef } from 'react'
import { init } from '@payperform/widget'
import styles from './OrbitalWidget.module.scss'

const OrbitalWidget: React.FC = () => {
  const [signature, setSignature] = useState<string | null>(null)
  const orbitalRef = useRef<HTMLDivElement | null>(null)

  useEffect(() => {
    // Fetch signature from your backend server and set it here
    // Example: setSignature(response.signature);
    // Developer should replace this with their own server call to fetch signature
    setSignature('your-signature-from-backend')
  }, [])

  useEffect(() => {
    if (signature && orbitalRef.current) {
      orbitalRef.current.setAttribute('signature', signature)

      init({
        container: orbitalRef.current,
      })
    }
  }, [signature])

  return <div className={styles['iframe-container']} id="orbital" ref={orbitalRef}></div>
}

export default OrbitalWidget
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="Content-Security-Policy" content="frame-src 'self' https://hpp.getorbital.io/" />
    <title>Orbital Widget Example</title>
  </head>
  <body>
    <div id="orbital"></div>
    <script src="https://widgets.getorbital.io/index-latest.js"></script>
    <script>
      window.addEventListener('load', async () => {
        // Simulate fetching the signature from your backend
        const signature = 'your-signature-from-backend' // Replace with your own logic to get the signature

        const orbitalElement = document.getElementById('orbital')
        if (orbitalElement && signature) {
          orbitalElement.setAttribute('signature', signature)
        }

        if (typeof OrbitalWidget !== 'undefined' && typeof OrbitalWidget.init === 'function') {
          OrbitalWidget.init({
            container: 'orbital',
          })
        } else {
          console.error('OrbitalWidget was not loaded properly.')
        }
      })
    </script>
  </body>
</html>

Step 3: Customize with Properties

The init() method supports several options you can use to match the widget to your site’s design and user flow

PropertyTypeDescription
containerstring /string[] /HTMLElement / HTMLElement[]The container(s) where the widget will be initialized. Can be a single string, an array of strings, or a single HTMLElement or an array of HTMLElements.
mode'iframe-only' /'small-widgets'Defines the mode for the widget. If not provided, defaults to 'iframe-only'.
button.color'white-black' /'black-white' /'red-white' /'red-black' / 'blue-white'Button color schemes.
button.logoOnlybooleanIf true, will use the text-based logo.
button.widthstringThe width of the button (CSS units). Added to the style tag.
button.heightstringThe height of the button (CSS units). Added to the style tag.

See the Widget Reference for the full list of properties and advanced customization options.

Step 4: Add CSP to your Html

To allow your page to embed the Orbital iframe, you must add a Content-Security-Policy (CSP) meta tag to the head of your HTML file. This policy tells the browser that your site trusts and is permitted to load content from Orbital.

<meta http-equiv="Content-Security-Policy" content="frame-src 'self' [https://hpp.getorbital.io](https://hpp.getorbital.io)">

If you use other iframes aside from our package, ensure that it is also added to the content lists of allowed domains.

🚧

At this point the example uses a placeholder for signature. The widget won’t load correctly until you call the backend API to fetch valid signature. But you'll be able to see how the container render and how the integration behave.

Step 5: Fetch the signature from your backend

For security, the payment widget requires a unique signature to be initialized. This signature must be generated on your backend server using your secret API key. This prevents your key from being exposed in frontend code.

Here is an example of a secure endpoint using Node.js and Express that your frontend code from Step 2 can call.

First, install dependencies:

npm install express axios cors dotenv

Then create a file server.js:

require('dotenv').config()
const express = require('express')
const axios = require('axios')
const cors = require('cors')

const app = express()
app.use(cors())
app.use(express.json())

app.post('/generate-signature', async (req, res) => {
  try {
    const response = await axios.post(
      process.env.API_URL || 'https://hpp.getorbital.io/invoice/widgets',
      req.body,
      {
        headers: {
          'Content-Type': 'application/json',
          'x-api-key': process.env.API_KEY,
        },
      }
    )
    res.status(200).json(response.data)
  } catch (error) {
    res.status(500).json({
      message: 'Error sending request',
      error: error.response ? error.response.data : error.message,
    })
  }
})

const PORT = process.env.PORT || 3000
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`)
})

Create a .env file in the project root and set up the necessary environment variables in a .env file:

API_URL=https://hpp.getorbital.io/invoice/widgets
         
API_KEY=your_api_key_here

Start the server:

node server.js

Your frontend can now call POST /generate-signature to fetch a valid signature for the Orbital Widget.

Step 6: Test the Widget

Run your React app (or open your HTML file) at http://localhost:3000.

  • With a placeholder signature → you’ll see the container and iframe, but checkout won’t initialize.
  • With a real backend signature → the full Orbital checkout loads and your customers can complete payments.
📘

This server implementation is not part of the Orbital Widget library, but it provides a necessary backend for users to fetch the required signature.

Security Considerations

When implementing an embedded payment page:

  • Always use HTTPS to encrypt data in transit.
  • Implement proper Content Security Policy (CSP) headers.
  • Regularly update the Orbital Widget to the latest version.
  • Never store sensitive payment information on your servers.
  • Implement proper error handling to avoid exposing sensitive information.