Documentation API Collecte CMM (Aggregate Payment)

Spécifications techniques, simulation, initiation et suivi RESTful des opérations de collecte agrégée BMO.

Présentation

L'API Collecte CMM (Aggregate Payment) permet aux partenaires tiers d'effectuer des encaissements et collectes de fonds agrégées vers les solutions BMO.

Le parcours d'intégration s'articule autour de 3 opérations fondamentales :

  1. Simuler une collecte (POST /external/aggregate-payment/simulate) : Permet de valider la structure de la requête et d'évaluer l'opération sans générer d'impact financier ni de référence de transaction.
  2. Initier une collecte (POST /external/aggregate-payment) : Lance l'opération de paiement agrégé, génère une référence unique système et retourne le statut initial (ex: ONGOING).
  3. Suivre le statut d'une collecte (GET /external/aggregate-payment/{reference}) : Endpoint RESTful permettant d'interroger l'état final ou en cours de la transaction en passant directement la référence dans le chemin URI.

Environnement de Test (Sandbox) & Authentification :

  • Base URL TEST (Sandbox - Recommandé) : https://svc.test.bestcash.me/external (Environnement pré-configuré et validé pour la collecte CMM)
  • Base URL PAP (Pré-production) : https://svc.pap.bestcash.me/external
  • En-têtes d'authentification obligatoires :
    • X-Auth-ApiKey : Votre clé API partenaire (ex: +2290160606790)
    • X-Auth-ApiSecret : Votre secret API partenaire (ex: l/LshBHhTvhWcA==)
    • Content-Type: application/json
    • Accept: application/json

Remarque importante sur l'environnement de test (Sandbox) : Les tests d'initiation et de simulation de la collecte CMM nécessitent un profil client et un wallet récepteur pré-configurés (BMOPAY, client +2290167895434). Pour éviter l'erreur 401 Invalid authentication token ou 403 CUSTOMER NOT FOUND, les consoles d'essai <ApiPlayground /> ci-dessous sont configurées par défaut sur l'environnement TEST (Sandbox) (https://svc.test.bestcash.me/external) avec les identifiants dédiés (+2290160606790 / l/LshBHhTvhWcA==).


1. Simuler une collecte (POST /external/aggregate-payment/simulate)

Permet de simuler une opération de collecte avant son exécution réelle. Cet appel valide la forme des données transmises (sourceOperationData et targetOperationData) sans débiter les comptes ni créer de transaction persistante (reference: null).

  • Méthode : POST
  • URL : /external/aggregate-payment/simulate
  • Headers requis :
    • Content-Type: application/json
    • Accept: application/json
    • X-Auth-ApiKey: +2290160606790
    • X-Auth-ApiSecret: l/LshBHhTvhWcA==

Structure du Body JSON

ChampTypeDescription
amountnumberMontant total de la collecte (ex: 1000)
sourcestringSource du paiement (ex: "WALLET")
targetstringDestination du paiement (ex: "BMOPAY")
sourceOperationDataobjectInformations relatives à la source de la collecte
sourceOperationData.amountnumberMontant prélevé à la source
sourceOperationData.targetFirstnamestringPrénom du bénéficiaire à la source
sourceOperationData.targetLastnamestringNom du bénéficiaire à la source
sourceOperationData.targetMsisdnstringTéléphone du bénéficiaire à la source (ex: "+2290196784521")
sourceOperationData.targetNationalitystringCode pays ISO à 2 lettres (ex: "BJ")
targetOperationDataobjectInformations relatives à la cible de la collecte
targetOperationData.amountnumberMontant crédité à la cible
targetOperationData.customerobjectObjet contenant les données du client (phone)
targetOperationData.reasonstringMotif de l'opération de collecte
targetOperationData.depositorstringNom complet du déposant / initiateur
targetOperationData.idTypestringType de pièce d'identité (ex: "CI", "PASSPORT")
targetOperationData.idNumberstringNuméro de la pièce d'identité

Tester la simulation de collecte (Environnement TEST)

Exécutez une simulation d'opération sans génération de référence ni débit.

Authentification (En-têtes B-MO)
Paramètres d'URL / Query Parameters (0)

Aucun paramètre d'URL configuré.

Corps de la Requête (JSON Body)

Exemple de réponse HTTP 200 (Simulation)

{
  "reference": null,
  "amount": 1000.0,
  "source": "WALLET",
  "target": "BMOPAY",
  "status": null
}

2. Initier une collecte (POST /external/aggregate-payment)

Initie le paiement agrégé effectif et enregistre l'opération dans le système BMO.

  • Méthode : POST
  • URL : /external/aggregate-payment
  • Headers requis :
    • Content-Type: application/json
    • Accept: application/json
    • X-Auth-ApiKey: +2290160606790
    • X-Auth-ApiSecret: l/LshBHhTvhWcA==

Structure du Body JSON

Le corps de la requête utilise la même structure que l'étape de simulation :

{
  "amount": 1000,
  "source": "WALLET",
  "target": "BMOPAY",
  "sourceOperationData": {
    "amount": 1000,
    "targetFirstname": "Jean",
    "targetLastname": "Dupont",
    "targetMsisdn": "+2290196784521",
    "targetNationality": "BJ"
  },
  "targetOperationData": {
    "amount": 1000,
    "customer": {
      "phone": "+2290167895434"
    },
    "reason": "Simulation de test via API",
    "depositor": "Koffi Test",
    "idType": "CI",
    "idNumber": "123456789"
  }
}

Tester l'initiation d'une collecte (Environnement TEST)

Soumettez une collecte de fonds agrégée et obtenez la référence unique.

Authentification (En-têtes B-MO)
Paramètres d'URL / Query Parameters (0)

Aucun paramètre d'URL configuré.

Corps de la Requête (JSON Body)

Exemple de réponse HTTP 200 (Initiation)

{
  "reference": "7487519710968287232",
  "amount": 1000.0,
  "source": "WALLET",
  "target": "BMOPAY",
  "status": "ONGOING"
}

Statuts possibles de la réponse d'initiation

  • INITIATED : Opération créée et en attente de traitement.
  • ONGOING : Traitement de la collecte en cours.
  • COMPLETED : Transaction finalisée et validée avec succès.
  • PARTIALLY_COMPLETE : Traitement partiel de l'opération.
  • INCOMPLETE : Données de traitement incomplètes.
  • FAILED : Échec lors du traitement de la collecte.

IMPORTANT : Conservez l'identifiant numérique retourné dans le champ reference (ex: "7487519710968287232"). Il est indispensable pour interroger l'état du paiement à l'étape suivante.


3. Suivi du statut de la collecte (GET /external/aggregate-payment/{reference})

Permet de consulter l'état actualisé d'une opération de collecte à l'aide de son identifiant unique.

  • Méthode : GET
  • URL : /external/aggregate-payment/{reference}
  • Format du chemin (URI Path) : Renseigner directement la référence dans l'URL (ex: /external/aggregate-payment/7487519710968287232).
  • Headers requis :
    • Accept: application/json
    • X-Auth-ApiKey: +2290160606790
    • X-Auth-ApiSecret: l/LshBHhTvhWcA==

REMARQUE RESTful — Passage de la référence en chemin d'URI : Conformément aux spécifications validées en environnement réel, le suivi de statut de la collecte CMM s'effectue en passant la référence de l'opération directement en variable de chemin (/aggregate-payment/{reference}) et non en paramètre de requête.

Tester le suivi de statut de collecte (Environnement TEST)

Vérifiez l'état d'une transaction de collecte via sa référence unique dans le chemin URI.

Authentification (En-têtes B-MO)
Paramètres d'URL / Query Parameters (0)

Aucun paramètre d'URL configuré.

Exemple de réponse HTTP 200 (Transaction finalisée)

{
  "reference": "7487519710968287232",
  "amount": 1000.0,
  "source": "WALLET",
  "target": "BMOPAY",
  "status": "COMPLETED"
}

4. Dépannage & Erreurs courantes (Troubleshooting)

Erreur 401 Unauthorized (Invalid authentication token)

  • Cause : Survient lorsque les en-têtes d'authentification X-Auth-ApiKey ou X-Auth-ApiSecret transmis ne correspondent pas aux identifiants valides de l'environnement sélectionné. Sur le serveur TEST (Sandbox) (https://svc.test.bestcash.me), l'API de collecte CMM exige spécifiquement la clé partenaire +2290160606790 et le secret l/LshBHhTvhWcA==. Si vous aviez conservé une autre clé globale (ex: +2290196666262) dans les champs de votre navigateur, le serveur rejettera la requête avec un code HTTP 401.
  • Correction : Dans la console d'essai <ApiPlayground />, veillez à renseigner la clé +2290160606790 et le secret l/LshBHhTvhWcA== lorsque vous ciblez l'environnement TEST (Sandbox).

Erreur 403 Forbidden (CUSTOMER NOT FOUND)

  • Cause : L'endpoint de simulation (/simulate) et d'initiation (/aggregate-payment) vérifie la présence du profil client en base de données pour l'environnement ciblé (notamment via targetOperationData.customer.phone et les données source). Si le numéro de téléphone transmis (ex: +2290167895434) n'est pas un compte client ou un wallet récepteur actif dans l'environnement sélectionné (PAP vs TEST), le serveur rejette la requête.
  • Correction : Transmettre un numéro de téléphone client actif et enregistré dans l'environnement de test BestCash (ex: +2290167895434 sur le serveur Sandbox TEST https://svc.test.bestcash.me/external avec les clés API +2290160606790).

Erreur 500 Internal Server Error (SERVER ERROR)

  • Cause : Survient généralement lorsqu'un champ obligatoire du corps JSON est absent, mal structuré ou typé incorrectement par rapport aux attentes du backend.
  • Correction :
    • S'assurer que les montants sont transmis sous forme numérique (ex: "amount": 1000 et non sous forme de chaîne de caractères "1000").
    • Vérifier la présence et le typage exact des sous-objets sourceOperationData et targetOperationData.
    • Veiller à utiliser les codes pays au format ISO à 2 lettres (ex: "BJ" pour le Bénin).

Exemple d'intégration complet en Node.js / Axios (Environnement TEST - Sandbox)

Le script suivant illustre le flux complet d'une opération de collecte CMM : simulation facultative, initiation effective avec récupération de la référence, et boucle de contrôle jusqu'à la confirmation du statut final (COMPLETED) via l'URI RESTful ${BASE_URL}/aggregate-payment/${reference} :

import axios from 'axios';

const BASE_URL = 'https://svc.test.bestcash.me/external';
const headers = {
  'X-Auth-ApiKey': '+2290160606790',
  'X-Auth-ApiSecret': 'l/LshBHhTvhWcA==',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
};

const payload = {
  amount: 1000,
  source: 'WALLET',
  target: 'BMOPAY',
  sourceOperationData: {
    amount: 1000,
    targetFirstname: 'Jean',
    targetLastname: 'Dupont',
    targetMsisdn: '+2290196784521',
    targetNationality: 'BJ'
  },
  targetOperationData: {
    amount: 1000,
    customer: {
      phone: '+2290167895434'
    },
    reason: 'Paiement commande via API',
    depositor: 'Koffi Test',
    idType: 'CI',
    idNumber: '123456789'
  }
};

async function executeCmmCollectionWorkflow() {
  try {
    // 1. Simulation préalable (Optionnel)
    console.log('--- 1. Simulation de la collecte CMM ---');
    const simRes = await axios.post(`${BASE_URL}/aggregate-payment/simulate`, payload, { headers });
    console.log('Résultat de la simulation :', simRes.data);

    // 2. Initiation de la collecte
    console.log('--- 2. Initiation de la collecte CMM ---');
    const initRes = await axios.post(`${BASE_URL}/aggregate-payment`, payload, { headers });
    const reference = initRes.data.reference;
    console.log(`Collecte initiée avec succès ! Référence : ${reference}, Statut initial : ${initRes.data.status}`);

    if (!reference) {
      throw new Error("Aucune référence retournée par l'initiation.");
    }

    // 3. Suivi du statut de la collecte via l'URI RESTful (/aggregate-payment/{reference})
    console.log('--- 3. Vérification du statut de l\'opération ---');
    
    // Attente recommandée de quelques secondes si le statut initial est ONGOING
    let status = initRes.data.status;
    let attempts = 0;

    while (status === 'ONGOING' && attempts < 5) {
      attempts++;
      console.log(`Tentative de vérification ${attempts}...`);
      await new Promise(resolve => setTimeout(resolve, 2000)); // Attente de 2s

      const statusRes = await axios.get(`${BASE_URL}/aggregate-payment/${reference}`, { headers });
      status = statusRes.data.status;
      console.log(`Statut de la transaction : ${status}`);
    }

    console.log(`Traitement terminé. Statut final : ${status}`);

  } catch (error) {
    if (error.response?.data?.code === 401) {
      console.error("Dépannage (401 Invalid authentication token) : Vérifiez que les en-têtes d'authentification contiennent bien X-Auth-ApiKey: +2290160606790 et X-Auth-ApiSecret: l/LshBHhTvhWcA== sur le serveur TEST.");
    } else if (error.response?.data?.code === 403) {
      console.error("Dépannage (403 CUSTOMER NOT FOUND) : Vérifiez que le numéro de téléphone du client est bien enregistré sur l'environnement ciblé.");
    } else if (error.response?.data?.code === 500) {
      console.error("Dépannage (500 SERVER ERROR) : Vérifiez que les montants sont de type numérique et que le JSON est correctement structuré.");
    } else {
      console.error('Erreur durant le workflow de collecte :', error.response?.data || error.message);
    }
  }
}

executeCmmCollectionWorkflow();