SoftPay : le paiement natif, avec votre design
SoftPay affiche le choix de l’opérateur, le numéro, le code de confirmation, le lien d’application (Wave, Djamo) et le suivi du paiement directement dans votre page, sans passer par la page Cartflox. Vous gardez la main sur tout le style, ou vous dessinez chaque écran vous-même. Seule votre clé publique est utilisée côté navigateur.
Le pied du formulaire porte toujours la mention « Propulsé par Cartflox » avec un lien vers cartflox.com : elle fait partie des conditions d’utilisation de SoftPay et ne se retire pas. Vous pouvez en changer la couleur, pas la masquer.
Essayez tout de suite : démo SoftPay avec votre clé publique et vos couleurs.
Option A : formulaire prêt, à vos couleurs
Section intitulée « Option A : formulaire prêt, à vos couleurs »<div id="paiement"></div><script src="https://cartflox.com/cartflox-softpay.js"></script><script> Cartflox.softpay.configure({ publicKey: "af_live_pub_VOTRE_CLE" }); Cartflox.softpay.mount({ container: "#paiement", amount: 5000, currency: "XOF", country: "ci", // moyens de paiement proposés (ci, sn, bj, ml, bf, tg, cm...) description: "Commande #1042", customer_email: "awa@example.com", metadata: { order_id: "1042" }, merchant_name: "Ma Boutique", // facultatif : nom affiché sur les reçus et la page Cartflox équivalente merchant_logo: "https://maboutique.com/logo.png", theme: { accent: "#1a1a1c", "accent-text": "#ffffff", radius: "0px", font: "inherit" }, onSuccess: function (r) { /* affichez un merci ; validez côté serveur */ }, onError: function (e) { console.error(e); } });</script>Options de mount
Section intitulée « Options de mount »| Option | Type | Requis | Description |
|---|---|---|---|
container |
string ou élément | Oui | Sélecteur CSS ou élément qui reçoit le formulaire |
amount |
number | Oui | Montant, entier pour le franc CFA |
currency |
string | Non | XOF par défaut |
country |
string | Non | Pays des moyens proposés (ci, sn, bj, ml, bf, tg, cm, gn…). Sans valeur : tous les opérateurs actifs |
description, customer_name, customer_email, customer_phone, metadata, success_url, cancel_url |
Non | Mêmes champs que POST /v1/checkout/sessions |
|
merchant_name, merchant_logo |
string | Non | Nom et logo (adresse https) affichés sur la page Cartflox équivalente et les reçus, à la place de ceux de votre espace |
title |
string | Non | Titre du formulaire (« Paiement » par défaut) |
theme |
object | Non | Variables CSS sans le préfixe : { accent, "accent-text", bg, text, muted, border, field, radius, font } |
labels |
object | Non | Libellés à remplacer (voir Textes) |
autoRedirect |
boolean | Non | false pour ne pas envoyer vous-même le client sur une page hébergée : vous recevez l’URL dans onRedirect |
timeoutMs |
number | Non | Durée maximale de suivi d’un paiement en attente (180 000 ms par défaut) |
onSession, onStatus, onRedirect, onSuccess, onError |
function | Non | Voir Événements |
configure accepte publicKey (obligatoire), country (pays par défaut), css: false (aucun style injecté) et baseUrl (uniquement si vous servez le script depuis un autre domaine).
Personnaliser le style
Section intitulée « Personnaliser le style »Le formulaire est construit avec des variables CSS et des classes stables. Surchargez-les dans votre propre feuille de style, ou passez { css: false } à configure pour n’injecter aucun style et tout écrire vous-même.
| Variable | Rôle |
|---|---|
--cf-accent |
Couleur du bouton Payer et de la sélection |
--cf-accent-text |
Couleur du texte du bouton |
--cf-bg |
Fond du formulaire |
--cf-text |
Texte principal |
--cf-muted |
Texte secondaire |
--cf-border |
Bordures |
--cf-field |
Fond des champs |
--cf-radius |
Arrondi général |
--cf-font |
Police (inherit par défaut : celle de votre page) |
.cf-sp { --cf-accent: #c01826; --cf-radius: 0; --cf-font: "Questrial", sans-serif; }.cf-sp-bouton { text-transform: uppercase; letter-spacing: .06em; }.cf-sp-methode.cf-sp-actif { box-shadow: none; background: #fff3f3; }Classes disponibles : .cf-sp, .cf-sp-entete, .cf-sp-titre, .cf-sp-montant, .cf-sp-methodes, .cf-sp-methode, .cf-sp-actif, .cf-sp-telephone, .cf-sp-indicatif, .cf-sp-input, .cf-sp-otp, .cf-sp-ussd, .cf-sp-bouton, .cf-sp-lien, .cf-sp-erreur, .cf-sp-attente, .cf-sp-spinner, .cf-sp-qr, .cf-sp-pied, .cf-sp-securise, .cf-sp-propulse (la mention Cartflox : couleur libre, affichage imposé). Chaque écran porte aussi une classe .cf-sp-vue-<nom> (formulaire, attente, otp, application, redirection, succes, echec).
Tous les libellés se remplacent avec l’option labels, par exemple labels: { payer: "Régler", telephone: "Votre numéro Mobile Money", succes: "Paiement reçu !" }.
Événements
Section intitulée « Événements »| Événement | Quand |
|---|---|
onSession(s) |
Session créée : s.id, s.orderId, s.url (la page Cartflox équivalente) |
onStatus(r) |
À chaque réponse de paiement ou de suivi : r.status |
onRedirect(url) |
Page hébergée (carte, certains agrégateurs) : l’URL vers laquelle le client part, autoRedirect: false pour gérer vous-même. Aussi appelé pour un lien d’application (Wave, Djamo) : le widget reste alors affiché avec le bouton « Ouvrir » et suit le paiement. |
onSuccess(r) |
Paiement confirmé : r.sessionId, r.orderId, r.amount, r.currency |
onError(e) |
Paiement refusé, délai dépassé ou erreur réseau : e.message |
Option B : headless, vous dessinez tout
Section intitulée « Option B : headless, vous dessinez tout »Même moteur, aucune interface : vous appelez la session et affichez ce que vous voulez.
En mode headless, c’est vous qui dessinez le pied de page : la mention « Propulsé par Cartflox » avec un lien vers https://cartflox.com reste due, au même titre que dans le formulaire prêt à l’emploi.
Cartflox.softpay.configure({ publicKey: "af_live_pub_VOTRE_CLE" });
const session = await Cartflox.softpay.createSession({ amount: 5000, currency: "XOF", metadata: { order_id: "1042" },});
const methods = await session.methods("ci");// [{ code, gatewayId, name, provider, country, type, logo, requiresPhone, dialCode }]
const r = await session.pay({ method: methods[0], phone: "+2250700000000", name: "Awa Koné" });switch (r.status) { case "SUCCESS": /* payé */ break; case "PENDING": /* demande poussée sur le téléphone : affichez r.instructions, puis session.waitForResult() */ break; case "REQUIRE_OTP": /* code de confirmation (Orange Money, Magma OnePay, Paystack...) : affichez r.ussdCode ou r.instructions, puis session.pay({ ..., otp }) */ break; case "APP_LINK": /* Wave, Djamo : bouton vers r.redirectUrl (cible _blank), r.qr en image sur ordinateur, puis session.waitForResult() */ break; case "REDIRECT": window.location.href = r.redirectUrl; break; // page hébergée du fournisseur case "INLINE_CARD": window.location.href = session.url; break; // carte : page sécurisée Cartflox default: /* r.message */}
const fin = await session.waitForResult({ timeoutMs: 180000, onTick: (d) => console.log(d.status) });// fin.status : SUCCESS | FAILED | CANCELLED| Méthode | Rôle |
|---|---|
createSession(options) |
Mêmes champs que POST /v1/checkout/sessions. Renvoie une session. |
session.methods(pays?) |
Moyens de paiement disponibles, filtrés par pays (code ISO). |
session.pay({ method, phone, name, email, country, otp }) |
Lance le paiement. Renvoie { status, message, redirectUrl, application, qr, instructions, ussdCode, providerReference }. application et qr (image en data URL) ne sont remplis que pour APP_LINK ; instructions porte la consigne du fournisseur quand il en donne une. |
session.getStatus() |
Statut courant : { status, paid, order_id, provider }. |
session.waitForResult({ intervalMs, timeoutMs, onTick }) |
Interroge le statut jusqu’à un état final. |