BURIDA

API de gestion des factures et paiements Mobile Money & Bancaire

EBENYX TECHNOLOGIES

API Opérationnelle

Version

Version stable de l'API avec toutes les fonctionnalités de production.

Version: 1.0.0
Framework: Quarkus 3.26.2
Java: 21 LTS

Sécurité

API sécurisée avec authentification HMAC-SHA256 et rate limiting.

Auth: HMAC-SHA256
Rate Limit: 30 req/min
TLS: Support HTTPS

Performance

Architecture optimisée avec cache Redis et pagination intelligente.

Cache: Redis/Caffeine
Latence: < 100ms
Throughput: 1000+ req/s

Ressources & Documentation

Documentation Interactive

Explorez et testez l'API directement depuis l'interface Swagger UI.

Ouvrir Swagger UI

Collection Postman

Collection Postman prête à l'emploi avec exemples et tests.

Télécharger Collection

Documentation Technique

Architecture, diagrammes et spécifications techniques détaillées.

Consulter

Découvrir l'API

Guide complet avec exemples d'utilisation et génération HMAC.

Explorer l'API

🔐 Découverte de l'API - Guide Complet

Génération de la Signature HMAC (Stratégie FIELDS)

La stratégie FIELDS est recommandée car elle ne signe que les champs critiques, offrant performance et sécurité optimales.

Structure de la signature FIELDS
# Format de la chaîne à signer :
METHOD|PATH|TIMESTAMP|field1=value1|field2=value2|...

# Exemple concret :
GET|/api/1200263/factures-non-soldees|1757580100
GET|/api/tarifs/evenements-occasionnels|1757580100
POST|/api/webhook/{client}/paiement|1757580100|idTransaction=TRX123456
POST|/api/webhook/{client}/paiement-occasionnel|1757580100|idTransaction=TXN1757494924308

# Headers requis :
X-HMAC-Signature: /iQRSEtLBjaNWrpVJY+i1KYg5uAofWcGW0ppvswnFCI=
X-Timestamp: 1757580100
X-Client-Id: orange-money-client

# Headers facultatif :
X-Signature-Strategy: FIELDS

Exemple GET - Consultation des Factures Non Soldées

✅ Cas Positif

# Requête valide avec HMAC correct
GET /api/1200263/factures-non-soldees?page=0&size=20
Headers:
  X-HMAC-Signature: /iQRSEtLBjaNWrpVJY+i1KYg5uAofWcGW0ppvswnFCI=
  X-Timestamp: 1757580100
  X-Client-Id: orange-money-client
  Accept: application/json

# Réponse 200 OK
{
  "client": {
    "identifiant": "1200263",
    "etablissement": "CAFE DE LA PAIX"
  },
  "factures": [
    {
      "numero": "2018/01/0014566",
      "libelle": "Redevance janvier 2018",
      "montant": 100,
      "status": "non-solde"
    },
    {
      "numero": "2025070005",
      "libelle": "Redevance juillet 2025",
      "montant": 9000,
      "status": "non-solde"
    }
  ],
  "pagination": {
    "page": 0,
    "size": 20,
    "totalElements": 2
  }
}

❌ Cas Négatif

# Requête avec signature invalide
GET /api/1200263/factures-non-soldees
Headers:
  X-HMAC-Signature: SIGNATURE_INVALIDE
  X-Timestamp: 1757580100
  X-Client-Id: orange-money-client

# Réponse 401 Unauthorized
{
  "error": "INVALID_SIGNATURE",
  "message": "Signature HMAC invalide",
  "timestamp": "2025-01-11T08:30:00Z"
}

# Autres erreurs possibles :
# - 404: Client non trouvé
# - 400: Paramètres de pagination invalides
# - 401: Timestamp expiré (> 5 min)
# - 500: Erreur système

Exemple POST - Webhook de Paiement Régulier

✅ Cas Positif

# Requête valide avec body complet
POST /api/webhook/orange/paiement
Headers:
  X-HMAC-Signature: HJNX3LSzG0rtXFXJtRrCTFAZQ4jUXxGbUWdAVuSbExM=
  X-Timestamp: 1757580551
  X-Client-Id: orange-money-client
  Content-Type: application/json

Body:
{
  "commande": {
    "idTransaction": "TXN1757494924190",
    "clientReference": "1200263",
    "dateTransaction": "2025-09-10T09:16:49.425Z",
    "commentaire": "Paiement de factures"
  },
  "nonSoldees": [
    {
      "numeroFacture": "2018/01/0014566",
      "montant": 100
    },
    {
      "numeroFacture": "2025070005",
      "montant": 9000
    }
  ]
}

# Réponse 200 OK
{
  "status": "success",
  "message": "Paiement traité avec succès",
  "reglementId": "REG-2025-001",
  "numeroQuittance": "QUIT-2025-001",
  "montantTotal": 9100,
  "facturesTraitees": 2
}

❌ Cas Négatif

# Body malformé ou invalide
POST /api/webhook/orange/paiement
Headers:
  X-HMAC-Signature: HJNX3LSzG0rtXFXJtRrCTFAZQ4jUXxGbUWdAVuSbExM=
  X-Timestamp: 1757580551
  X-Client-Id: orange-money-client

Body:
{
  // Commande manquante!
  "nonSoldees": [{
    "numeroFacture": "2018/01/0014566",
    "montant": 100
  }]
}

# Réponse 400 Bad Request
{
  "error": "VALIDATION_ERROR",
  "message": "Commande de paiement manquante",
  "details": {
    "field": "commande",
    "constraint": "NotNull"
  }
}

# Autres erreurs possibles :
# - 409: Transaction déjà existante
# - 404: Client ou factures non trouvés
# - 422: Erreur de traitement métier
# - 500: Erreur système

Exemple GET - Consultation Grille Tarifaire des Événements

# Récupération de la grille tarifaire pour les paiements occasionnels
GET /api/tarifs/evenements-occasionnels
Headers:
  X-HMAC-Signature: Xg/dPiBpy7Atq4UPaySWTM8LcvQTi9JXOUxTZakSIZQ=
  X-Timestamp: 1761825016
  X-Client-Id: orange-money-client
  Accept: application/json

# Réponse 200 OK
{
  "tarifs": [
    {
      "id": 6,
      "code": "ANIMATION_ENTREPRISE",
      "libelle": "Animation promotionnelle (entreprises, supermarchés, grandes surfaces, PME, secteur informel)",
      "tarif": 65000,
      "categorie": "ANIMATION_PROMOTIONNELLE",
      "description": "Animation sur site pour entreprises, commerces et PME"
    },
    {
      "id": 5,
      "code": "ANIMATION_CARAVANE",
      "libelle": "Animation promotionnelle – CARAVANE (voiture, camionnette, camion, etc.)",
      "tarif": 130000,
      "categorie": "ANIMATION_PROMOTIONNELLE",
      "description": "Animation mobile avec véhicule (voiture, camionnette, camion)"
    },
    {
      "id": 4,
      "code": "BAPTEME",
      "libelle": "Baptême",
      "tarif": 5000,
      "categorie": "CEREMONIE",
      "description": "Prestation pour baptême"
    },
    {
      "id": 3,
      "code": "ANNIVERSAIRE",
      "libelle": "Anniversaire",
      "tarif": 5000,
      "categorie": "CEREMONIE",
      "description": "Prestation pour anniversaire"
    },
    {
      "id": 2,
      "code": "MARIAGE_INTERIEUR",
      "libelle": "Mariage / Dot (Intérieur)",
      "tarif": 20000,
      "categorie": "CEREMONIE",
      "description": "Prestation pour mariage ou dot à l'intérieur du pays (hors Abidjan)"
    },
    {
      "id": 1,
      "code": "MARIAGE_ABIDJAN",
      "libelle": "Mariage / Dot (District d'Abidjan et Assinie)",
      "tarif": 30000,
      "categorie": "CEREMONIE",
      "description": "Prestation pour mariage ou dot dans le district d'Abidjan et à Assinie"
    }
  ],
  "dateMAJ": "2025-10-30",
  "devise": "FCFA",
  "count": 6
}

Exemple POST - Paiement Occasionnel

# Paiement ponctuel multi-client avec tarif événement
POST /api/webhook/{client}/paiement-occasionnel
Headers:
  X-HMAC-Signature: HJNX3LSzG0rtXFXJtRrCTFAZQ4jUXxGbUWdAVuSbExM=
  X-Timestamp: 1757580551
  X-Client-Id: orange-money-client
  Content-Type: application/json

Body:
{
  "idTransaction": "TXN1757494924308",
  "commentaire": "Paiement ponctuel",
  "contact": "+2250712345678",
  "description": "Prestation musicale",
  "tarifEvenementId": 1,
  "montant": 30000
}

# Réponse 200 OK
{
  "status": "success",
  "message": "Payment processed successfully",
  "reglementId": 656387,
  "numeroQuittance": "TXN1757494924308",
  "montantTotal": "30000.0",
  "tarifEvenementDTO": {
    "code": "MARIAGE_ABIDJAN",
    "tarif": 30000,
    "description": "Prestation pour mariage ou dot dans le district d'Abidjan et à Assinie"
  },
  "facturesTraitees": [
    {
      "numeroFacture": "OCC-20251030-165555-764",
      "montantPaye": "30000.0",
      "nouveauSolde": "0.0"
    }
  ],
  "success": true
}

Documentation des Routes Principales

Endpoint Méthode Description Champs HMAC
/api/tarifs/evenements-occasionnels GET Consultation de la grille tarifaire des événements occasionnels (filtre optionnel ?categorie=CEREMONIE) -
/api/tarifs/evenements-occasionnels/{code} GET Consultation d'un tarif événement par son code (ex: MARIAGE_ABIDJAN, ANIMATION_CARAVANE) code (path)
/api/{codeClient}/factures-non-soldees GET Consultation des factures non soldées codeClient (path)
/api/webhook/{client}/paiement POST Traitement paiement régulier multi-client idTransaction
/api/webhook/{client}/paiement-occasionnel POST Paiement occasionnel multi-client avec tarif événement idTransaction

Outil de Génération HMAC V2

Utilisez notre outil Java pour générer facilement les signatures HMAC :

Télécharger HMAC Generator V2

Version 2.0 • Java 8+ requis • Taille: ~6 KB

Télécharger et exécuter l'outil
# 1. Télécharger l'outil (disponible après compilation)
wget http://localhost:8085/downloads/hmac-generator-v2.jar

# 2. Exécuter avec vos paramètres
java -jar hmac-generator-v2.jar \
  --method GET \
  --path /api/1200263/factures-non-soldees \
  --secret "VOTRE_SECRET_HMAC"

java -jar hmac-generator-v2.jar \
  --method POST \
  --path /api/webhook/orange/paiement \
  --fields "idTransaction=TXN1757494924191" \
  --secret "VOTRE_SECRET_HMAC"


# 3. Résultat généré (exemple) :
╔══════════════════════════════════════════════════════════╗
║                   HEADERS HMAC V2 GÉNÉRÉS                ║
╚══════════════════════════════════════════════════════════╝
Stratégie: FIELDS (Critical Fields)
─────────────────────────────────────────────────────────────
X-HMAC-Signature: /iQRSEtLBjaNWrpVJY+i1KYg5uAofWcGW0ppvswnFCI=
X-Timestamp: 1757580100
X-Client-Id: orange-money-client
X-Signature-Strategy: FIELDS

⚠️ Important - Sécurité

  • • Ne jamais exposer le secret HMAC dans le code client

Outil de Génération HMAC V2 (Code)

Exemple de code Java pour générer les signatures HMAC dans votre application :

HmacClientOrangeExample.java
import com.ebenyx.burida.util.HmacGeneratorV2.SignatureStrategy;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class HmacClientOrangeExample {

  private static final String HMAC_ALGORITHM = "HmacSHA256";
  private static final String DEFAULT_SECRET = "VOTRE_SECRET_HMAC";
  private static final String DEFAULT_CLIENT_ID = "orange-money-client";

  public static void main(String[] args) throws Exception {
    System.out.println("Hmac Generator v2");
    long timestamp = Instant.now().getEpochSecond();

    String method = "GET";
    String path = "/api/1200263/factures-non-soldees";
    String clientId = DEFAULT_CLIENT_ID;
    String body = null;

    String signature = generateSignature(method, "/api/1200263/factures-non-soldees", timestamp, null,
        "VOTRE_SECRET_HMAC");

    // Afficher les résultats
    printResults(signature, timestamp, clientId);

    // Afficher la commande curl
    printCurlCommand(method, path, signature, timestamp, clientId, body);
  }

  private static String generateSignature(String method, String path, long timestamp,
      Map<String, String> fields, String secret) throws Exception {
    String dataToSign = generateFieldsData(method, path, timestamp, fields);
    return calculateHmac(dataToSign, secret);
  }

  private static String generateFieldsData(String method, String path, long timestamp,
      Map<String, String> fields) {
    StringBuilder data = new StringBuilder();
    data.append(method).append("|");
    data.append(path).append("|");
    data.append(timestamp);

    if (fields != null && !fields.isEmpty()) {
      for (Map.Entry<String, String> entry : fields.entrySet()) {
        data.append("|").append(entry.getKey()).append("=").append(entry.getValue());
      }
    }

    return data.toString();
  }

  private static String calculateHmac(String data, String secret) throws Exception {
    Mac mac = Mac.getInstance(HMAC_ALGORITHM);
    SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8),
        HMAC_ALGORITHM);
    mac.init(secretKey);
    byte[] hmacBytes = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
    return Base64.getEncoder().encodeToString(hmacBytes);
  }

  private static void printResults(String signature, long timestamp, String clientId) {
    System.out.println();
    System.out.println("╔══════════════════════════════════════════════════════════╗");
    System.out.println("║                   HEADERS HMAC V2 GÉNÉRÉS                ║");
    System.out.println("╚══════════════════════════════════════════════════════════╝");
    System.out.println("─────────────────────────────────────────────────────────────");
    System.out.println("X-HMAC-Signature: " + signature);
    System.out.println("X-Timestamp: " + timestamp);
    System.out.println("X-Client-Id: " + clientId);
    System.out.println();
  }

  private static void printCurlCommand(String method, String path, String signature,
      long timestamp, String clientId, String body) {
    System.out.println("╔══════════════════════════════════════════════════════════╗");
    System.out.println("║                    COMMANDE CURL DE TEST                 ║");
    System.out.println("╚══════════════════════════════════════════════════════════╝");
    System.out.println();

    StringBuilder curl = new StringBuilder();
    curl.append("curl -X ").append(method);
    curl.append(" http://localhost:8085").append(path);
    curl.append(" \\\n");
    curl.append("  -H \"X-HMAC-Signature: ").append(signature).append("\" \\\n");
    curl.append("  -H \"X-Timestamp: ").append(timestamp).append("\" \\\n");
    curl.append("  -H \"X-Client-Id: ").append(clientId).append("\" \\\n");
    curl.append("  -H \"Content-Type: application/json\"");

    if (body != null && !body.isEmpty() && !method.equals("GET")) {
      curl.append(" \\\n  -d '").append(body).append("'");
    }

    System.out.println(curl.toString());
    System.out.println();
  }
}

Limites de Taux (Rate Limiting)

DEV

100-200

req/min

HOMO

500-1000

req/min

PROD (Partenaires)

50,000+

req/min

Exemple d'Utilisation

Exemple de requête avec authentification HMAC
# Récupération des factures d'un client
curl -X GET \
  https://api.burida.com/factures/client/2202139 \
  -H "Content-Type: application/json" \
  -H "X-Timestamp: 1704067200" \
  -H "X-Signature: YmFzZTY0X2VuY29kZWRfc2lnbmF0dXJl" \
  -H "X-Client-Id: your-client-id"

# Exemple de réponse
{
  "success": true,
  "data": {
    "factures": [...],
    "total": 25,
    "page": 1
  }
}