Aller au contenu

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.

HTML
<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>
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).

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)
CSS, exemple : votre charte
.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é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

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.

JavaScript
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.