Introduction

L'API MaliaPay vous permet d'accepter les paiements mobiles et bancaires en Côte d'Ivoire. Une seule intégration pour accéder à Wave, Orange Money, MTN MoMo, Moov, Djamo et les paiements par carte bancaire.

ℹ️ Base URL

https://business.malia.ci/api/v1

Format des requêtes

  • Toutes les requêtes sont en JSON
  • Header obligatoire : Content-Type: application/json
  • Authentification : Authorization: Bearer TOKEN

1. Authentification

L'API utilise Laravel Sanctum pour l'authentification. Vous devez d'abord obtenir un token Bearer en vous connectant, puis l'utiliser pour toutes les requêtes suivantes.

POST /api/auth/login

Corps de la requête

JSON
{ "email": "contact@votre-entreprise.ci", "password": "votre-mot-de-passe" }

Réponse succès (200)

JSON
{ "token": "1|aBcDeFgHiJkLmNoP...", "token_type": "Bearer", "user": { "id": 1, "name": "Mon Entreprise", "email": "contact@votre-entreprise.ci", "role": "merchant", "merchant_id": "MI_12345678" } }

Réponse erreur (401)

JSON
{ "message": "Identifiants incorrects.", "errors": { "email": ["Identifiants incorrects."] } }
⚠️ Important

Conservez le token en sécurité. Il expire automatiquement après une période d'inactivité. En cas d'expiration, effectuez une nouvelle requête de login.

2. Canaux de paiement

Utilisez ces codes pour spécifier le canal de paiement lors de la création d'une transaction.

CanalCode APITypeDescription
Wave CIWAVECIMobile MoneyPaiement via l'application Wave
Orange MoneyOMCIMobile MoneyPaiement via Orange Money CI
MTN MoMoMTNCIIMobile MoneyPaiement via MTN Mobile Money
Moov CIMOOVCIMobile MoneyPaiement via Moov Money
DjamoDJAMOMobile MoneyPaiement via l'application Djamo
PeyaPayPEYAPAYMobile MoneyPaiement via PeyaPay (avec OTP)
Carte BancaireCARDCartePaiement par carte Visa/Mastercard

3. Créer un paiement

Cet endpoint crée une transaction de paiement et retourne une URL de redirection pour le client final.

POST /api/v1/payments

Headers requis

Authorization: Bearer VOTRE_TOKEN Content-Type: application/json

Corps de la requête

JSON
{ "merchant_id": "MI_12345678", // Obligatoire - Votre ID Marchand "channel": "WAVECI", // Obligatoire - Code du canal "montant": 5000, // Obligatoire - Montant en FCFA "reference": "CMD-001", // Obligatoire - Votre référence commande "customer_name": "Jean Dupont", // Obligatoire - Nom du client "customer_phone_number": "0700000000", // Obligatoire - Téléphone client "customer_surname": "Dupont", // Optionnel - Prénom du client "customer_email": "client@email.com", // Optionnel "description": "Achat produit XYZ", // Optionnel "return_url": "https://monsite.ci/merci", // Optionnel - URL après paiement "notification_url": "https://monsite.ci/webhook" // Optionnel - URL webhook }
ℹ️ Où trouver votre Merchant ID ?

Connectez-vous à votre espace marchand → Paramètres → Informations du compte. Votre ID Marchand commence par MI_.

Réponse succès (200)

JSON
{ "success": true, "transaction_id": "TXN_abc123def456", "merchant_id": "MI_12345678", "reference": "CMD-001", "montant": 5000, "channel": "WAVECI", "status": "pending", "link": "https://business.malia.ci/pay/abc123def456", "message": "Transaction créée. Redirigez le client vers le lien." }
✅ Prochaine étape

Redirigez votre client vers l'URL retournée dans le champ link. Le client complètera le paiement directement avec l'opérateur.

Flux de paiement par canal

1

Wave, Orange, MTN, Moov

Redirection vers une page de confirmation. Le client valide sur son téléphone et retourne automatiquement.

2

PeyaPay

Nécessite une validation par OTP. Le client entre le code reçu par SMS sur la page de paiement.

3

Carte Bancaire

Redirection vers l'interface sécurisée de SycaPay pour saisie des informations de carte.

4. Vérifier le statut d'un paiement

Consultez le statut d'une transaction pour savoir si elle a été complétée, est en attente, ou a échoué.

GET /api/v1/payments/{transaction_id}

Exemple de requête

cURL
curl -X GET https://business.malia.ci/api/v1/payments/TXN_abc123def456 \
-H "Authorization: Bearer VOTRE_TOKEN" \
-H "Content-Type: application/json"

Réponse

JSON
{ "transaction_id": "TXN_abc123def456", "reference": "CMD-001", "montant": 5000, "channel": "WAVECI", "status": "completed", // pending, completed, failed, cancelled "customer_phone": "0700000000", "created_at": "2024-01-15T10:30:00Z", "updated_at": "2024-01-15T10:32:15Z" }

Statuts possibles

StatutDescription
pendingPaiement initié, en attente de confirmation client
completedPaiement confirmé et réussi
failedPaiement échoué (fonds insuffisants, erreur opérateur...)
cancelledPaiement annulé par le client ou expiré

5. Webhooks (Notifications)

Recevez des notifications en temps réel lorsqu'un paiement change de statut. Configurez votre URL webhook dans votre espace marchand.

ℹ️ Configuration

Dans votre espace marchand : Paramètres → Webhooks. Ajoutez l'URL de votre endpoint de réception.

Payload du webhook

JSON
{ "event": "payment.completed", "transaction_id": "TXN_abc123def456", "reference": "CMD-001", "montant": 5000, "channel": "WAVECI", "status": "completed", "customer_phone": "0700000000", "paid_at": "2024-01-15T10:32:15Z", "signature": "sha256=xxxxxxxxxxxxxxxx" }

Types d'événements

ÉvénementDescription
payment.pendingPaiement initié
payment.completedPaiement réussi
payment.failedPaiement échoué
payment.cancelledPaiement annulé

Vérification de la signature

Pour sécuriser vos webhooks, vérifiez la signature reçue dans l'en-tête ou le payload :

PHP
$signature = hash_hmac('sha256', json_encode($payload), $webhookSecret); $received = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE']; if (!hash_equals($signature, $received)) { http_response_code(401); exit; }
✅ Bonnes pratiques

Retournez toujours un HTTP 200 à la réception du webhook. Traitez les événements de manière idempotente (une transaction peut générer plusieurs webhooks).

6. Codes d'erreur

Code HTTPErreurDescription
400Bad RequestDonnées manquantes ou invalides
401UnauthorizedToken manquant ou invalide
403ForbiddenAccès non autorisé à cette ressource
404Not FoundTransaction ou ressource introuvable
422Validation ErrorErreur de validation des champs
429Too Many RequestsRate limit dépassé
500Server ErrorErreur serveur, réessayez plus tard

Format d'erreur standard

JSON
{ "message": "Le champ montant est requis.", "errors": { "montant": ["Le champ montant est requis."], "channel": ["Le canal sélectionné n'est pas valide."] } }

7. Exemples complets

Exemple PHP complet

PHP
class MaliaPayClient { private $baseUrl = 'https://business.malia.ci/api/v1'; private $token; // 1. Authentification public function login($email, $password) { $response = $this->request('POST', '/auth/login', [ 'email' => $email, 'password' => $password ]); $this->token = $response['token']; return $response; } // 2. Créer un paiement public function createPayment($data) { return $this->request('POST', '/payments', $data); } // 3. Vérifier statut public function getPayment($transactionId) { return $this->request('GET', "/payments/{$transactionId}"); } private function request($method, $path, $data = []) { $ch = curl_init($this->baseUrl . $path); $headers = ['Content-Type: application/json']; if ($this->token) { $headers[] = "Authorization: Bearer {$this->token}"; } curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => $method, CURLOPT_HTTPHEADER => $headers, CURLOPT_POSTFIELDS => json_encode($data) ]); $result = json_decode(curl_exec($ch), true); curl_close($ch); return $result; } } // Utilisation $client = new MaliaPayClient(); $client->login('contact@entreprise.ci', 'motdepasse'); $payment = $client->createPayment([ 'merchant_id' => 'MI_12345678', // Votre ID Marchand 'channel' => 'WAVECI', 'montant' => 5000, 'reference' => 'CMD-001', 'customer_name' => 'Jean Dupont', 'customer_phone_number' => '0700000000' ]); // Rediriger le client header("Location: {$payment['link']}");

Exemple JavaScript (Node.js)

JavaScript
const createPayment = async () => { // 1. Login pour obtenir le token const loginRes = await fetch('https://business.malia.ci/api/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: 'contact@entreprise.ci', password: 'motdepasse' }) }); const { token } = await loginRes.json(); // 2. Créer le paiement const paymentRes = await fetch('https://business.malia.ci/api/v1/payments', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify({ merchant_id: 'MI_12345678', // Votre ID Marchand channel: 'WAVECI', montant: 5000, reference: 'CMD-001', customer_name: 'Jean Dupont', customer_phone_number: '0700000000' }) }); const payment = await paymentRes.json(); // 3. Rediriger vers la page de paiement window.location.href = payment.link; };

Exemple Python

Python
import requests BASE_URL = "https://business.malia.ci/api/v1" # 1. Authentification login_res = requests.post(f"{BASE_URL}/auth/login", json={ "email": "contact@entreprise.ci", "password": "motdepasse" }) token = login_res.json()["token"] # 2. Créer un paiement headers = {"Authorization": f"Bearer {token}"} payment_res = requests.post( f"{BASE_URL}/payments", headers=headers, json={ "merchant_id": "MI_12345678", # Votre ID Marchand "channel": "WAVECI", "montant": 5000, "reference": "CMD-001", "customer_name": "Jean Dupont", "customer_phone_number": "0700000000" } ) payment = payment_res.json() print(f"Rediriger vers: {payment['link']}")

Support & Contact

Besoin d'aide pour l'intégration ? Notre équipe technique est disponible pour vous accompagner.

Une solution proposée par Lkmdigital