Aller au contenu
OPTGateway
Documentation

Accepter des paiements avec OPTGateway

Ce guide part de zéro. Suivez les étapes dans l'ordre : en moins d'une heure, votre site accepte des paiements de test. Chaque exemple peut être copié tel quel.

Qu'est-ce qu'OPTGateway ?

OPTGateway est une passerelle de paiement. Elle se place entre votre site et les opérateurs de paiement : M-Pesa, Orange Money, Airtel Money, Afrimoney, illicocash et les cartes Visa et Mastercard.

Sans passerelle, il faudrait signer un contrat et écrire une intégration différente pour chaque opérateur. Avec OPTGateway, vous écrivez une seule intégration, et vos clients choisissent leur moyen de paiement.

Les mots à connaître

Vous les croiserez partout dans ce guide. Pas besoin de tout retenir maintenant : revenez ici au besoin.

Clé API
Un mot de passe réservé à votre serveur, qui prouve à OPTGateway que la demande vient bien de vous. Elle commence par sk_test_ (essais) ou sk_live_ (argent réel). Ne la mettez jamais dans une page web ou une application mobile.
Mode test
Un bac à sable : tout fonctionne comme en vrai, mais aucun argent ne circule. Idéal pour apprendre.
Mode live
Le mode réel : les clients sont vraiment débités. Il s'active après la vérification de votre établissement par notre équipe.
Référence
Votre numéro à vous pour ce paiement, par exemple un numéro de facture. Il doit être unique : deux paiements ne peuvent pas avoir la même référence.
Session de paiement
Une demande de paiement prête à être payée. Elle possède une adresse (url) vers laquelle vous envoyez votre client.
Webhook
Un message qu'OPTGateway envoie automatiquement à votre serveur pour dire « ce paiement est réussi ». C'est la preuve fiable qu'il faut attendre avant de livrer.
OTP
Un code à usage unique envoyé par SMS au client, par exemple par illicocash, pour confirmer qu'il est bien le titulaire du compte.

Comment se passe un paiement

  1. Votre site crée une demande : le montant, la devise et votre référence.
  2. Le client paie sur la page OPTGateway, avec son téléphone ou sa carte.
  3. OPTGateway vérifie auprès de l'opérateur que l'argent est bien reçu, avec le bon montant.
  4. Votre serveur est prévenu par un webhook, et le client revient sur votre site.

Moyens de paiement acceptés

Vos clients choisissent sur la page de paiement. Selon le moyen choisi, ils valident de trois façons différentes : OPTGateway gère chacune pour vous.

MoyenValeur de methodComment le client valideMontants
illicocash
illicocash
illicocashIl reçoit un code par SMS et le saisit sur la page de paiement.à partir de 1 000 CDF
M-PesaOrange MoneyAirtel MoneyAfrimoney
Mobile money
mobile_moneyUne demande s'affiche sur son téléphone ; il la valide avec son code secret.aucune limite propre à OPTGateway
VisaMastercard
Carte bancaire
cardIl est redirigé vers la page sécurisée de sa banque, puis revient.aucune limite propre à OPTGateway

Chaque paiement renvoyé par l'API, et chaque webhook, indique son moyen dans method. Pour le mobile money, le champ operator précise l'opérateur : mpesa, orange, airtel ou afrimoney (déduit du numéro). Vous distinguez ainsi sans ambiguïté un paiement illicocash d'un paiement M-Pesa.

Sur la page de paiement, le client choisit parmi les moyens actifs sur votre compte. Pour n'en proposer que certains, passez methods à la création de la session, par exemple "methods": ["illicocash"]. En API directe, method est obligatoire. GET /v1/payment-methods liste les moyens actifs sur votre compte.

Devises : francs congolais (CDF) et dollars (USD). Les moyens actifs dépendent des comptes d'encaissement configurés pour vous par notre équipe ; votre tableau de bord les affiche. Un montant hors limites est refusé avant tout envoi au client, avec le code amount_below_minimum.

Créer votre compte et votre clé de test

  1. Créez votre compte sur l'espace marchand. Vous êtes tout de suite en mode test.
  2. Dans le menu, ouvrez Clés API, choisissez « Test », puis cliquez sur Créer.
  3. Copiez la clé tout de suite : pour votre sécurité, elle ne sera plus jamais affichée. En cas de perte, créez-en une nouvelle et révoquez l'ancienne.
  4. Rangez-la sur votre serveur dans une variable d'environnement nommée OPTGATEWAY_KEY, par exemple dans le fichier .env de votre projet.

Astuce : dans l'espace marchand, la page Documentation contient des boutons « Essayer » qui envoient de vraies requêtes de test. Pratique pour voir les réponses sans écrire une ligne.

Méthode 1 : le lien de paiement, sans code

Vous n'avez pas de site, ou vous voulez encaisser un montant ponctuel ? Le lien de paiement suffit.

  1. Dans l'espace marchand, ouvrez Liens de paiement.
  2. Indiquez le montant, la devise et le motif, par exemple « Frais d'inscription 2026-2027 ».
  3. Cliquez sur Créer le lien, puis sur Envoyer par WhatsApp ou Copier le lien.
  4. Le client ouvre le lien et paie. Le paiement apparaît dans Paiements, avec son statut.

Un lien reste valable 24 heures.

Méthode 2 : la page de paiement (recommandée)

Votre site envoie le client vers la page de paiement OPTGateway, puis le récupère une fois le paiement terminé. C'est la méthode la plus simple à coder : la page gère le numéro de téléphone, le code SMS, la carte bancaire et les erreurs.

Étape 1 : installer le SDK

Le SDK est une petite bibliothèque qui vous évite d'écrire les appels HTTP à la main. Téléchargez celui de votre langage, puis installez-le dans votre projet.

SDK PHP

Version 1.1.0 · PHP 7.4 ou plus récent

Télécharger

optgateway-php-1.1.0.zip · 8 Ko

SDK Node.js

Version 1.1.0 · Node.js 18 ou plus récent

Télécharger

enywork-optgateway-1.1.0.tgz · 6,7 Ko

  • PHP avec Composer : ajoutez le bloc ci-dessous à votre composer.json (dans la section repositories si elle existe déjà), puis lancez composer require enywork/optgateway:1.1.0.
  • PHP sans Composer : décompressez l'archive dans votre projet et chargez autoload.php.
  • Node.js : une seule commande, qui télécharge et installe le paquet.
{
  "repositories": [
    {
      "type": "package",
      "package": {
        "name": "enywork/optgateway",
        "version": "1.1.0",
        "dist": { "url": "https://pay.optsolution.pro/sdk/optgateway-php-1.1.0.zip", "type": "zip" },
        "require": { "php": ">=7.4", "ext-curl": "*", "ext-json": "*" },
        "autoload": { "psr-4": { "Enywork\\OPTGateway\\": "src/" } }
      }
    }
  ]
}

Avec Node.js, le code reste identique : import OPTGateway from '@enywork/optgateway'. Les paquets seront aussi publiés sur Packagist et npm ; les commandes composer require et npm install @enywork/optgateway fonctionneront alors directement, avec le même code.

Étape 2 : créer la demande de paiement

Ce code s'exécute sur votre serveur, au moment où le client clique sur « Payer » sur votre site.

<?php
require 'vendor/autoload.php'; // sans Composer : require 'optgateway-php/autoload.php';
use Enywork\OPTGateway\Client;

// La clé est lue dans une variable d'environnement, jamais écrite dans le code
$optg = new Client(getenv('OPTGATEWAY_KEY'), ['base_url' => 'https://pay.optsolution.pro']);

$session = $optg->checkout->createSession([
  'amount'      => '150000',                 // montant en francs congolais
  'currency'    => 'CDF',                    // ou 'USD'
  'reference'   => 'FACT-2026-000123',       // votre numéro de facture, unique
  'description' => 'Frais académiques - 1er semestre',
  'return_url'  => 'https://votre-site.cd/paiement/retour',
]);

// Étape suivante : envoyer le client vers la page de paiement
header('Location: ' . $session['url'], true, 303);
exit;

OPTGateway répond avec la session créée. Le champ important est url :

{
  "id": "cs_test_Gq3…",
  "url": "https://pay.optsolution.pro/pay/cs_test_Gq3…",
  "status": "open",
  "amount": "150000.00",
  "currency": "CDF",
  "reference": "FACT-2026-000123"
}

Et si le client clique deux fois ? Aucun risque : avec la même reference, OPTGateway renvoie la même session. Le client ne peut pas payer deux fois la même facture.

Étape 3 : envoyer le client vers la page

C'est la dernière ligne de l'exemple ci-dessus : une redirection vers session.url. Le client voit la page de paiement, choisit son moyen de paiement et paie.

Étape 4 : recevoir la confirmation (webhook)

Quand le paiement est confirmé, OPTGateway appelle une adresse de votre serveur. Pour la configurer :

  1. Dans l'espace marchand, ouvrez Webhooks et saisissez l'adresse, par exemple https://votre-site.cd/webhooks/optgateway.
  2. Cliquez sur Générer un nouveau secret et rangez-le dans la variable OPTGATEWAY_WEBHOOK_SECRET.
  3. Ajoutez ce code sur votre serveur, puis cliquez sur Envoyer un test pour vérifier qu'il répond.
<?php
// Fichier appelé par OPTGateway : https://votre-site.cd/webhooks/optgateway
require 'vendor/autoload.php';
use Enywork\OPTGateway\Webhook;
use Enywork\OPTGateway\Exception\SignatureVerificationException;

try {
  $event = Webhook::constructEvent(
    file_get_contents('php://input'),            // le corps brut de la requête
    $_SERVER['HTTP_OPTGATEWAY_SIGNATURE'] ?? '',
    getenv('OPTGATEWAY_WEBHOOK_SECRET')           // le secret whsec_... de votre tableau de bord
  );
} catch (SignatureVerificationException $e) {
  http_response_code(400);                        // pas envoyé par OPTGateway : on ignore
  exit;
}

if ($event['type'] === 'checkout.session.completed') {
  // Le paiement est confirmé : marquez la facture comme payée
  marquerFacturePayee($event['data']['reference']);
}

http_response_code(200);                          // répondre vite : "bien reçu"

Important : marquez une facture comme payée uniquement dans ce code-là. Le webhook est la seule preuve fiable. OPTGateway le renvoie automatiquement pendant environ 22 heures si votre serveur ne répond pas.

Étape 5 : la page de retour

Après le paiement, le client revient sur votre return_url. L'adresse contient status=succeeded, mais un client malin pourrait la taper lui-même. Pour afficher le bon message, demandez l'état réel à OPTGateway :

<?php
// https://votre-site.cd/paiement/retour?session_id=...&status=succeeded
// On ne se fie pas à l'adresse : on demande l'état réel à OPTGateway
$session = $optg->checkout->retrieveSession($_GET['session_id'] ?? '');

if ($session['status'] === 'completed') {
  echo 'Merci, votre paiement est bien reçu.';
} else {
  echo 'Le paiement n\'est pas encore confirmé.';
}

Étape 6 : tester

Faites un paiement complet avec votre clé de test et les numéros de test. Vérifiez trois choses : la page de paiement s'ouvre, le webhook arrive sur votre serveur, et la facture passe à « payée ».

Méthode 3 : l'API directe (avancé)

Pour construire votre propre écran de paiement, par exemple dans une application mobile. Votre écran propose les moyens de paiement, le client en choisit un, puis vous créez le paiement avec ce moyen dans method (obligatoire). Vous suivez ensuite le champ next_action, qui indique ce que le client doit faire.

// 1. Créer le paiement, avec le moyen choisi par le client (obligatoire)
let p = await optg.payments.create({
  method: 'illicocash',            // ou 'mobile_money', ou 'card'
  amount: '5000', currency: 'CDF', reference: 'CMD-42',
  customer: { phone: '+243850000005' },
});

// 2. Suivre l'action demandée
if (p.next_action?.type === 'otp') {
  // illicocash : le client a reçu un code par SMS, vous le lui demandez
  p = await optg.payments.confirm(p.id, codeSaisiParLeClient);
} else if (p.next_action?.type === 'redirect') {
  // carte bancaire : envoyer le client vers p.next_action.url
} else if (p.next_action?.type === 'wait_for_customer') {
  // M-Pesa, Orange, Airtel, Afrimoney : le client valide sur son téléphone
  // attendez le webhook payment.succeeded
}
next_action.typeCe qui se passeCe que vous faites
otpillicocash envoie un code par SMS au clientDemandez le code au client, puis appelez confirm
wait_for_customerLe client reçoit une demande sur son téléphone (M-Pesa, Orange, Airtel, Afrimoney)Affichez « Validez sur votre téléphone » et attendez le webhook
redirectPaiement par carte bancaireEnvoyez le client vers next_action.url

Tester sans argent réel

Avec une clé sk_test_, les paiements sont simulés, avec le parcours réel de chaque moyen :

MoyenScénarioRésultat
illicocashN'importe quel numéroCode SMS demandé : 123456 réussit, tout autre code est refusé
mobile_moneyPar exemple +243 97 000 00 01Validation sur le téléphone, puis paiement réussi après environ 5 secondes
mobile_moneyNuméro qui finit par 2, par exemple +243 97 000 00 02Validation sur le téléphone, puis échec pour solde insuffisant
cardAucunPage bancaire simulée : le paiement réussit quand le client revient sur la page de paiement

Si votre compte n'a qu'illicocash en live, seul illicocash est proposé en test aussi : votre intégration se comporte comme en production.

Sécurité : les bons réflexes

Cinq règles suffisent à éviter l'essentiel des problèmes. Relisez-les avant la mise en ligne.

  • La clé API reste sur votre serveur. Jamais dans une page web, une application mobile ou un dépôt Git. Rangez-la dans une variable d'environnement. Si elle a fuité, révoquez-la dans Clés API et créez-en une autre.
  • Livrez uniquement sur webhook. La page de retour peut être ouverte par n'importe qui ; seul le webhook signé prouve le paiement.
  • Vérifiez la signature de chaque webhook, avec le SDK ou à la main, et refusez les messages de plus de 5 minutes.
  • Contrôlez le montant et la référence reçus dans le webhook avant de marquer la facture comme payée.
  • Gardez une référence unique par facture. Si vous renvoyez la même demande, OPTGateway renvoie le même paiement au lieu d'en créer un second : pas de double débit en cas de clic répété ou de coupure réseau.

Passer en production

  1. Dans le tableau de bord, onglet Vérification, renseignez votre établissement et déposez vos documents : RCCM (ou arrêté / agrément pour une école ou une université) et pièce d'identité du représentant légal. Notre équipe examine le dossier, en général sous 48 heures ouvrées, configure votre compte d'encaissement (wallet illicocash ou compte FlexPay) et active le mode live. Vous êtes prévenu par e-mail à chaque étape.
  2. Créez une clé Live dans Clés API, et remplacez la clé de test sur votre serveur de production.
  3. Vérifiez que l'adresse de webhook est en https:// et qu'elle répond.
  4. Faites un vrai paiement d'un petit montant et vérifiez-le dans Paiements.

Adresses de l'API

Toutes les adresses commencent par https://pay.optsolution.pro. Chaque requête porte l'en-tête Authorization: Bearer VOTRE_CLE.

AdresseRôle
POST /v1/checkout/sessionsCréer une demande de paiement (page hébergée)
GET /v1/checkout/sessions/:idConsulter une demande de paiement
POST /v1/paymentsCréer un paiement (API directe)
GET /v1/payments/:idConsulter un paiement
GET /v1/paymentsLister les paiements (filtres : status, reference, limit)
POST /v1/payments/:id/confirmEnvoyer le code SMS du client (illicocash)
GET /v1/balanceConsulter votre solde à reverser

Champs d'une demande de paiement

ChampObligatoireDescription
amountOuiMontant en chaîne de caractères : "150000" ou "12.50"
currencyOuiCDF ou USD
referenceOuiVotre identifiant unique (numéro de facture)
return_urlOuiPage de votre site où revient le client
cancel_urlNonPage de votre site si le client annule
descriptionNonTexte affiché au client, par exemple « Frais académiques »
customer.phoneNonNuméro du client, au format +243…. S'il est absent, le client le saisit.
metadataNonInformations libres, renvoyées telles quelles (matricule, identifiant interne…)
expires_in_minutesNonDurée de validité, de 5 à 1440 minutes (60 par défaut)

Statuts d'un paiement

StatutSignificationQue faire
pendingEn attente de validation par le clientAttendre
requires_actionLe client doit agir (code SMS, carte)Suivre next_action
succeededPayé et vérifiéLivrer
failed, expired, cancelledNon payéProposer de réessayer
processingL'opérateur n'a pas encore confirmé ; notre équipe vérifieNe pas faire payer une deuxième fois : attendre le webhook

Événements (webhooks)

ÉvénementQuand
checkout.session.completedUne demande de paiement est payée : c'est celui à écouter en priorité
payment.succeededUn paiement est réussi
payment.failed, payment.expired, payment.cancelledUn paiement n'a pas abouti
payment.review_requiredUn paiement est en vérification par notre équipe
checkout.session.expiredUne demande n'a pas été payée à temps
payout.succeeded, payout.failedUn reversement de fonds vers votre compte

Chaque webhook porte l'en-tête OPTGateway-Signature. Les fonctions constructEvent des SDK la vérifient pour vous. Votre serveur doit répondre par un code 2xx en moins de 10 secondes ; sinon OPTGateway recommence plus tard, avec 8 tentatives au total. Un même événement peut donc arriver deux fois : ignorez celui que vous avez déjà traité (même id).

Vérifier une signature sans SDK

Si vous n'utilisez pas nos SDK, la vérification tient en quelques lignes. L'en-tête a la forme t=HORODATAGE,v1=SIGNATURE. La signature est un HMAC-SHA256, en hexadécimal, calculé avec votre secret de webhook sur le texte HORODATAGE.CORPS, où le corps est le JSON brut reçu, tel quel.

<?php
// Sans SDK : vérifier soi-même la signature d'un webhook
$body   = file_get_contents('php://input');           // corps brut, avant json_decode
$header = $_SERVER['HTTP_OPTGATEWAY_SIGNATURE'] ?? ''; // ex. t=1790000000,v1=5f2c...
$secret = getenv('OPTGATEWAY_WEBHOOK_SECRET');

parse_str(str_replace(',', '&', $header), $parts);     // ['t' => ..., 'v1' => ...]
$attendu = hash_hmac('sha256', $parts['t'] . '.' . $body, $secret);

$valide = isset($parts['v1'])
  && hash_equals($attendu, $parts['v1'])               // comparaison à temps constant
  && abs(time() - (int) $parts['t']) <= 300;           // message de moins de 5 minutes

if (!$valide) { http_response_code(400); exit; }
$event = json_decode($body, true);

Piège fréquent : calculer la signature sur un JSON déjà décodé puis réencodé. L'ordre des champs ou les espaces peuvent changer, et la signature ne correspond plus. Utilisez toujours le corps brut.

Erreurs

En cas d'erreur, la réponse contient un code et un message en français, par exemple :

{ "error": { "code": "invalid_request", "message": "Requete invalide", "details": ["currency : CDF ou USD"] } }
Code HTTPCodeCause fréquente
400invalid_requestUn champ manque ou est mal écrit, par exemple method absent : lisez details
400method_not_availableCe moyen de paiement n'est pas actif sur votre compte dans ce mode. details.available_methods liste ceux qui le sont
400amount_below_minimumMontant trop petit pour le moyen de paiement. Le minimum est indiqué dans details.min_amount (1 000 CDF pour illicocash)
400amount_above_maximumMontant trop élevé pour le moyen de paiement
401unauthorizedClé absente, mal copiée ou révoquée
403forbiddenClé live utilisée avant l'activation du mode live
404not_foundIdentifiant inconnu, ou créé dans l'autre mode (test ou live)
409duplicate_referenceRéférence déjà utilisée avec un autre montant
429rate_limitedTrop de requêtes : patientez quelques secondes

Questions fréquentes

Faut-il un site web ?

Non. Les liens de paiement fonctionnent sans site : vous les envoyez par WhatsApp ou par SMS.

Le client ne reçoit pas le code SMS, que faire ?

Sur la page de paiement, il clique sur « Je n'ai pas reçu de code » pour relancer une demande. Vérifiez aussi que le numéro est bien celui de son compte illicocash.

Un paiement est « En vérification » : c'est grave ?

Non. L'opérateur n'a pas répondu à temps. Notre équipe vérifie auprès de lui, puis vous recevez le webhook final. Surtout, ne faites pas payer le client une deuxième fois.

Puis-je encaisser en dollars ?

Oui. Utilisez "currency": "USD". Les montants acceptent deux décimales : "12.50".

Quand est-ce que je reçois l'argent ?

Cela dépend de vos comptes d'encaissement. Si vous avez vos propres comptes (wallet illicocash, compte FlexPay), l'argent arrive directement chez vous, sans délai de notre côté. Sinon, vos paiements sont encaissés sur les comptes de notre équipe, qui vous reverse les fonds, commission déduite ; le calendrier est convenu à l'activation de votre compte. Votre espace marchand indique, pour chaque moyen, quel compte est utilisé.

J'ai une autre question

Contactez notre équipe depuis votre espace marchand ou avec les coordonnées de la page d'accueil.