Trois étapes, une trentaine de lignes de code. Votre client paie sur une page hébergée
chez nous : vous n'avez jamais à manipuler ses coordonnées bancaires ni son numéro mobile money.
PHP, cURL ou tout client HTTPEnvironnement de test inclusWebhooks signés
Votre serveur crée une session de paiement et reçoit une URL. Vous y redirigez votre
client, il paie, puis nous notifions votre serveur par un webhook signé. Le retour du
client sur votre site n'arrive qu'après, et ne sert qu'à l'affichage.
Le webhook part avant le retour du client : c'est lui, et non la redirection, qui fait foi.
1Créer une session
Depuis votre serveur, avec votre clé secrète.
Jamais depuis le navigateurUne clé sk_ placée dans du JavaScript ou une application mobile permet à n'importe qui de créer des paiements et de lire vos transactions en votre nom.
$hub = new Hub\Client('sk_test_…');
$session = $hub->sessions->creer([
'montant' => 25000, // en francs, sans décimale'devise' => 'XOF',
'reference' => $commande->numero,
'url_succes' => 'https://boutique.ci/merci',
]);
Le montant est exprimé en unité mineure entière. Le franc CFA n'ayant pas de décimale,
1 000 F s'écrit simplement 1000.
2Rediriger le client
PHP
header('Location: ' . $session['url']);
exit;
Votre client choisit son moyen de paiement, confirme sur son téléphone, puis revient sur votre
url_succes. La page hébergée gère l'attente de validation, les échecs et les nouvelles tentatives.
3Recevoir le résultat
Déclarez un endpoint depuis votre espace développeur. Vérifiez toujours la signature
avant de traiter l'événement, et répondez 200 rapidement.
$evenement = Hub\Webhooks::depuisRequete('whsec_…');
if ($evenement['type'] === 'paiement.reussi') {
$reference = $evenement['donnees']['paiement']['reference'];
// Livrez la commande.
}
http_response_code(200);
Votre endpoint doit répondre 200 en moins de 15 secondes. Pour un traitement long
(email, facture, stock), enregistrez l'événement et traitez-le dans une file d'attente.
Trois pièges à éviter
Ce sont les erreurs que nous voyons le plus souvent, et les plus coûteuses.
Le retour navigateur ne prouve rien
Un client peut fermer son onglet avant la redirection : vous ne saurez jamais qu'il a
payé. Il peut aussi ouvrir votre URL de succès sans avoir payé, en la devinant ou en
revenant en arrière.
Ne validez une commande que sur webhook, ou sur interrogation du statut. L'URL de succès sert à afficher un message, rien de plus.
Le statut indéterminé existe
En mobile money, un paiement peut rester sans réponse : l'opérateur ne confirme ni ne
refuse, et le payeur a peut-être été débité. Nous ne le déclarons jamais en échec. Il
passe en a_revoir, et notre réconciliation tranche sous 24 heures à partir
du relevé opérateur.
Ne livrez pas, mais ne considérez pas la commande annulée. Et surtout, ne demandez pas au client de repayer : c'est ainsi qu'on crée un double débit et une réclamation.
L'idempotence n'est pas optionnelle
Un timeout ne vous dit pas si la requête a abouti. Sans clé d'idempotence, la rejouer
crée un doublon.
En-tête HTTP
# Une clé stable dérivée de votre commande, pas un aléatoire :# sinon le rejeu ne sert à rien.
Idempotency-Key: commande-4711
Tester
Avec une clé sk_test_, aucun mouvement réel n'est produit.
Les scénarios se pilotent par les quatre derniers chiffres du numéro du payeur.
Numéro finissant par
Résultat
…0000
Succès immédiat
…0002
Solde insuffisant
…0004
Opérateur indisponible
…0005
Statut indéterminéÀ tester en priorité
…0006
Aucune réponse, expirera
Liste complète, cartes de test et avance du temps sur la page ressources.
Commencez par 0005C'est le cas que la plupart des intégrations gèrent mal, et celui qui produit les réclamations.
Passer en production
Cochez chaque point au fur et à mesure. Votre progression reste enregistrée dans ce navigateur.
Avant la mise en ligne0/7
Votre intégration est prête pour la production.
Votre espace développeur affiche vos derniers événements et vos tentatives de livraison,
avec le code HTTP renvoyé par votre serveur. La plupart des problèmes de réception s'y
diagnostiquent sans nous écrire.