Appearance
Référence SDK embed
Le SDK checkout Epayment ouvre un overlay iframe sur le portail intégrateur. Il ne contient aucun secret (sk_, clé API). Seul le client_secret de session transite du back intégrateur vers le navigateur.
Distribution
CDN (recommandé eGouv, SI legacy)
html
<script src="https://pay.example.gov/sdk/v1.js" async></script>URL versionnée par chemin : /sdk/v1.js sur l'origine checkout de votre environnement.
npm (React / Next)
bash
pnpm add @epayment/checkout-sdktypescript
import { EpaymentCheckout } from '@epayment/checkout-sdk';
EpaymentCheckout.open({
clientSecret: `${session.id}:${session.client_secret}`,
onComplete: ({ completionToken }) => acknowledge(completionToken),
});| Intégrateur | Canal recommandé |
|---|---|
| eGouv / e-Citizen | CDN script tag |
| SI legacy (PHP, JSP) | CDN |
| SI React / Next | npm ou CDN |
API publique EpaymentCheckout.open()
typescript
EpaymentCheckout.open({
clientSecret: string,
sessionId?: string,
onComplete: (payload: { completionToken: string }) => void,
onClose?: () => void,
locale?: string,
checkoutOrigin?: string,
layout?: 'compact' | 'large',
}): { close: () => void }Options
| Option | Requis | Description |
|---|---|---|
clientSecret | Oui | Composite {session_id}:{client_secret} ou secret seul avec sessionId |
sessionId | Conditionnel | Obligatoire si clientSecret ne contient que chs_secret_… |
onComplete | Oui | Appelé avec { completionToken } à l'état terminal |
onClose | Non | Overlay fermé (manuel ou auto après completion) |
locale | Non | Transmis à l'iframe (fr, …) |
checkoutOrigin | Non | Hôte checkout (défaut : origine du script) |
layout | Non | Disposition iframe : compact ou large (voir ci-dessous) |
Le handle retourné expose close() pour fermer l'overlay programmatiquement.
Layouts iframe
Deux dispositions fixes. Le SDK fixe la largeur de l'overlay ; l'iframe adapte le contenu (colonne unique ou résumé + paiement côte à côte).
layout | Largeur × hauteur mini | Contenu typique |
|---|---|---|
compact | 400 × 620 px | Colonne unique (mobile / viewport étroit) |
large | 760 × 560 px | Deux colonnes (desktop) |
Sélection par défaut (SDK) :
- largeur viewport ≥ 720 px →
large - sinon →
compact
Vous pouvez forcer le mode via layout: 'compact' ou layout: 'large'.
Repli responsive dans l'iframe : si layout=large mais le conteneur iframe est ≤ 559 px de large, le rendu bascule en compact sans changer l'URL.
Comportement overlay
- Backdrop semi-opaque, modal centré.
- Dimensions initiales selon
layout; hauteur ajustée sur événementresize(plancher = hauteur du layout). - Le modal reste ouvert après le
completion_tokenpour afficher la confirmation. Il se ferme quand le payeur clique sur Fermer, ou automatiquement au bout de 10 secondes. - Confirmation si fermeture pendant paiement en cours (
epayment.checkout.pending), y compris redirect acquéreur carte. - Piège focus (focus trap) et fermeture
Escape.
Construction de l'URL iframe
Le SDK construit :
text
{checkoutOrigin}/embed/{sessionId}?client_secret={secret}&parent_origin={encodeURIComponent(window.location.origin)}&layout={compact|large}&locale=fr| Query | Obligatoire | Rôle |
|---|---|---|
client_secret | Oui | Auth session embed (Bearer côté checkout) |
parent_origin | Oui | Origine du portail parent ; validée contre la liste d'origines autorisées |
layout | Non | compact ou large ; défaut effectif large si absent ou valeur inconnue |
locale | Non | Locale transmise par le SDK |
Ne construisez cette URL à la main que pour un diagnostic. En production, passez par EpaymentCheckout.open().
Protocole postMessage
Source fixe : epayment.checkout. Le SDK filtre event.origin === checkoutOrigin.
type | Payload | Comportement SDK |
|---|---|---|
epayment.checkout.ready | { height? } | Dimensionnement initial |
epayment.checkout.resize | { height } | Ajuste hauteur iframe |
epayment.checkout.pending | { pending: true } | Paiement en cours ; confirmation à la fermeture (MM, agence, carte) |
epayment.checkout.completion_token | { completion_token } | Appelle onComplete, fermeture auto |
epayment.checkout.closed | - | Ferme l'overlay |
epayment.checkout.external_checkout | { url } | Break-out : le parent doit ouvrir l'URL acquéreur (ex. window.location ou nouvel onglet) |
Exemple message iframe → parent :
json
{
"source": "epayment.checkout",
"type": "epayment.checkout.completion_token",
"payload": {
"completion_token": "cpt_..."
}
}Règles impératives :
targetOrigin= origine parent validée (jamais*)- Jamais
paid,status, ouorder_iddans postMessage - Le parent vérifie
event.originavant traitement
Paiement carte (CARD pending)
Lors d'un collect carte (offer_id: paddle) :
- l'iframe tente d'abord l'overlay acquéreur dans le frame (attribut
allow="payment") ; - si un redirect pleine page est nécessaire, l'iframe émet
epayment.checkout.external_checkoutavec{ "url": "https://..." }: le parent ouvre l'URL (ne jamais imbriquer la page acquéreur dans l'iframe) ; - pendant le paiement, l'iframe émet
epayment.checkout.pendingavec{ "pending": true }; - le SDK bloque la fermeture sans confirmation ;
- à la confirmation acquéreur, le flux reprend puis émet
completion_tokensi la session est payée.
Ne pas interpréter pending comme un paiement réussi. Toujours confirmer côté back via webhook ou verify-completion.
Intégration minimale
html
<script src="https://pay.example.gov/sdk/v1.js" async></script>
<script>
async function payer(clientSecret) {
EpaymentCheckout.open({
clientSecret,
// layout: 'large', // optionnel ; défaut selon la largeur viewport
onComplete: ({ completionToken }) => {
fetch('/api/paiements/acknowledge', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ completion_token: completionToken }),
});
},
});
}
</script>Le back intégrateur doit implémenter acknowledge via POST /checkout/sessions/verify-completion (voir Checkout embarqué).
Fallback nouvel onglet
Si l'iframe est bloquée (politique X-Frame-Options, CSP parent), le SDK propose d'ouvrir checkout_url (mode hosted) dans un nouvel onglet. Le parcours completion repose alors sur webhook ou polling GET /checkout/sessions?order_id=.