Skip to main content

Merchant Hosted

iFrame

Basic Integration

Description

Embed our payment page in an iframe on your website. The payer completes the payment without leaving your page.

The payment page detects that it is opened in an iframe and adapts its layout to it. Everything around the form — the container, its size, the way it is closed — is yours.

Integration Instructions

  1. Create the order with the Create Order endpoint and take the paymentLink from the response.
  2. Add an iframe with the paymentLink as its src and the allow attribute — see Browser Permissions. Size and position the iframe with your own CSS.
<iframe
id="payment-frame"
src="https://pay.example.com/?session-id=..."
allow="clipboard-write *; clipboard-read *; payment *; publickey-credentials-get *; otp-credentials *"
></iframe>

That is the whole integration: your own container — a modal, a window manager, your own close button — closes the iframe, and you learn the result through callbacks or Retrieve Order Details.

Do you need the snippet?

Basic integration. The payment page works entirely inside the iframe: it takes the payment and shows the result to the payer. It does not reach your page — it cannot close the iframe or tell your page how the payment ended. Everything outside the iframe is yours: how it is shown, how it is closed, and how your system learns the result.

With the snippet. The payment page gets a channel to your page and brings two things:

  • Closing from inside the payment page. The payer can close the payment page from within the form, without leaving it for your controls: the payment page asks your page, and you remove the iframe in the onClose callback.
  • The payment result on your page, right away. When the payment is accepted or declined, the payment page reports it to your page at the same moment the payer sees the final screen — you can close the iframe and show your own confirmation without waiting for the backend callback.

Browser Permissions

Add the allow attribute to the iframe — without it, the browser blocks these features for the embedded payment page:

PermissionWhat it enables
clipboard-writeCopy buttons on the payment page (order number, payment details)
clipboard-readPasting a code from an SMS or an authenticator app
paymentPayment Request API — Apple Pay and Google Pay
publickey-credentials-getWebAuthn and passkeys, used by 3-D Secure
otp-credentialsAutomatic SMS code fill (WebOTP)

Separate the permissions with semicolons. Add * after each permission so it also covers the acquirer and bank pages opened inside the frame; without * the permission applies to the payment page only.

Customization

Fields, colors, and more can be customized through technical support. Contact support to receive an alias code for the embedded payment form, and pass it in the alias property of paymentPageDesign when creating the order.

Snippet (Optional)

This part is optional. Skip it if your own container closes the iframe and the backend result is enough for you.

Connect the payment page to your page when you need one of these:

  • A close button inside the payment form. By design, some payment page layouts place the close button in the form header. The payment page cannot close your iframe by itself, so it asks your page to do it.
  • The payment result in your interface right away. When the payment reaches a final screen, the payment page reports accepted or declined, and your page can close the iframe and show its own confirmation without waiting for the backend callback.

The exchange runs over window.postMessage. The ready-made snippet handles it for you.

If you prefer to handle the messages yourself, see the Message Protocol.

Quick Start

  1. Download payment-page-snippet.js and add it to your page in one of two ways:
    • paste its contents into a <script> tag on your page, the same way analytics code is added;
    • or host the file on your side and load it with <script src>.
  2. Add the iframe as described above.
  3. Configure the snippet with the iframe and your callbacks:
<iframe
id="payment-frame"
src="https://pay.example.com/?session-id=..."
allow="clipboard-write *; clipboard-read *; payment *; publickey-credentials-get *; otp-credentials *"
></iframe>

<script>
/* contents of payment-page-snippet.js */
</script>
<script>
PaymentPage({
iframe: document.getElementById("payment-frame"),
onClose: function () {
document.getElementById("payment-frame").remove()
},
onPaymentEvent: function (e) {
if (e.event === "accepted") {
document.getElementById("payment-frame").remove()
/* show your own confirmation screen */
}
},
})()
</script>

Load the snippet before the payment page loads: the payment page waits 3 seconds for your page to connect. Without a connection it shows no close button and sends no events.

Pass only the callbacks you need. The close button appears only if you passed onClose, and payment events arrive only if you passed onPaymentEvent.

Options

PaymentPage(options) accepts:

OptionRequiredTypeDescription
iframeYesHTMLIFrameElementThe iframe with the payment page. Messages are accepted only from the origin of its src
onCloseNo(payload: { reason: "user" }) => voidCalled when the payer clicks the close button. Removing the iframe is up to you
onPaymentEventNo(payload: { event, final?, orderId, traceId? }) => voidCalled when the payment reaches a final screen
onLogNo(label, message) => voidLogs every message with a label: event for incoming, reply for automatic answers, send for your own calls
channelNostringMessage channel name. Do not set it unless support gives you a value

Callback Payloads

onClose receives the reason for the close request:

{ "reason": "user" }

onPaymentEvent receives the outcome:

{
"event": "accepted",
"orderId": 12345,
"traceId": "550e8400-e29b-41d4-a716-446655440000"
}
{
"event": "declined",
"final": true,
"orderId": 12345,
"traceId": "550e8400-e29b-41d4-a716-446655440000"
}
FieldDescription
eventaccepted or declined
finalPresent for declined only. true means the payment cannot be retried
orderIdNumeric identifier of the order
traceIdOptional correlation identifier; include it when contacting support about a payment

Use these events to update your interface only; confirm the final status on your backend through callbacks or Retrieve Order Details.

Advanced: Reopening the Payment Page

You need this section only if you open the payment page more than once on the same iframe without reloading your page — for example, a new order after a declined one.

PaymentPage(options) returns a create() function. In the Quick Start it is called immediately — PaymentPage({...})(). create() locks onto the origin of iframe.src at the moment it is called, so set iframe.src first. Each call to create() starts a session and returns:

  • destroy() — stops listening for messages and sets iframe.src to about:blank.
  • send(messageType, payload) — sends a message to the payment page. Reserved: the protocol currently defines no messages for you to send.

To open a new payment page on the same iframe:

  1. Call destroy() on the current session.
  2. Assign the new paymentLink to iframe.src.
  3. Call create() to start the new session.

Keep this order — otherwise events arrive twice or not at all.

<script>
const iframe = document.getElementById("payment-frame")

// Configure once
const create = PaymentPage({
iframe,
onClose: () => paymentPageSession.destroy(),
})

// Start a session
let paymentPageSession = create()

// Later, open a new session on the same iframe
function reopen(url) {
iframe.src = url // must come before create()
paymentPageSession = create()
}
</script>

PCI DSS Compliant

Description

For merchants compliant with PCI DSS.

Contact

For more information, contact support.