Appearance
Matrice des cas limites embed
Référence des comportements attendus lorsque le parcours embed ne suit pas le chemin nominal. Le principe directeur : le front intégrateur ne débloque jamais un dossier sur la seule base du postMessage.
Matrice
| Cas | Comportement attendu | Action intégrateur |
|---|---|---|
Front forge paid: true dans postMessage | Ignoré ; seul completion_token est émis | Toujours appeler verify-completion |
Webhook checkout.completed avant onComplete | Déblocage via webhook | acknowledge idempotent sur order_id |
onComplete avant webhook | Déblocage via verify-completion | Webhook traité en idempotent ensuite |
| Overlay fermé, paiement agence en cours | Pas de token immédiat | Attendre webhook ou polling status |
| Overlay fermé après voucher agence | Polling iframe arrêté ; encaissement ultérieur | Webhook ou GET ?order_id= |
client_secret sur session hosted | API retourne 401 | Créer session mode: embedded |
| Origines embed non configurées | 422 embed.origins_required à la création session | Configurer origines admin / régie |
parent_origin non listé | Iframe refuse le chargement | Ajouter origine exacte (schéma + hôte) |
layout absent ou inconnu | Rendu large (puis repli compact si conteneur ≤ 559 px) | Passer compact / large via le SDK si besoin |
| Viewport < 720 px | SDK ouvre en compact par défaut | Forcer layout: 'large' uniquement si le portail le justifie |
| Token expiré (> 10 min) | 410 checkout.completion_token_expired | Nouvelle session ou polling fallback |
| Token déjà consommé | 409 puis replay idempotent → 200 même corps | Traiter comme succès |
| Token inconnu | 404 checkout.completion_token_not_found | Rejeter ; investiguer fraude ou bug |
order_id verify ≠ dossier attendu | Rejeter côté back intégrateur | 403 métier |
paid: false après verify | Session terminale non payée (expirée, annulée) | Informer citoyen, proposer nouvelle session |
| iframe bloquée (X-Frame) | SDK propose hosted nouvel onglet | Webhook obligatoire pour ce parcours |
Double clic open() | Deux overlays possibles | Désactiver bouton pendant session |
Paiement MM en cours (pending) | Fermeture overlay demande confirmation | Laisser webhook finaliser si fermé |
| Paiement carte redirect en cours | epayment.checkout.pending actif | Ne pas débloquer ; attendre webhook ou verify-completion |
| Refus carte acquéreur | Session checkout reste open | Citoyen peut relancer paddle sur la même session |
| Timeout approbation carte | Session open, pas de checkout.failed | Nouvelle tentative carte ou autre offre |
| Overlay fermé pendant carte pending | Pas de token immédiat | Webhook checkout.completed ou polling GET ?order_id= |
Devise session XAF | Offre paddle absente | Créer session en devise carte si paiement carte requis |
| Session expirée en iframe | État terminal expired ; pas de token payé | Recréer session |
Clé plateforme sans tenant_id | 400 checkout.tenant_required | Toujours passer tenant_id (eGouv) |
| Réseau coupé pendant verify | Retry exponentiel côté back | Ne pas débloquer sans réponse API |
| Citoyen change d'onglet (mobile) | Overlay persiste ; polling voucher continue | Pas d'action spécifique |
| Montant session ≠ attente métier | Verify retourne amount dans metadata si fourni | Valider order_id + règles métier |
Priorité des chemins de confirmation
- Webhook HMAC
checkout.completed(file durable, at-least-once) POST /checkout/sessions/verify-completionavecsk_(fermeture synchrone post-embed)GET /checkout/sessions?order_id=avecsk_(fallback)
Idempotence déblocage
typescript
async function unlockDossierIdempotent(orderId: string, source: 'webhook' | 'verify' | 'poll') {
// Même order_id : second appel ne doit pas annuler le premier succès
await db.transaction(async (tx) => {
const row = await tx.dossier.findForUpdate(orderId);
if (row.status === 'paid') return;
await tx.dossier.markPaid(orderId, { source });
});
}Anti-patterns à éviter
| Anti-pattern | Risque |
|---|---|
Débloquer sur onComplete sans verify | Fraude front, token forgé |
Faire confiance à event.data.paid | Non émis par le SDK officiel |
Stocker client_secret en localStorage | Vol XSS |
Exposer sk_ au navigateur | Compromission compte ministry |
| Ignorer webhook car verify a réussi | Perte notification si verify rollback métier |