Guide marchand

Production
Guide marchand
7 procédures pour intégrer et exploiter Neka Paie côté marchand.

1. Récupérer mes clés API

Vos clés sont délivrées à la création de votre compte par l'équipe Neka Paie.

Étapes
  1. Vous connecter à votre espace marchand avec vos identifiants.
  2. Aller dans Clés API dans le menu latéral.
  3. Vos clés sont normalement déjà transmises lors de l'onboarding. En cas d'oubli ou de fuite suspectée :
    • Cliquer sur « Régénérer mes clés API ».
    • 📋 Copier immédiatement l'API Key et l'API Secret affichés.
  4. Stocker dans un coffre-fort (AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault).
Ne jamais committer l'API Secret dans un dépôt Git ni l'embarquer dans une app mobile/SPA publique.

2. Configurer mon URL webhook

Votre serveur recevra une notification HTTP POST à chaque changement d'état terminal.

Étapes
  1. Aller dans Clés API.
  2. Dans le bloc « URL Webhook », saisir l'URL HTTPS publique de votre endpoint :
    https://api.votreentreprise.com/webhooks/nekapay
  3. Cliquer sur « Enregistrer ».
  4. L'URL peut être surchargée requête par requête via le champ notify_url dans le body JSON.
Exigences
  • HTTPS obligatoire (TLS 1.2 minimum)
  • Certificat SSL valide (pas auto-signé)
  • Réponse en moins de 3 secondes (mettre en queue le traitement)
  • Renvoyer un statut 2xx pour acquitter la réception

3. Initier mon premier paiement (Cash-In)

Encaisser un paiement client via Orange Money.

Workflow
  1. Côté votre site/app, le client clique sur « Payer avec Orange Money ».
  2. Votre backend appelle POST /api/v1/payments/cashin avec le body signé HMAC.
  3. Vous recevez une réponse 202 avec une payment_url.
  4. Vous redirigez le client vers cette URL.
  5. Le client saisit son PIN sur la page Orange.
  6. Vous recevez un webhook avec le statut final.
Exemple PHP complet
PHP<?php
$apiKey = getenv('NEKAPAY_API_KEY');
$apiSecret = getenv('NEKAPAY_API_SECRET');
$apiBase = 'https://nekapaie.com/api/v1';

$payload = [
    'merchant_order_id' => 'order_' . uniqid(),
    'amount' => 50000,           // 500 XOF en centimes
    'currency' => 'XOF',
    'customer_msisdn' => '+22376123456',
    'country_code' => 'ML',
    'return_url' => 'https://shop.example.com/checkout/success',
    'notify_url' => 'https://api.example.com/webhooks/nekapay',
    'metadata' => ['order_id' => 1234, 'user_id' => 5678],
];

$body = json_encode($payload);
$timestamp = (string) time();
$signature = hash_hmac('sha256', $timestamp . $body, $apiSecret);

$ch = curl_init($apiBase . '/payments/cashin');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $body,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'X-NekaPay-Key: ' . $apiKey,
        'X-NekaPay-Timestamp: ' . $timestamp,
        'X-NekaPay-Signature: ' . $signature,
    ],
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$data = json_decode($response, true);

if ($httpCode === 202) {
    header('Location: ' . $data['data']['payment_url']);
    exit;
}

4. Recevoir et vérifier un webhook

Sur votre URL notify_url, vous recevez un POST signé HMAC.

Étapes côté serveur
  1. Lire les en-têtes X-NekaPay-Signature et X-NekaPay-Timestamp.
  2. Vérifier que le timestamp est dans une fenêtre de ±300 secondes (anti-replay).
  3. Recalculer la signature HMAC-SHA256 avec votre API Secret.
  4. Comparer avec hash_equals() (résistant au timing attack).
  5. Traiter l'événement et renvoyer un statut 2xx.
Exemple PHP de handler
PHP<?php
$apiSecret = getenv('NEKAPAY_API_SECRET');

$timestamp = $_SERVER['HTTP_X_NEKAPAY_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_X_NEKAPAY_SIGNATURE'] ?? '';
$body = file_get_contents('php://input');

// 1. Anti-replay
if (!$timestamp || abs(time() - (int)$timestamp) > 300) {
    http_response_code(401);
    exit;
}

// 2. Vérification de signature
$expected = hash_hmac('sha256', $timestamp . $body, $apiSecret);
if (!hash_equals($expected, $signature)) {
    http_response_code(401);
    exit;
}

// 3. Traitement
$event = json_decode($body, true);

switch ($event['status']) {
    case 'SUCCESS':
        markOrderAsPaid($event['merchant_order_id']);
        break;
    case 'FAILED':
    case 'EXPIRED':
        markOrderAsFailed($event['merchant_order_id'], $event['status']);
        break;
    case 'REVERSED':
        refundOrder($event['merchant_order_id']);
        break;
}

http_response_code(200);
echo json_encode(['received' => true]);

5. Effectuer un Cash-Out (payout)

Reverser des fonds vers le wallet d'un bénéficiaire (remboursement, gain, salaire).

Pré-requis
  • Solde suffisant sur la filiale concernée (consulter mes soldes)
  • Pour un montant ≥ cashout_approval_threshold (défaut 1 000 000 XOF), validation à deux yeux requise côté Neka Paie.
Exemple
PHP$payload = [
    'merchant_order_id' => 'payout_' . uniqid(),
    'amount' => 100000,
    'beneficiary_msisdn' => '+22376987654',
    'currency' => 'XOF',
    'reason' => 'Gain de la session du 28/04',
];

// Même signature HMAC + POST sur /api/v1/payments/cashout

6. Exporter mes transactions

Pour la comptabilité, l'audit ou la réconciliation interne.

Méthode 1 : depuis le portail web
  1. Menu Mes transactions.
  2. Appliquer les filtres (statut, type, dates).
  3. Cliquer sur Export.
Méthode 2 : via API
BASH# Format JSON
GET /api/v1/transactions/export?date_from=2026-04-01&date_to=2026-04-30

# Format CSV
GET /api/v1/transactions/export?date_from=2026-04-01&date_to=2026-04-30&format=csv

7. Consulter mes soldes par filiale

Le solde évolue en fonction des Cash-In encaissés (+) et Cash-Out reversés (-).

Méthode 1 : portail
  1. Aller dans Soldes.
  2. Une carte par filiale active avec le solde disponible.
Méthode 2 : API
JSONGET /api/v1/balances

→ {
  "data": [
    {
      "country_code": "ML",
      "country_name": "Mali",
      "currency": "XOF",
      "available_balance": 8750000,
      "pending_balance": 125000
    }
  ]
}