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
{
"email": "contact@votre-entreprise.ci",
"password": "votre-mot-de-passe"
}
Réponse succès (200)
{
"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)
{
"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.
| Canal | Code API | Type | Description |
| Wave CI | WAVECI | Mobile Money | Paiement via l'application Wave |
| Orange Money | OMCI | Mobile Money | Paiement via Orange Money CI |
| MTN MoMo | MTNCII | Mobile Money | Paiement via MTN Mobile Money |
| Moov CI | MOOVCI | Mobile Money | Paiement via Moov Money |
| Djamo | DJAMO | Mobile Money | Paiement via l'application Djamo |
| PeyaPay | PEYAPAY | Mobile Money | Paiement via PeyaPay (avec OTP) |
| Carte Bancaire | CARD | Carte | Paiement 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
{
"merchant_id": "MI_12345678",
"channel": "WAVECI",
"montant": 5000,
"reference": "CMD-001",
"customer_name": "Jean Dupont",
"customer_phone_number": "0700000000",
"customer_surname": "Dupont",
"customer_email": "client@email.com",
"description": "Achat produit XYZ",
"return_url": "https://monsite.ci/merci",
"notification_url": "https://monsite.ci/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)
{
"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 -X GET https://business.malia.ci/api/v1/payments/TXN_abc123def456 \
-H "Authorization: Bearer VOTRE_TOKEN" \
-H "Content-Type: application/json"
Réponse
{
"transaction_id": "TXN_abc123def456",
"reference": "CMD-001",
"montant": 5000,
"channel": "WAVECI",
"status": "completed",
"customer_phone": "0700000000",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:32:15Z"
}
Statuts possibles
| Statut | Description |
| pending | Paiement initié, en attente de confirmation client |
| completed | Paiement confirmé et réussi |
| failed | Paiement échoué (fonds insuffisants, erreur opérateur...) |
| cancelled | Paiement 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
{
"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énement | Description |
payment.pending | Paiement initié |
payment.completed | Paiement réussi |
payment.failed | Paiement échoué |
payment.cancelled | Paiement 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 :
$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 HTTP | Erreur | Description |
| 400 | Bad Request | Données manquantes ou invalides |
| 401 | Unauthorized | Token manquant ou invalide |
| 403 | Forbidden | Accès non autorisé à cette ressource |
| 404 | Not Found | Transaction ou ressource introuvable |
| 422 | Validation Error | Erreur de validation des champs |
| 429 | Too Many Requests | Rate limit dépassé |
| 500 | Server Error | Erreur serveur, réessayez plus tard |
Format d'erreur standard
{
"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
class MaliaPayClient {
private $baseUrl = 'https://business.malia.ci/api/v1';
private $token;
public function login($email, $password) {
$response = $this->request('POST', '/auth/login', [
'email' => $email,
'password' => $password
]);
$this->token = $response['token'];
return $response;
}
public function createPayment($data) {
return $this->request('POST', '/payments', $data);
}
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;
}
}
$client = new MaliaPayClient();
$client->login('contact@entreprise.ci', 'motdepasse');
$payment = $client->createPayment([
'merchant_id' => 'MI_12345678',
'channel' => 'WAVECI',
'montant' => 5000,
'reference' => 'CMD-001',
'customer_name' => 'Jean Dupont',
'customer_phone_number' => '0700000000'
]);
header("Location: {$payment['link']}");
Exemple JavaScript (Node.js)
const createPayment = async () => {
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();
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',
channel: 'WAVECI',
montant: 5000,
reference: 'CMD-001',
customer_name: 'Jean Dupont',
customer_phone_number: '0700000000'
})
});
const payment = await paymentRes.json();
window.location.href = payment.link;
};
Exemple Python
import requests
BASE_URL = "https://business.malia.ci/api/v1"
login_res = requests.post(f"{BASE_URL}/auth/login", json={
"email": "contact@entreprise.ci",
"password": "motdepasse"
})
token = login_res.json()["token"]
headers = {"Authorization": f"Bearer {token}"}
payment_res = requests.post(
f"{BASE_URL}/payments",
headers=headers,
json={
"merchant_id": "MI_12345678",
"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']}")