Appearance
Paiement agence en embed
En mode embed, le citoyen peut choisir le canal agence (paiement en espèces chez un agent connecté). Le voucher et la référence payment_ref s'affichent dans l'iframe ; l'encaissement physique survient hors du portail intégrateur.
Parcours citoyen
- Le citoyen ouvre l'overlay embed et sélectionne Payer en agence.
- L'iframe affiche le voucher avec
payment_refet les instructions. - Le citoyen peut fermer l'overlay et se rendre en agence (message explicite dans l'UI).
- L'agent encaisse via le portail régie (scan ou saisie
payment_ref). - La session passe à l'état
completed. - Le citoyen est notifié côté intégrateur via webhook ou polling.
Polling voucher dans l'iframe
Tant que l'overlay reste ouvert et que le canal agence est actif, l'iframe interroge le statut session avec backoff :
| Étape | Délai |
|---|---|
| 1 | 4 s |
| 2 | 15 s |
| 3 | 30 s |
| 4+ | 60 s (plafond) |
Dès détection de l'état terminal payé, l'iframe émet epayment.checkout.completion_token vers le parent SDK.
Overlay fermé avant encaissement
| Situation | Signal disponible |
|---|---|
| Overlay ouvert, agent encaisse | completion_token via postMessage |
| Overlay fermé, agent encaisse plus tard | Webhook checkout.completed |
| Overlay fermé, pas de webhook reçu | GET /checkout/sessions?order_id= (fallback) |
Le front intégrateur doit afficher un message du type : « Vous pouvez fermer cette fenêtre et vous rendre en agence avec votre référence. » Le déblocage métier ne doit pas dépendre de la fermeture de l'overlay.
Séquence complète
Implémentation back intégrateur
Si overlay reste ouvert
typescript
EpaymentCheckout.open({
clientSecret,
onComplete: async ({ completionToken }) => {
await acknowledge(orderId, completionToken);
},
});Si overlay fermé (cas fréquent agence)
Maintenir un écouteur webhook et optionnellement un job polling :
typescript
// Webhook (principal pour overlay fermé)
app.post('/webhooks/epayment', verifyHmac, async (req, res) => {
if (req.body.type === 'checkout.completed' && req.body.data.paid) {
await unlockDossierIdempotent(req.body.data.order_id, 'webhook');
}
res.sendStatus(200);
});
// Fallback polling (si webhook retardé)
async function pollUntilPaid(orderId: string) {
const session = await epayment.get('/checkout/sessions', { params: { order_id: orderId } });
if (session.paid) await unlockDossierIdempotent(orderId, 'poll');
}Contenu verify-completion (agence)
Réponse typique après encaissement agence :
json
{
"session_id": "chs_01JXXXXXXXX",
"order_id": "CJ-2026-88421",
"status": "completed",
"paid": true,
"metadata": { "tribunal": "Brazzaville" }
}Le bloc payment de la confirmation ERP (si applicable) aura channel: "CASH" et payment_ref identique au voucher.
Recette agence embed
- [ ] Voucher visible dans iframe avec
payment_reflisible - [ ] Fermeture overlay sans erreur ; message citoyen affiché
- [ ] Encaissement agent → webhook reçu sous 60 s
- [ ] Si overlay ouvert :
onCompletedéclenché après encaissement - [ ] verify-completion retourne
paid: trueetorder_idattendu - [ ] Second webhook / second verify : pas de double déblocage