Płatności w iframe (Iframe SDK)
Tryb iframe pozwala osadzić formularz płatności kartowej (manual entry) oraz przyciski Apple Pay i Google Pay bezpośrednio na Twojej stronie - bez przekierowania do zewnętrznej bramki płatności.
Zalety:
- Brak przekierowania - klient nie opuszcza Twojej strony
- Pełna kontrola nad UX - formularz/przycisk wbudowany w Twój layout
- Kilka linijek kodu - szybka integracja przez SDK JavaScript
- Bezpieczeństwo - dane kart szyfrowane RSA po stronie iframe, merchant nie dotyka danych kart
Integracja przez iframe nie wymaga posiadania certyfikacji PCI DSS - dane kart są wprowadzane i szyfrowane wyłącznie po stronie iframe dpay i nigdy nie trafiają na Twój serwer. Jeśli potrzebujesz pełnej kontroli nad formularzem i przetwarzasz dane kart po swojej stronie, zobacz integrację Server-to-Server (S2S) - ta opcja wymaga certyfikacji PCI DSS.
Obsługiwane metody
| Metoda | Opis | Wartość method |
|---|---|---|
| Karta (manual entry) | Pełny formularz: dane posiadacza, numer karty, data ważności, CVC | CARD |
| Karta (pola inline) | Same pola karty (numer, data, CVC) osadzone w Twoim formularzu | CARD_INLINE |
| Apple Pay | Przycisk Apple Pay | APPLE_PAY |
| Google Pay | Przycisk Google Pay | GOOGLE_PAY |
Schemat działania
/api/v1_0/cards/payment/{transactionId}/pay/card-otpKontrakt płatności kartowej, którą realizuje iframe SDK.Pełny kontrakt w API Reference
Szybki start
Krok 1: Rejestracja płatności
Zarejestruj transakcję standardowo przez 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://mojsklep.pl/sukces",
"url_fail": "https://mojsklep.pl/blad",
"url_ipn": "https://mojsklep.pl/api/ipn",
"checksum": "..."
}'
Zapisz transactionId z odpowiedzi.
Krok 2: Dodanie SDK na stronę
<script src="https://gateway.dpay.pl/sdk/dpay-iframe-sdk.js"></script>
Dla środowiska testowego użyj: https://gateway.snd.dpay.pl/sdk/dpay-iframe-sdk.js
Krok 3: Sprawdzenie dostępności metody (opcjonalne)
Dla Apple Pay i Google Pay warto sprawdzić, czy dana metoda jest dostępna na urządzeniu klienta:
if (DPayIframeSDK.isApplePayAvailable()) {
// Pokaż przycisk Apple Pay
}
if (DPayIframeSDK.isGooglePayAvailable()) {
// Pokaż przycisk Google Pay
}
Dostępność Apple Pay:
- iOS, macOS, Windows, Linux - dostępny
- Android - niedostępny
Dostępność Google Pay:
- Android, Desktop, iOS (Chrome/Edge) - dostępny
- iOS Safari - niedostępny
Krok 4: Inicjalizacja SDK
const sdk = new DPayIframeSDK({
transactionId: 'your-transaction-id',
method: 'CARD', // lub 'CARD_INLINE', 'APPLE_PAY', 'GOOGLE_PAY'
containerId: 'payment-container',
environment: 'production',
onIframeReady: (data) => {
console.log('Iframe gotowy', data);
},
onPaymentSuccess: (data) => {
console.log('Płatność udana!', data);
window.location.href = '/sukces';
},
onPaymentError: (data) => {
console.error('Błąd płatności:', data.error);
},
});
sdk.init();
Konfiguracja SDK
Parametry wymagane
| Parametr | Typ | Opis |
|---|---|---|
transactionId | string | UUID transakcji z Kroku 1 |
method | string | Metoda płatności: CARD, CARD_INLINE, APPLE_PAY lub GOOGLE_PAY |
containerId lub container | string / HTMLElement | ID elementu DOM lub referencja do elementu, w którym zostanie osadzony iframe |
Parametry opcjonalne
| Parametr | Typ | Domyślnie | Opis |
|---|---|---|---|
locale | string | 'pl' | Język formularza |
environment | string | 'production' | Środowisko: 'production' lub 'sandbox' |
baseUrl | string | automatyczny | URL bazowy bramki (wyliczany na podstawie environment) |
iframeStyles | object | {} | Niestandardowe style CSS dla iframe |
timeout | number | 300000 | Timeout w milisekundach (domyślnie 5 min) |
debug | boolean | false | Logowanie debugowe w konsoli przeglądarki |
autoResize | boolean | true | Automatyczne dopasowanie wysokości iframe do zawartości |
Domyślnym środowiskiem jest 'production' - pominięcie parametru environment kieruje SDK na bramkę produkcyjną. Do testów ustaw jawnie environment: 'sandbox'. Dla czytelności konfiguracji zalecamy podawać environment zawsze wprost.
Parametry specyficzne dla CARD
| Parametr | Typ | Domyślnie | Opis |
|---|---|---|---|
threeDsMode | string | 'iframe' | Tryb 3D Secure: 'iframe' (w ramce) lub 'redirect' (przekierowanie) |
firstName | string | '' | Imię posiadacza karty (pre-fill) |
lastName | string | '' | Nazwisko posiadacza karty (pre-fill) |
email | string | '' | Email posiadacza karty (pre-fill) |
Parametry specyficzne dla CARD_INLINE
| Parametr | Typ | Domyślnie | Opis |
|---|---|---|---|
threeDsMode | string | 'modal' | Tryb 3D Secure: 'modal' (nakładka modalna nad stroną) lub 'redirect' (przekierowanie) |
layout | string | 'stacked' | Układ pól: 'stacked' (jedno pod drugim) lub 'single-row' (w jednym wierszu) |
showErrors | boolean | false | Czy iframe ma wyświetlać komunikaty walidacji pól; przy false obsłuż je w onValidationError |
labels | boolean | false | Czy iframe ma wyświetlać etykiety pól |
fieldStyles | object | {} | Style CSS pól karty (przekazywane do iframe) |
Callbacki
| Callback | Parametry | Opis |
|---|---|---|
onIframeReady | { transactionId, method } | Iframe załadowany i gotowy |
onPaymentStarted | { transactionId, method } | Użytkownik rozpoczął płatność |
onPaymentSuccess | { transactionId, status } | Płatność zakończona sukcesem |
onPaymentError | { transactionId, error, code? } | Błąd płatności |
onPaymentCancelled | { transactionId } | Użytkownik anulował płatność |
on3dsRedirect | { ... } | Przekierowanie 3D Secure (tryb threeDsMode: 'redirect') |
onIframeError | { error } | Błąd ładowania iframe |
onIframeResize | { height } | Zmiana rozmiaru iframe (przy autoResize: true obsługiwane automatycznie) |
onFieldChange | { field, ... } | Zmiana stanu pola karty (tylko CARD_INLINE) |
onValidationError | { fields: [{ field, error }] } | Błędy walidacji pól (tylko CARD_INLINE) |
Metody SDK
init()
Inicjalizuje SDK, tworzy iframe i renderuje formularz/przycisk w kontenerze.
sdk.init();
destroy()
Usuwa iframe i czyści event listenery. Wywołaj przy odmontowaniu komponentu.
sdk.destroy();
reload()
Przeładowuje iframe (np. po zmianie konfiguracji).
sdk.reload();
getStatus()
Zwraca aktualny status SDK.
const status = sdk.getStatus();
// {
// status: 'idle' | 'loading' | 'ready' | 'processing' | 'success' | 'error',
// isInitialized: boolean,
// transactionId: string,
// method: string
// }
sendMessage(message)
Wysyła wiadomość do iframe przez postMessage.
sdk.sendMessage({ type: 'custom:action', data: { ... } });
submit(personalData) (tylko CARD_INLINE)
Wysyła płatność z danymi posiadacza zebranymi w Twoim formularzu. Wymagane pola: firstName, lastName, email, acceptTerms - braki zgłaszane są przez onValidationError bez wysyłki.
sdk.submit({
firstName: 'Jan',
lastName: 'Kowalski',
email: 'jan@example.com',
acceptTerms: true,
});
focus(field) (tylko CARD_INLINE)
Ustawia fokus na wybranym polu karty: 'ccn' (numer), 'expiry' (data ważności) lub 'cvc'.
sdk.focus('ccn');
clear() (tylko CARD_INLINE)
Czyści wartości pól karty w iframe.
sdk.clear();
Eventy (postMessage)
SDK komunikuje się z iframe przez window.postMessage. Eventy są obsługiwane automatycznie i przekazywane do odpowiednich callbacków.
| Typ eventu | Callback | Opis |
|---|---|---|
iframe:ready | onIframeReady | Iframe załadowany i gotowy |
iframe:resize | onIframeResize | Zmiana rozmiaru zawartości iframe |
iframe:error | onIframeError | Błąd iframe |
payment:started | onPaymentStarted | Rozpoczęcie płatności |
payment:success | onPaymentSuccess | Płatność udana |
payment:error | onPaymentError | Błąd płatności |
payment:cancelled | onPaymentCancelled | Anulowanie płatności |
payment:3ds-redirect | on3dsRedirect | Przekierowanie 3DS |
payment:3ds-modal | (obsługiwany wewnętrznie) | Otwarcie modalnej nakładki 3DS (CARD_INLINE z threeDsMode: 'modal') |
inline:field-change | onFieldChange | Zmiana stanu pola karty (CARD_INLINE) |
inline:validation-error | onValidationError | Błędy walidacji pól (CARD_INLINE) |
Przykłady integracji
- Vanilla JS
- React
- Vue
<!DOCTYPE html>
<html>
<head>
<title>Płatność</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 = '/sukces';
},
onPaymentError: (data) => {
alert('Błąd płatności: ' + data.error);
},
});
sdk.init();
</script>
</body>
</html>
import { useEffect, useRef } from 'react';
function PaymentIframe({ transactionId, method = 'CARD' }) {
const containerRef = useRef(null);
const sdkRef = useRef(null);
useEffect(() => {
const sdk = new window.DPayIframeSDK({
transactionId,
method,
container: containerRef.current,
onPaymentSuccess: (data) => {
console.log('Płatność udana:', data);
},
onPaymentError: (data) => {
console.error('Błąd:', data.error);
},
});
sdk.init();
sdkRef.current = sdk;
return () => sdk.destroy();
}, [transactionId, method]);
return <div ref={containerRef} />;
}
<template>
<div ref="paymentContainer"></div>
</template>
<script>
export default {
props: ['transactionId', 'method'],
mounted() {
this.sdk = new window.DPayIframeSDK({
transactionId: this.transactionId,
method: this.method || 'CARD',
container: this.$refs.paymentContainer,
onPaymentSuccess: (data) => {
this.$emit('success', data);
},
onPaymentError: (data) => {
this.$emit('error', data);
},
});
this.sdk.init();
},
beforeUnmount() {
this.sdk?.destroy();
},
};
</script>
Integracja CARD (manual entry)
Metoda CARD wyświetla pełny formularz płatności kartowej w iframe. Formularz zbiera:
- Imię i nazwisko posiadacza karty
- Adres email
- Numer karty
- Data ważności
- Kod CVC/CVV
Dane karty są szyfrowane RSA po stronie iframe - Twoja strona nigdy nie ma dostępu do surowych danych kart. Nie musisz posiadać certyfikacji PCI DSS.
Pre-fill danych posiadacza
Możesz wstępnie wypełnić dane posiadacza karty, jeśli już je znasz (np. z procesu zamówienia):
const sdk = new DPayIframeSDK({
transactionId: 'abc-123-def',
method: 'CARD',
containerId: 'payment-container',
firstName: 'Jan',
lastName: 'Kowalski',
email: 'jan@example.com',
onPaymentSuccess: (data) => {
window.location.href = '/sukces';
},
});
sdk.init();
Dynamic Currency Conversion (DCC)
Jeśli posiadacz karty płaci kartą zagraniczną, a Twój serwis ma aktywne DCC, iframe SDK obsługuje całość po swojej stronie - klient widzi ekran wyboru waluty wewnątrz ramki, a po podjęciu decyzji SDK kontynuuje flow do payment:success lub challenge 3DS. Merchant nie musi obsługiwać dodatkowych callbacków ani widoków.
Pełen opis kontraktu API i wymagań UI dla integracji bez iframe (S2S): Dynamic Currency Conversion (DCC).
Obsługa 3D Secure
Parametr threeDsMode kontroluje sposób obsługi weryfikacji 3D Secure:
'iframe'(domyślny) - weryfikacja 3DS odbywa się wewnątrz iframe, klient nie opuszcza strony'redirect'- klient zostaje przekierowany na stronę banku, po czym wraca naurl_success/url_fail
const sdk = new DPayIframeSDK({
transactionId: 'abc-123-def',
method: 'CARD',
containerId: 'payment-container',
threeDsMode: 'iframe', // lub 'redirect'
on3dsRedirect: (data) => {
// Wywoływane tylko przy threeDsMode: 'redirect'
console.log('Przekierowanie 3DS:', data);
},
onPaymentSuccess: (data) => {
window.location.href = '/sukces';
},
});
sdk.init();
Integracja CARD_INLINE (pola karty w Twoim formularzu)
Metoda CARD_INLINE osadza w iframe wyłącznie pola karty (numer, data ważności, CVC) - resztę formularza (dane posiadacza, zgody, przycisk płatności) budujesz po swojej stronie i wysyłasz płatność metodą sdk.submit(...). Dane karty nadal nie opuszczają iframe dpay, więc certyfikacja PCI DSS nie jest wymagana.
const sdk = new DPayIframeSDK({
transactionId: 'abc-123-def',
method: 'CARD_INLINE',
containerId: 'card-fields',
environment: 'production',
threeDsMode: 'modal', // 'modal' (nakładka) lub 'redirect'
layout: 'single-row', // 'stacked' lub 'single-row'
showErrors: false, // komunikaty walidacji obsluzysz sam
labels: false, // bez etykiet pol w iframe
fieldStyles: { // stylowanie pol karty
fontSize: '16px',
},
onFieldChange: (data) => {
// np. aktualizacja stanu przycisku "Zaplac"
},
onValidationError: (data) => {
data.fields.forEach(({ field, error }) => {
// pokaz blad przy polu formularza
});
},
onPaymentSuccess: (data) => {
window.location.href = '/sukces';
},
onPaymentError: (data) => {
console.error('Blad platnosci:', data.error);
},
});
sdk.init();
// Po kliknieciu Twojego przycisku "Zaplac":
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,
});
});
Przy threeDsMode: 'modal' challenge 3D Secure otwiera się automatycznie w modalnej nakładce nad Twoją stroną - zamknięcie nakładki przez klienta wywołuje onPaymentCancelled. Przy threeDsMode: 'redirect' klient przechodzi na stronę banku i wraca na url_success / url_fail.
Bezpieczeństwo
Content Security Policy (CSP)
Dodaj domenę bramki dpay do dyrektywy frame-src:
<meta http-equiv="Content-Security-Policy"
content="frame-src https://gateway.dpay.pl https://gateway.snd.dpay.pl;">
HTTPS
Iframe SDK wymaga, aby Twoja strona działała na HTTPS. Apple Pay i Google Pay nie działają na stronach HTTP.
Atrybuty sandbox iframe
SDK automatycznie ustawia atrybuty bezpieczeństwa iframe:
sandbox="allow-scripts allow-same-origin allow-forms allow-popups"
allow="payment"
Filtrowanie wiadomości postMessage
SDK weryfikuje przychodzące wiadomości postMessage dwuwarstwowo: po źródle (przetwarza wyłącznie wiadomości pochodzące z okna osadzonego przez siebie iframe, event.source) oraz po pochodzeniu (event.origin musi zgadzać się z origin bramki wyliczonym z baseUrl - wiadomości z innego origin są odrzucane). Wiadomości do iframe wysyłane są z konkretnym targetOrigin bramki, nie '*'. Jeśli mimo to w swojej aplikacji nasłuchujesz zdarzeń message samodzielnie (obok SDK), również weryfikuj event.origin względem adresu bramki dpay (https://gateway.dpay.pl lub https://gateway.snd.dpay.pl), zanim zaufasz treści wiadomości.
Troubleshooting
Iframe nie ładuje się
- Sprawdź nagłówki CSP -
frame-srcmusi zawierać domenę bramki dpay - Zweryfikuj
baseUrl/environmentw konfiguracji SDK - Sprawdź zakładkę Network w DevTools
Przycisk Apple Pay / Google Pay nie wyświetla się
- Użyj
DPayIframeSDK.isApplePayAvailable()/isGooglePayAvailable()aby sprawdzić dostępność na danym urządzeniu - Sprawdź czy transakcja ma odpowiedni kanał płatności
- Włącz
debug: truei sprawdź konsolę przeglądarki
Płatność się nie rozpoczyna
- Upewnij się, że strona działa na HTTPS
- Sprawdź czy
transactionIdjest prawidłowy i transakcja nie wygasła - Użyj callbacku
onIframeErrordo diagnostyki
Formularz CARD nie wyświetla się poprawnie
- Sprawdź czy kontener ma wystarczającą szerokość (min. 320px)
- Przy
autoResize: falseręcznie ustaw wysokość iframe (min. 580px dla formularza CARD) - Nie ustawiaj
overflow: hiddenna kontenerze - może to obciąć modalne okna 3DS
Testowanie w trybie sandbox
Gdy serwis ma włączony tryb testowy, scenariusz symulacji wybierany jest po numerze karty wpisanym w formularzu w iframe - wpisz jeden z numerów testowych tak, jak klient wpisałby prawdziwą kartę:
| Numer karty | Scenariusz |
|---|---|
4111111111111111 | Visa - płatność zakończona sukcesem |
5555555555554444 | Mastercard - płatność zakończona sukcesem |
4000000000000002 | Visa - odmowa |
4000000000000069 | Visa - karta wygasła |
4000000000000127 | Visa - brak środków |
Pełna lista numerów testowych i szczegóły działania dostępne na stronie Środowisko testowe.