v1.0
Se connecter

API Marchand GeniusPay

Intégrez les paiements mobiles (Wave, Orange Money, MTN Money) et par carte dans vos applications en quelques minutes.

Base URL
https://pay.genius.ci/api/v1/merchant
🧪

Sandbox

Testez votre intégration sans frais. Les transactions sont simulées.

Production

Transactions réelles. Activez le mode live dans vos paramètres.

Authentification

Toutes les requêtes doivent inclure vos clés API dans les headers HTTP.

Header Description
X-API-Key Votre clé publique (pk_sandbox_... ou pk_live_...)
X-API-Secret Votre clé secrète (sk_sandbox_... ou sk_live_...)
Content-Type application/json

Exemple avec cURL

curl -X POST https://pay.genius.ci/api/v1/merchant/payments \
  -H "X-API-Key: pk_sandbox_xxxxxxxx" \
  -H "X-API-Secret: sk_sandbox_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"amount": 5000, "customer": {"phone": "+221771234567"}}'

Démarrage rapide - 2 lignes de code

La façon la plus simple d'intégrer GeniusPay. Créez un paiement et redirigez votre client vers notre page de checkout sécurisée où il choisira son moyen de paiement.

✨ Intégration minimale

// 1. Créer le paiement (sans spécifier payment_method)
$response = Http::withHeaders([
    'X-API-Key' => 'pk_live_xxx',
    'X-API-Secret' => 'sk_live_xxx',
])->post('https://pay.genius.ci/api/v1/merchant/payments', [
    'amount' => 15000,
    'description' => 'Commande #123',
]);

// 2. Rediriger vers la page de checkout GeniusPay
return redirect($response['data']['checkout_url']);

Rapide

Intégration en 2 lignes, aucune logique de paiement à gérer

Sécurisé

Page de checkout hébergée et sécurisée par GeniusPay

Tous les moyens

Wave, Orange, MTN, Moov, Cartes bancaires

Comment ça marche ?

En omettant le paramètre payment_method, GeniusPay génère une URL vers notre page de checkout personnalisée. Votre client y choisira son moyen de paiement préféré. Une fois le paiement effectué, il sera redirigé et vous recevrez un webhook.

POST

Initier un paiement

Crée une nouvelle transaction et retourne une URL de paiement.

/payments

Paramètres

Paramètre Type Requis Description
amount number Montant en XOF (min: 200)
currency string - Devise (défaut: XOF)
payment_method string - wave, paystack, orange_money, mtn_money
description string - Description du paiement (max 500 car.)
customer.name string - Nom du client
customer.email string - Email du client
customer.phone string - Téléphone du client
success_url string - URL de redirection après succès
error_url string - URL de redirection après échec
metadata object - Données personnalisées

Requête

{
  "amount": 15000,
  "payment_method": "wave",
  "description": "Commande #12345",
  "customer": {
    "name": "Amadou Diallo",
    "email": "amadou@example.com",
    "phone": "+221771234567"
  },
  "metadata": {
    "order_id": "12345"
  }
}

Réponse 201

{
  "success": true,
  "data": {
    "id": 456,
    "reference": "MTX-A1B2C3D4E5",
    "amount": 15000,
    "fees": 450,
    "net_amount": 14550,
    "status": "pending",
    "payment_url": "https://wave.com/...",
    "gateway": "wave",
    "environment": "sandbox"
  }
}
PAGE

Page de Checkout GeniusPay

Quand vous initiez un paiement sans spécifier de payment_method, l'API retourne une checkout_url vers notre page de paiement hébergée.

Aperçu de la page de checkout
🏪

Paiement sécurisé

Votre Boutique

15 000 FCFA
Wave
Wave
Orange Money
Orange Money
MTN MoMo
MTN MoMo
Mastercard
Carte bancaire

Réponse API (mode checkout)

{
  "success": true,
  "data": {
    "id": 123,
    "reference": "MTX-A1B2C3D4E5",
    "amount": 15000,
    "currency": "XOF",
    "status": "pending",
    "checkout_url": "https://pay.genius.ci/checkout/MTX-A1B2C3D4E5",
    "payment_url": "https://pay.genius.ci/checkout/MTX-A1B2C3D4E5",
    "environment": "sandbox",
    "expires_at": "2024-12-16T14:00:00.000000Z"
  }
}

✅ Avantages

  • • Aucune gestion des moyens de paiement côté client
  • • Interface optimisée pour la conversion
  • • Mise à jour automatique des providers
  • • Design responsive (mobile/desktop)

📌 Bon à savoir

  • • Le lien expire après 24 heures
  • • Webhooks envoyés après paiement
  • • Redirection vers success_url/error_url
  • • Compatible sandbox et production
GET

Lister les paiements

/payments

Paramètres de query

Paramètre Description
status Filtrer par statut (pending, completed, failed)
from Date de début (YYYY-MM-DD)
to Date de fin (YYYY-MM-DD)
per_page Résultats par page (défaut: 20, max: 100)
GET

Récupérer un paiement

/payments/{reference}
GET

Informations du compte

/account
GET

Solde du compte

/account/balance
{
  "success": true,
  "data": {
    "available": 1250000,
    "pending": 75000,
    "total": 1325000,
    "currency": "XOF"
  }
}

Webhooks

Recevez des notifications en temps réel sur les événements de vos paiements. L'intégration webhook est identique pour Sandbox et Live, seules les clés changent.

🔑 Sandbox vs Live

Aspect Sandbox Live
Secret Webhook whsec_sandbox_xxx whsec_live_xxx
Header Environment X-Webhook-Environment: sandbox X-Webhook-Environment: live
Payload Field "environment": "sandbox" "environment": "live"
Code d'intégration ✅ Identique ✅ Identique
GET /webhooks Lister les webhooks
POST /webhooks Créer un webhook
PUT /webhooks/{id} Modifier un webhook
DELETE /webhooks/{id} Supprimer un webhook
POST /webhooks/{id}/test Tester un webhook

Événements webhook

Événement Description
payment.initiated Paiement initié
payment.success Paiement réussi
payment.failed Paiement échoué
payment.cancelled Paiement annulé
payment.refunded Paiement remboursé
payment.expired Paiement expiré
cashout.requested Demande de retrait
cashout.approved Retrait approuvé
cashout.completed Retrait complété
cashout.failed Retrait échoué
webhook.test Test de webhook

Configuration Webhook

✅ Créer un webhook

curl -X POST https://api.geniuspay.ci/merchant/webhooks \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Mon webhook",
    "url": "https://example.com/webhooks/geniuspay",
    "events": ["payment.success", "payment.failed", "cashout.completed"]
  }'

Le secret webhook sera retourné uniquement à la création. Conservez-le précieusement!

Payload webhook

Le payload est identique pour Sandbox et Live. Seul le champ "environment" change.

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "event": "payment.success",
  "timestamp": 1735587600,
  "created_at": "2025-12-30T12:00:00.000000Z",
  "data": {
    "object": "transaction",
    "id": 12345,
    "reference": "TXN-2025-001",
    "amount": 10000.00,
    "currency": "XOF",
    "fees": 250.00,
    "net_amount": 9750.00,
    "status": "completed",
    "payment_method": "mobile_money",
    "provider": "wave",
    "customer_name": "Jean Kouassi",
    "customer_phone": "+2250748123456",
    "merchant_id": 25,
    "metadata": {
      "order_id": "ORD-2025-123",
      "customer_email": "jean@example.com"
    }
  },
  "environment": "live",
  "api_version": "2024-01-01"
}

Sécurité des webhooks

Vérifiez toujours la signature des webhooks pour vous assurer qu'ils proviennent bien de GeniusPay.

Important

Ne traitez jamais un webhook sans vérifier sa signature.

Headers webhook

Header Description
Content-Type application/json
X-Webhook-Signature Signature HMAC-SHA256
X-Webhook-Timestamp Timestamp Unix de l'envoi
X-Webhook-Event Type d'événement
X-Webhook-Delivery ID unique de livraison (optionnel)
X-Webhook-Environment sandbox ou live
User-Agent GeniusPay-Webhook/1.0

Vérification de la signature

Format: signature = HMAC-SHA256(timestamp + "." + json_payload, secret)

// Récupérer les headers
$signature = $request->header('X-Webhook-Signature');
$timestamp = $request->header('X-Webhook-Timestamp');
$event = $request->header('X-Webhook-Event');

// Récupérer le payload JSON
$payload = $request->all();

// Construire la donnée à vérifier
$data = $timestamp . '.' . json_encode($payload);

// Calculer la signature attendue
$secret = 'whsec_xxxxxxxx'; // Votre clé secrète webhook
$expectedSignature = hash_hmac('sha256', $data, $secret);

// Vérifier la signature
if (!hash_equals($expectedSignature, $signature)) {
    return response()->json([
        'status' => 401,
        'detail' => 'Invalid signature'
    ], 401);
}

// Vérifier le timestamp (protection replay attack)
if (abs(time() - (int)$timestamp) > 300) { // 5 minutes
    return response()->json([
        'status' => 400,
        'detail' => 'Timestamp too old'
    ], 400);
}

// Traiter l'événement selon son type
switch ($event) {
    case 'payment.success':
        // Marquer la commande comme payée
        break;
    case 'payment.failed':
        // Notifier le client
        break;
}

📘 Documentation complète: Consultez le Guide d'Intégration Webhook pour des exemples en PHP, Node.js, Python et Java.

Statuts des paiements

pending

En attente de paiement

processing

En cours de traitement

completed

Paiement réussi

failed

Paiement échoué

cancelled

Paiement annulé

refunded

Paiement remboursé

Méthodes de paiement

Code Nom Pays
wave Wave SN, CI, ML, BF
orange_money Orange Money SN, CI, ML, BF
mtn_money MTN Mobile Money CI, BF
card Carte bancaire (Visa, Mastercard) International

Conseil

Omettez le paramètre payment_method pour laisser le client choisir sur la page de checkout GeniusPay. C'est l'approche recommandée pour maximiser les conversions.

Codes d'erreur

Code HTTP Description
MISSING_API_KEY 401 Clé API manquante
INVALID_API_KEY 401 Clé API invalide
MERCHANT_INACTIVE 403 Compte désactivé
PAYMENT_INIT_FAILED 400 Échec d'initialisation
TRANSACTION_NOT_FOUND 404 Transaction introuvable
VALIDATION_ERROR 422 Données invalides

Exemples d'intégration

RECOMMANDÉ

Mode Checkout (2 lignes)

Sans payment_method, le client choisit son moyen de paiement sur la page GeniusPay.

// Intégration en 2 lignes avec le SDK Laravel
$payment = GeniusPay::checkout(15000, 'Commande #123');
return redirect($payment->checkoutUrl);

// Ou avec Http natif
$response = Http::withHeaders([
    'X-API-Key' => 'pk_live_xxx',
    'X-API-Secret' => 'sk_live_xxx',
])->post('https://pay.genius.ci/api/v1/merchant/payments', [
    'amount' => 15000,
    'description' => 'Commande #123',
    // PAS de payment_method = Page checkout GeniusPay
]);

return redirect($response['data']['checkout_url']);
// Intégration simplifiée
const response = await fetch('https://pay.genius.ci/api/v1/merchant/payments', {
  method: 'POST',
  headers: {
    'X-API-Key': 'pk_live_xxx',
    'X-API-Secret': 'sk_live_xxx',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    amount: 15000,
    description: 'Commande #123',
    // PAS de payment_method = Page checkout GeniusPay
  }),
});

const { data } = await response.json();
window.location.href = data.checkout_url;
# Intégration simplifiée
import requests

response = requests.post(
    'https://pay.genius.ci/api/v1/merchant/payments',
    headers={
        'X-API-Key': 'pk_live_xxx',
        'X-API-Secret': 'sk_live_xxx',
    },
    json={
        'amount': 15000,
        'description': 'Commande #123',
        # PAS de payment_method = Page checkout GeniusPay
    }
)

checkout_url = response.json()['data']['checkout_url']
# Rediriger le client vers checkout_url
// Intégration en 2 lignes avec le SDK Flutter
final payment = await geniusPay.checkout(
  amount: 15000, 
  description: 'Commande #123',
);
launchUrl(Uri.parse(payment.checkoutUrl!));
ALTERNATIF

Mode Direct (méthode spécifiée)

Avec payment_method spécifié, redirection directe vers le gateway.

$response = Http::withHeaders([
    'X-API-Key' => 'pk_live_xxx',
    'X-API-Secret' => 'sk_live_xxx',
])->post('https://pay.genius.ci/api/v1/merchant/payments', [
    'amount' => 15000,
    'payment_method' => 'wave', // Redirection directe vers Wave
    'customer' => [
        'phone' => '+221771234567',
    ],
]);

return redirect($response['data']['payment_url']);
const response = await fetch('https://pay.genius.ci/api/v1/merchant/payments', {
  method: 'POST',
  headers: {
    'X-API-Key': 'pk_live_xxx',
    'X-API-Secret': 'sk_live_xxx',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    amount: 15000,
    payment_method: 'wave', // Redirection directe vers Wave
    customer: { phone: '+221771234567' },
  }),
});

const { data } = await response.json();
window.location.href = data.payment_url;