Skip to main content

Payments in an iframe (Iframe SDK)

Iframe mode lets you embed a card payment form (manual entry) and Apple Pay and Google Pay buttons directly on your website, without redirecting the customer to an external payment gateway.

Benefits:

  • No redirect - the customer stays on your website
  • Full control over UX - the form or button is embedded in your layout
  • A few lines of code - quick integration through the JavaScript SDK
  • Security - card data is encrypted with RSA inside the iframe, and the merchant never handles it
No PCI DSS certification required

Iframe integration does not require PCI DSS certification. Card data is entered and encrypted exclusively inside the dpay iframe and never reaches your server. If you need full control over the form and process card data in your own infrastructure, see the Server-to-Server (S2S) integration. That option requires PCI DSS certification.

Supported methods

MethodDescriptionmethod value
Card (manual entry)Complete form: cardholder details, card number, expiry date, and CVCCARD
Card (inline fields)Card fields only (number, expiry date, and CVC), embedded in your formCARD_INLINE
Apple PayApple Pay buttonAPPLE_PAY
Google PayGoogle Pay buttonGOOGLE_PAY

How it works

POST/api/v1_0/cards/payment/{transactionId}/pay/card-otpContract for the card payment performed by the iframe SDK.Full contract in the API Reference

Quick start

Step 1: Register the payment

Register the transaction through the standard API:

curl -X POST https://api-payments.dpay.pl/api/v1_0/payments/register \
-H "Content-Type: application/json" \
-d '{
"transactionType": "transfers",
"service": "abc123",
"value": "49.99",
"url_success": "https://myshop.example/success",
"url_fail": "https://myshop.example/error",
"url_ipn": "https://myshop.example/api/ipn",
"checksum": "..."
}'

Save the transactionId from the response.

Step 2: Add the SDK to your page

<script src="https://gateway.dpay.pl/sdk/dpay-iframe-sdk.js"></script>
Sandbox environment

For the test environment, use https://gateway.snd.dpay.pl/sdk/dpay-iframe-sdk.js.

Step 3: Check method availability (optional)

For Apple Pay and Google Pay, it is worth checking whether the method is available on the customer's device:

if (DPayIframeSDK.isApplePayAvailable()) {
// Show the Apple Pay button
}

if (DPayIframeSDK.isGooglePayAvailable()) {
// Show the Google Pay button
}

Apple Pay availability:

  • iOS, macOS, Windows, Linux - available
  • Android - unavailable

Google Pay availability:

  • Android, Desktop, iOS (Chrome/Edge) - available
  • iOS Safari - unavailable

Step 4: Initialize the SDK

const sdk = new DPayIframeSDK({
transactionId: 'your-transaction-id',
method: 'CARD', // or 'CARD_INLINE', 'APPLE_PAY', 'GOOGLE_PAY'
containerId: 'payment-container',
environment: 'production',

onIframeReady: (data) => {
console.log('Iframe ready', data);
},
onPaymentSuccess: (data) => {
console.log('Payment successful!', data);
window.location.href = '/success';
},
onPaymentError: (data) => {
console.error('Payment error:', data.error);
},
});

sdk.init();

SDK configuration

Required parameters

ParameterTypeDescription
transactionIdstringTransaction UUID from Step 1
methodstringPayment method: CARD, CARD_INLINE, APPLE_PAY, or GOOGLE_PAY
containerId or containerstring / HTMLElementDOM element ID or a reference to the element where the iframe will be embedded

Optional parameters

ParameterTypeDefaultDescription
localestring'pl'Form language
environmentstring'production'Environment: 'production' or 'sandbox'
baseUrlstringautomaticGateway base URL (derived from environment)
iframeStylesobject{}Custom CSS styles for the iframe
timeoutnumber300000Timeout in milliseconds (5 minutes by default)
debugbooleanfalseDebug logging in the browser console
autoResizebooleantrueAutomatically adjust the iframe height to its content
Environment

The default environment is 'production': omitting environment sends the SDK to the production gateway. For testing, explicitly set environment: 'sandbox'. To keep the configuration clear, we recommend always specifying environment.

CARD-specific parameters

ParameterTypeDefaultDescription
threeDsModestring'iframe'3D Secure mode: 'iframe' (inside the frame) or 'redirect' (redirect)
firstNamestring''Cardholder's first name (pre-fill)
lastNamestring''Cardholder's last name (pre-fill)
emailstring''Cardholder's email address (pre-fill)

CARD_INLINE-specific parameters

ParameterTypeDefaultDescription
threeDsModestring'modal'3D Secure mode: 'modal' (a modal overlay over the page) or 'redirect' (redirect)
layoutstring'stacked'Field layout: 'stacked' (one below another) or 'single-row' (one row)
showErrorsbooleanfalseWhether the iframe displays field validation messages; when false, handle them in onValidationError
labelsbooleanfalseWhether the iframe displays field labels
fieldStylesobject{}CSS styles for card fields (passed to the iframe)

Callbacks

CallbackParametersDescription
onIframeReady{ transactionId, method }Iframe loaded and ready
onPaymentStarted{ transactionId, method }The user started the payment
onPaymentSuccess{ transactionId, status }Payment completed successfully
onPaymentError{ transactionId, error, code? }Payment error
onPaymentCancelled{ transactionId }The user cancelled the payment
on3dsRedirect{ ... }3D Secure redirect (threeDsMode: 'redirect')
onIframeError{ error }Iframe loading error
onIframeResize{ height }Iframe size change (handled automatically when autoResize: true)
onFieldChange{ field, ... }Card field state change (CARD_INLINE only)
onValidationError{ fields: [{ field, error }] }Field validation errors (CARD_INLINE only)

SDK methods

init()

Initializes the SDK, creates an iframe, and renders the form or button in the container.

sdk.init();

destroy()

Removes the iframe and clears event listeners. Call it when unmounting the component.

sdk.destroy();

reload()

Reloads the iframe, for example after a configuration change.

sdk.reload();

getStatus()

Returns the current SDK status.

const status = sdk.getStatus();
// {
// status: 'idle' | 'loading' | 'ready' | 'processing' | 'success' | 'error',
// isInitialized: boolean,
// transactionId: string,
// method: string
// }

sendMessage(message)

Sends a message to the iframe through postMessage.

sdk.sendMessage({ type: 'custom:action', data: { ... } });

submit(personalData) (CARD_INLINE only)

Submits the payment with cardholder data collected in your form. The required fields are firstName, lastName, email, and acceptTerms. Missing fields are reported through onValidationError without submitting the payment.

sdk.submit({
firstName: 'John',
lastName: 'Doe',
email: 'john@example.com',
acceptTerms: true,
});

focus(field) (CARD_INLINE only)

Focuses the selected card field: 'ccn' (number), 'expiry' (expiry date), or 'cvc'.

sdk.focus('ccn');

clear() (CARD_INLINE only)

Clears the values of the card fields in the iframe.

sdk.clear();

Events (postMessage)

The SDK communicates with the iframe through window.postMessage. Events are handled automatically and passed to the appropriate callbacks.

Event typeCallbackDescription
iframe:readyonIframeReadyIframe loaded and ready
iframe:resizeonIframeResizeIframe content size changed
iframe:erroronIframeErrorIframe error
payment:startedonPaymentStartedPayment started
payment:successonPaymentSuccessPayment successful
payment:erroronPaymentErrorPayment error
payment:cancelledonPaymentCancelledPayment cancelled
payment:3ds-redirecton3dsRedirect3DS redirect
payment:3ds-modal(handled internally)Open the 3DS modal overlay (CARD_INLINE with threeDsMode: 'modal')
inline:field-changeonFieldChangeCard field state changed (CARD_INLINE)
inline:validation-erroronValidationErrorField validation errors (CARD_INLINE)

Integration examples

<!DOCTYPE html>
<html>
<head>
<title>Payment</title>
</head>
<body>
<div id="payment-container"></div>

<script src="https://gateway.dpay.pl/sdk/dpay-iframe-sdk.js"></script>
<script>
const sdk = new DPayIframeSDK({
transactionId: 'abc-123-def',
method: 'CARD',
containerId: 'payment-container',

onPaymentSuccess: (data) => {
window.location.href = '/success';
},
onPaymentError: (data) => {
alert('Payment error: ' + data.error);
},
});

sdk.init();
</script>
</body>
</html>

CARD integration (manual entry)

The CARD method displays a complete card payment form in the iframe. The form collects:

  • Cardholder's first and last name
  • Email address
  • Card number
  • Expiry date
  • CVC/CVV code
Card data security

Card data is encrypted with RSA inside the iframe. Your website never has access to raw card data. You do not need PCI DSS certification.

Pre-filling cardholder data

You can pre-fill the cardholder's details if you already know them, for example from the checkout process:

const sdk = new DPayIframeSDK({
transactionId: 'abc-123-def',
method: 'CARD',
containerId: 'payment-container',
firstName: 'John',
lastName: 'Doe',
email: 'john@example.com',

onPaymentSuccess: (data) => {
window.location.href = '/success';
},
});

sdk.init();

Dynamic Currency Conversion (DCC)

If the cardholder pays with a foreign card and DCC is enabled for your service, the iframe SDK handles the entire process internally. The customer sees the currency selection screen inside the iframe, and after they make a decision the SDK continues the flow to payment:success or a 3DS challenge. The merchant does not need to handle any additional callbacks or views.

For the complete API contract and UI requirements when integrating without an iframe (S2S), see Dynamic Currency Conversion (DCC).

Handling 3D Secure

The threeDsMode parameter controls how 3D Secure verification is handled:

  • 'iframe' (default) - 3DS verification takes place inside the iframe, and the customer stays on your website
  • 'redirect' - the customer is redirected to the bank's website and then returns to url_success / url_fail
const sdk = new DPayIframeSDK({
transactionId: 'abc-123-def',
method: 'CARD',
containerId: 'payment-container',
threeDsMode: 'iframe', // or 'redirect'

on3dsRedirect: (data) => {
// Called only when threeDsMode is 'redirect'
console.log('3DS redirect:', data);
},
onPaymentSuccess: (data) => {
window.location.href = '/success';
},
});

sdk.init();

CARD_INLINE integration (card fields in your form)

The CARD_INLINE method embeds only the card fields (number, expiry date, and CVC) in an iframe. You build the rest of the form (cardholder data, consents, and the payment button) on your side and submit the payment through sdk.submit(...). Card data still never leaves the dpay iframe, so PCI DSS certification is not required.

const sdk = new DPayIframeSDK({
transactionId: 'abc-123-def',
method: 'CARD_INLINE',
containerId: 'card-fields',
environment: 'production',
threeDsMode: 'modal', // 'modal' (overlay) or 'redirect'
layout: 'single-row', // 'stacked' or 'single-row'
showErrors: false, // handle validation messages yourself
labels: false, // no field labels inside the iframe
fieldStyles: { // card field styling
fontSize: '16px',
},

onFieldChange: (data) => {
// For example, update the state of the "Pay" button
},
onValidationError: (data) => {
data.fields.forEach(({ field, error }) => {
// Show the error next to the corresponding form field
});
},
onPaymentSuccess: (data) => {
window.location.href = '/success';
},
onPaymentError: (data) => {
console.error('Payment error:', data.error);
},
});

sdk.init();

// After the customer clicks your "Pay" button:
document.getElementById('pay-button').addEventListener('click', () => {
sdk.submit({
firstName: document.getElementById('first-name').value,
lastName: document.getElementById('last-name').value,
email: document.getElementById('email').value,
acceptTerms: document.getElementById('terms').checked,
});
});

With threeDsMode: 'modal', the 3D Secure challenge opens automatically in a modal overlay above your page. If the customer closes the overlay, onPaymentCancelled is called. With threeDsMode: 'redirect', the customer goes to the bank's website and returns to url_success / url_fail.

Security

Content Security Policy (CSP)

Add the dpay gateway domain to the frame-src directive:

<meta http-equiv="Content-Security-Policy"
content="frame-src https://gateway.dpay.pl https://gateway.snd.dpay.pl;">

HTTPS

The iframe SDK requires your website to use HTTPS. Apple Pay and Google Pay do not work on HTTP pages.

iframe sandbox attributes

The SDK automatically applies these iframe security attributes:

sandbox="allow-scripts allow-same-origin allow-forms allow-popups"
allow="payment"

Filtering postMessage messages

The SDK verifies incoming postMessage messages on two levels: by source (it processes only messages from the window of the iframe it embedded, using event.source) and by origin (event.origin must match the gateway origin derived from baseUrl; messages from other origins are rejected). Messages sent to the iframe use the gateway's specific targetOrigin, not '*'. If your application also listens for message events directly alongside the SDK, verify event.origin against the dpay gateway address (https://gateway.dpay.pl or https://gateway.snd.dpay.pl) before trusting the message contents.

Troubleshooting

The iframe does not load

  • Check the CSP headers: frame-src must include the dpay gateway domain
  • Verify baseUrl / environment in the SDK configuration
  • Check the Network tab in DevTools

The Apple Pay / Google Pay button does not appear

  • Use DPayIframeSDK.isApplePayAvailable() / isGooglePayAvailable() to check availability on the device
  • Check that the transaction has the correct payment channel
  • Enable debug: true and check the browser console

The payment does not start

  • Make sure the page uses HTTPS
  • Check that transactionId is valid and that the transaction has not expired
  • Use the onIframeError callback for diagnostics

The CARD form does not display correctly

  • Check that the container is wide enough (at least 320px)
  • With autoResize: false, set the iframe height manually (at least 580px for the CARD form)
  • Do not set overflow: hidden on the container, as it may crop 3DS modal windows

Testing in sandbox mode

When test mode is enabled for the service, the simulation scenario is selected by the card number entered in the form inside the iframe. Enter one of the test numbers exactly as a customer would enter a real card:

Card numberScenario
4111111111111111Visa - payment completed successfully
5555555555554444Mastercard - payment completed successfully
4000000000000002Visa - declined
4000000000000069Visa - expired card
4000000000000127Visa - insufficient funds

The full list of test numbers and details is available on the Test environment page.