L'intégration des paiements Mobile Money est devenue essentielle pour toute entreprise opérant en Afrique de l'Ouest et Centrale. Ce guide technique vous accompagne pas à pas dans l'intégration de l'API ElyonPay en PHP : authentification JWT, création de liens de paiement, vérification des transactions. À la fin, vous pourrez accepter les paiements Orange Money, Wave, MTN MoMo et carte bancaire dans 14 pays africains.
1Pourquoi intégrer l'API ElyonPay
L'API ElyonPay fournit une interface unifiée pour accepter les paiements Mobile Money (Orange Money, Wave, MTN MoMo, Moov Africa, Airtel Money) et les paiements par carte (Visa, Mastercard avec 3D Secure) dans 14 pays africains. Le modèle d'intégration est basé sur la création de liens de paiement : votre serveur PHP crée un lien, redirige le client vers une page sécurisée ElyonPay, puis vérifie le statut de la transaction.
Ce modèle « payment link + pull » simplifie considérablement l'intégration : pas besoin de gérer la conformité PCI DSS, pas de manipulation de données sensibles côté serveur, et la page de paiement est optimisée pour chaque opérateur. Les devises supportées sont XAF, XOF, EUR, USD, GBP, NGN, KES et CDF.
2Prérequis et environnements
Avant de commencer, assurez-vous d'avoir :
- Un compte marchand ElyonPay avec vos identifiants API (username et password)
- PHP 7.4 ou supérieur avec l'extension cURL activée
- Un certificat SSL valide sur votre serveur (HTTPS obligatoire)
L'API utilise deux environnements distincts :
| Environnement | URL de base | Description |
|---|---|---|
| Sandbox | https://api.elyonpay.net/api | Transactions de test, aucun débit réel |
| Production | https://api.elyonpay.org/api | Transactions réelles |
Stockez vos identifiants dans des variables d'environnement ou un fichier .env (jamais dans le code source) :
ELYONPAY_API_URL=https://api.elyonpay.net/api
ELYONPAY_USERNAME=votre_username
ELYONPAY_PASSWORD=votre_password3Authentification JWT
L'API utilise l'authentification JWT (JSON Web Token). Vous devez d'abord obtenir un token via l'endpoint POST /api/login, puis l'inclure dans l'en-tête Authorization: Bearer de toutes vos requêtes.
<?php
$apiUrl = getenv('ELYONPAY_API_URL');
function getToken(): string
{
global $apiUrl;
$ch = curl_init("$apiUrl/login");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode([
'username' => getenv('ELYONPAY_USERNAME'),
'password' => getenv('ELYONPAY_PASSWORD'),
'role' => 'ROLE_MERCHANT_ADMIN',
]),
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
throw new \RuntimeException("Login failed (HTTP $httpCode)");
}
$data = json_decode($response, true);
return $data['token'];
}Le token JWT a une durée de vie limitée. En production, stockez-le en cache (Redis, APCu) et renouvelez-le avant expiration. Le rôle ROLE_MERCHANT_ADMIN donne accès à toutes les opérations de paiement.
4Créer un lien de paiement
L'opération principale est la création d'un lien de paiement via POST /api/request-to-pay/payment/link. Vous envoyez le montant, le numéro de téléphone du client, la langue de la page et les URLs de redirection :
function createPaymentLink(string $token, array $order): string
{
global $apiUrl;
$ch = curl_init("$apiUrl/request-to-pay/payment/link");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer $token",
'Content-Type: application/json',
'Idempotency-Key: ' . $order['order_id'],
],
CURLOPT_POSTFIELDS => json_encode([
'amount' => $order['amount'],
'user_lang' => 'fr',
'msisdn' => $order['phone'],
'success_url' => 'https://votresite.com/paiement-reussi',
'error_url' => 'https://votresite.com/paiement-echec',
]),
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200 && $httpCode !== 201) {
throw new \RuntimeException("Payment link failed (HTTP $httpCode): $response");
}
$data = json_decode($response, true);
return $data['data']['payment_url'];
}L'en-tête Idempotency-Key évite les doublons en cas de retry réseau — utilisez votre référence de commande unique. Le paramètre user_lang (fr/en) détermine la langue de la page de paiement. Le champ msisdn est le numéro du client au format international.
5Rediriger le client
Une fois le lien de paiement obtenu, redirigez le client vers cette URL. Il effectue le paiement sur la page sécurisée ElyonPay (Mobile Money ou carte bancaire), puis est redirigé vers votre success_url ou error_url :
// Dans votre contrôleur de commande
$token = getToken();
$paymentUrl = createPaymentLink($token, [
'amount' => 5000,
'phone' => '+237691234567',
'order_id' => 'CMD-2026-042',
]);
// Sauvegarder la transaction en base avant la redirection
saveOrderPaymentPending('CMD-2026-042');
// Rediriger le client
header("Location: $paymentUrl");
exit;Important : ne vous fiez jamais uniquement à la redirection vers success_url pour valider un paiement. Un utilisateur pourrait accéder manuellement à cette URL. Vérifiez toujours le statut côté serveur (section suivante).
6Vérifier le statut d'une transaction
L'API ElyonPay utilise un modèle « pull » : c'est à vous de vérifier le statut de la transaction via GET /api/transactions/{id}. Appelez cet endpoint quand le client est redirigé vers votre success_url :
function getTransaction(string $token, string $transactionId): array
{
global $apiUrl;
$ch = curl_init("$apiUrl/transactions/$transactionId");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer $token",
'Accept: application/json',
],
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
throw new \RuntimeException("Transaction fetch failed (HTTP $httpCode)");
}
return json_decode($response, true);
}
// Vérification après redirection
$transaction = getTransaction($token, $transactionId);
$state = $transaction['data']['state'];
// Statuts : CREATED → PENDING → WAITING_FOR_PAYMENT → ACCEPTED → DELIVERED
if ($state === 'DELIVERED') {
markOrderAsPaid('CMD-2026-042');
} elseif (in_array($state, ['REJECTED', 'DECLINED', 'CANCELLED'])) {
markOrderAsFailed('CMD-2026-042');
}Ne considérez un paiement comme réussi qu'au statut DELIVERED. Vous pouvez aussi lister toutes vos transactions avec GET /api/transactions (paginé) pour la réconciliation comptable.
7Gestion des erreurs
L'API retourne des erreurs JSON avec des codes machine lisibles. Voici les erreurs les plus courantes :
| Code erreur | Signification | Action recommandée |
|---|---|---|
INSUFFICIENT_FUNDS | Solde Mobile Money insuffisant | Informer le client de recharger |
PHONE_INVALID | Numéro non enregistré / invalide | Demander au client de vérifier son numéro |
AMOUNT_TOO_LOW | Montant sous le minimum | Vérifier les minimums par devise |
TOKEN_EXPIRED | Token JWT expiré | Renouveler le token et réessayer |
function handleApiError(string $responseBody, int $httpCode): void
{
$error = json_decode($responseBody, true);
$code = $error['code'] ?? 'UNKNOWN';
match ($code) {
'INSUFFICIENT_FUNDS' => throw new PaymentException('Solde insuffisant'),
'PHONE_INVALID' => throw new PaymentException('Numéro invalide'),
'TOKEN_EXPIRED' => throw new AuthException('Token expiré'),
default => throw new ApiException("Erreur API [$code]: " . ($error['message'] ?? '')),
};
}8Classe helper complète
Voici une classe réutilisable qui encapsule toutes les opérations. Vous pouvez l'intégrer dans votre framework (Laravel, Symfony, etc.) :
class ElyonPayClient
{
private string $apiUrl;
private ?string $token = null;
public function __construct(string $apiUrl)
{
$this->apiUrl = rtrim($apiUrl, '/');
}
public function authenticate(string $username, string $password): void
{
$response = $this->request('POST', '/login', [
'username' => $username,
'password' => $password,
'role' => 'ROLE_MERCHANT_ADMIN',
], false);
$this->token = $response['token'];
}
public function createPaymentLink(int $amount, string $phone, string $orderId, string $lang = 'fr'): string
{
$response = $this->request('POST', '/request-to-pay/payment/link', [
'amount' => $amount,
'user_lang' => $lang,
'msisdn' => $phone,
'success_url' => getenv('APP_URL') . '/payment/success',
'error_url' => getenv('APP_URL') . '/payment/error',
], true, ['Idempotency-Key: ' . $orderId]);
return $response['data']['payment_url'];
}
public function getTransaction(string $id): array
{
return $this->request('GET', "/transactions/$id");
}
private function request(string $method, string $endpoint, array $body = [], bool $auth = true, array $extraHeaders = []): array
{
$ch = curl_init($this->apiUrl . $endpoint);
$headers = ['Content-Type: application/json', 'Accept: application/json'];
if ($auth && $this->token) {
$headers[] = "Authorization: Bearer {$this->token}";
}
$headers = array_merge($headers, $extraHeaders);
$opts = [CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => $headers];
if ($method === 'POST') {
$opts[CURLOPT_POST] = true;
$opts[CURLOPT_POSTFIELDS] = json_encode($body);
}
curl_setopt_array($ch, $opts);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode >= 400) {
handleApiError($response, $httpCode);
}
return json_decode($response, true);
}
}9Mode Sandbox vs Production
Le sandbox permet de tester sans frais réels. Le passage en production consiste uniquement à changer l'URL de base :
| Critère | Sandbox | Production |
|---|---|---|
| URL | api.elyonpay.net/api | api.elyonpay.org/api |
| Débits réels | Non | Oui |
| Numéros de test | Disponibles | N/A |
Le sandbox fournit des numéros de téléphone de test avec des comportements simulés (succès, fonds insuffisants, timeout) et des numéros de carte de test pour valider les différents scénarios. Testez exhaustivement avant de passer en production.
Checklist production : URL de base changée vers api.elyonpay.org, identifiants de production configurés, HTTPS sur votre serveur, vérification côté serveur du statut implémentée, gestion des erreurs en place, première transaction test réussie avec un petit montant.
10Bonnes pratiques de sécurité
Sécurisez votre intégration :
- Stockez vos identifiants dans des variables d'environnement (jamais dans le code source)
- Ne loguez jamais le token JWT dans vos logs applicatifs
- Utilisez exclusivement HTTPS — les requêtes HTTP sont rejetées par l'API
- Vérifiez toujours le statut de la transaction côté serveur (ne pas se fier à la redirection)
- Implémentez l'en-tête
Idempotency-Keypour éviter les paiements en double - Limitez les tentatives de paiement par session/IP pour prévenir les abus
Conclusion
Vous avez maintenant toutes les bases pour intégrer l'API ElyonPay en PHP : authentification JWT, création de liens de paiement, redirection du client et vérification des transactions. L'API unifie l'accès à tous les opérateurs Mobile Money (Orange Money, Wave, MTN MoMo, Moov, Airtel) et aux cartes bancaires dans 14 pays africains. Pour aller plus loin, consultez la documentation complète de l'API ElyonPay qui détaille l'ensemble des endpoints et des options disponibles.
Lancez-vous avec ElyonPay
Acceptez les paiements Mobile Money et cartes bancaires en quelques minutes.
Creer votre compte gratuit