embed.js ouvre le checkout IzichangePay dans une modale (iframe) directement sur votre page, au lieu de rediriger le client vers la page de paiement hébergée. Le client paie sans quitter votre site ; à la fin, le bouton de sortie devient simplement « Fermer » et la modale se referme.
Le payment intent est toujours créé côté serveur avec votre clé secrète. embed.js ne fait qu’afficher un intent déjà créé : aucune clé n’est exposée au navigateur.

Démo live — IziShop

Boutique e-commerce de démonstration qui intègre embed.js en conditions réelles (Tron testnet, paiement en TRX / USDT). Ajoutez un article au panier puis lancez le paiement : la modale de checkout s’ouvre sans quitter la page, exactement comme décrit dans ce guide.

Ajouter un bouton « Payer »

Trois façons d’intégrer, du plus simple au plus flexible :
MéthodeBackend requis ?MontantPour qui
1. Bouton sans code (lien Produit)❌ NonFixe (défini au dashboard)Sites no-code, montant connu
2. Bouton géré par le SDK (IziPay.Button)✅ OuiDynamique (panier)Boutiques, montant calculé
3. Ouverture programmée (IziPay.open)✅ OuiDynamiqueContrôle total du déclenchement
Dans tous les cas, la clé secrète sk_… ne quitte jamais le serveur. Le navigateur ne manipule qu’un identifiant public : le publicId de l’intent ou le slug du produit. La confirmation fait toujours foi via le webhook signé payment_intent.completed.

Générateur de bouton

Choisissez la forme (pill · rounded · soft), la couleur (teal · sombre · bleue) et la taille (sm · normal · lg · xl), prévisualisez en direct, puis copiez le code HTML ou JS. Le bouton utilise toujours la police de marque (Typold) et votre logo.
Vous pouvez aussi ouvrir le générateur en plein écran (utile sur mobile).

Méthode 1 — Bouton sans code (lien Produit)

Pour un montant fixe, aucun serveur n’est nécessaire. Créez un produit dans le dashboard (Vente → Produits) : vous obtenez un lien https://checkout.pay.izichange.com/pay/product/<slug>. Le montant est figé côté IzichangePay — le client ne peut pas le modifier. Collez le loader, puis un bouton portant l’attribut data-izipay-url :
<script src="https://checkout.pay.izichange.com/embed.js"></script>

<button data-izipay-url="https://checkout.pay.izichange.com/pay/product/<slug>">
  Payer avec IzichangePay
</button>
embed.js câble automatiquement tout élément [data-izipay-url] (ou [data-izipay-intent]) : au clic, la modale s’ouvre. Pas une ligne de JavaScript.
AttributRôle
data-izipay-urlLien de checkout / produit à ouvrir.
data-izipay-intentpublicId d’un PaymentIntent (alternative à l’URL).
data-izipay-localeLangue du widget (fr, en).
data-izipay-success-urlPage vers laquelle rediriger une fois le paiement confirmé et la modale fermée.
data-izipay-containerSélecteur CSS pour monter le widget en ligne au lieu d’une modale.
Pour réagir au résultat, écoutez les CustomEvents émis sur le bouton :
<button id="pay" data-izipay-url="https://checkout.pay.izichange.com/pay/product/<slug>">
  Payer avec IzichangePay
</button>
<script>
  document.getElementById('pay').addEventListener('izipay:success', function (e) {
    console.log('Payé', e.detail); // { intentId, amount, assetCode, network }
  });
  // également émis : izipay:expired, izipay:failed, izipay:error, izipay:close
</script>
izipay:success est un signal d’interface. Ne livrez jamais la commande dessus seul : la source de vérité reste le webhook payment_intent.completed traité côté serveur.

Méthode 2 — Bouton géré par le SDK (montant dynamique)

Pour un montant calculé (panier), le bouton appelle votre serveur au clic — le modèle des Smart Buttons PayPal. embed.js dessine le bouton ; votre serveur crée l’intent avec la clé secrète et renvoie son publicId ; la modale s’ouvre. Côté navigateur :
<script src="https://checkout.pay.izichange.com/embed.js"></script>
<div id="pay-container"></div>
<script>
  IziPay.Button({
    // Appelé au clic. Renvoie le publicId de l'intent (ou un objet
    // { id | publicId | url }). N'exposez JAMAIS la clé secrète ici.
    createIntent: function () {
      return fetch('/api/create-intent', { method: 'POST' })
        .then(function (r) { return r.json(); })
        .then(function (d) { return d.publicId; });
    },
    label: 'Payer avec IzichangePay',
    locale: 'fr',
    onSuccess: function (d) { /* signal UI — la vérité reste le webhook */ },
    onClose:   function () { /* modale fermée */ },
    onError:   function (e) { console.error(e); }
  }).render('#pay-container');
</script>
Côté serveur (Node + SDK) — la clé secrète reste ici :
// POST /api/create-intent
app.post('/api/create-intent', async (req, res) => {
  const intent = await izipay.paymentIntents.create({
    requestedCurrencyType: 'fiat',
    currencyRequested: 'XOF',
    amountRequested: panierTotalXOF,   // montant calculé côté serveur
    merchantReference: 'order_4821',
  });
  res.json({ publicId: intent.id });   // seul l'identifiant public part au navigateur
});
Option de IziPay.Button({...})TypeRôle
createIntent() => Promise<string | { id|publicId|url }>Appelle votre serveur ; renvoie l’intent.
url / intentIdstringAlternative statique à createIntent.
labelstringTexte affiché avant le logo (défaut « Payer avec »).
logobooleanAffiche le logo IzichangePay complet dans le bouton (défaut true). false pour masquer.
shape'pill' | 'rounded' | 'soft'Forme des angles (défaut rounded). Aplat de marque, sans ombre, police Typold.
color'teal' | 'dark' | 'blue' (ou hex)Couleur de fond — teal #008080, sombre #14142B, bleue #274586 (défaut teal).
size'sm' | 'normal' | 'lg' | 'xl'Taille du bouton (défaut normal).
className / stylestringPersonnalisation (sinon style IzichangePay par défaut).
localestringLangue du widget.
onSuccess · onExpired · onFailed · onError · onClose · onReadyfunctionCallbacks (identiques à IziPay.open).
render(target) accepte un sélecteur CSS ou un élément DOM et renvoie { element }.

Méthode 3 — Ouverture programmée

Si vous pilotez vous-même le déclencheur, créez l’intent côté serveur puis appelez IziPay.open(...).

Créer l’intent côté serveur

Comme pour le flux par redirection, créez un payment intent et récupérez sa réponse (qui contient id et paymentUrl). Renvoyez paymentUrl (ou id) à votre page.
// Votre backend — clé secrète, jamais exposée au client
const intent = await izipay.paymentIntents.create({
  requestedCurrencyType: 'fiat',
  currencyRequested: 'XOF',
  amountRequested: 5000,
  merchantReference: 'order_4821',
});
// → renvoyez intent.paymentUrl (ou intent.id) au front

Ouvrir la modale côté client

Incluez le loader, puis appelez IziPay.open() :
<script src="https://checkout.pay.izichange.com/embed.js"></script>
<script>
  document.querySelector('#pay').addEventListener('click', function () {
    IziPay.open({
      url: intentPaymentUrl,          // intent.paymentUrl renvoyé par votre serveur
      // ou : intentId: 'pi_xxx',     // alternative : le publicId de l'intent

      onSuccess: function (data) {
        // { intentId, amount, assetCode, network }
        // Paiement confirmé. Mettez à jour votre commande ici.
        console.log('Payé', data);
      },
      onExpired: function () { /* l'intent a expiré */ },
      onFailed:  function () { /* paiement échoué */ },
      onError:   function () { /* erreur inattendue */ },
      onClose:   function () { /* le client a fermé la modale */ },
    });
  });
</script>
N’utilisez jamais onSuccess seul pour livrer la commande : c’est un signal d’interface. La source de vérité reste votre webhook payment_intent.completed (signé), traité côté serveur. Voir Webhooks.

Options de IziPay.open(options)

OptionTypeDescription
urlstringURL de checkout de l’intent (intent.paymentUrl). url ou intentId est requis.
intentIdstringpublicId du payment intent (intent.id). Alternative à url.
containerstring | ElementSélecteur CSS ou élément DOM. Si fourni, le widget est monté en ligne dans ce conteneur au lieu d’une modale plein écran.
localestringForce la langue du widget (fr, en).
dismissOnBackdropbooleanAutorise la fermeture en cliquant en dehors de la modale. false par défaut, pour éviter d’interrompre un paiement par erreur.
onSuccess(data)functionPaiement confirmé. data = { intentId, amount, assetCode, network }.
onExpired(data)functionL’intent a expiré sans paiement suffisant.
onFailed(data)functionPaiement en échec.
onError(data)functionErreur inattendue.
onClose()functionLa modale a été fermée (bouton « Fermer », croix, Échap).
onReady()functionLe widget est chargé et prêt (pour retirer un éventuel spinner).
IziPay.open() renvoie un handle { close(), getIframe() } pour piloter la modale par programme :
var modal = IziPay.open({ url: intentPaymentUrl });
// … plus tard
modal.close();

Événements

Sous le capot, le widget communique avec votre page via postMessage. Les callbacks ci-dessus correspondent à ces événements :
ÉvénementCallback
izipay:readyonReady
izipay:payment_completedonSuccess
izipay:payment_expiredonExpired
izipay:payment_failedonFailed
izipay:erroronError
izipay:closedonClose

Sécurité

  • Le widget n’envoie ses messages qu’à l’origine exacte de votre page (jamais *) : le navigateur ne les délivre qu’à votre site.
  • embed.js n’accepte en retour que les messages provenant de l’origine du widget IzichangePay.
  • Le checkout autorise l’embarquement par iframe (frame-ancestors) car c’est sa fonction ; aucune action de paiement n’est déclenchée sans envoi crypto explicite du client.

Intégration en ligne (sans modale)

Pour intégrer le checkout dans une section de votre page plutôt qu’en surimpression :
<div id="checkout" style="max-width:440px;margin:0 auto;"></div>
<script>
  IziPay.open({ url: intentPaymentUrl, container: '#checkout' });
</script>

Sandbox

En environnement de test, chargez le loader depuis le checkout sandbox :
<script src="https://checkout.sandbox-pay.izichange.com/embed.js"></script>