Aller au contenu
NEVORUS PaymentHub · Wiki Se connecter

Intégrer · Brancher une application sur la plateforme

Guide d'intégration

Dans cette page

Pour un partenaire ou un intégrateur qui doit brancher son application sur la plateforme. Rien ici ne suppose d'accès au dépôt ni à l'infrastructure.

Une seule porte

Tous les appels passent par la passerelle, sur un seul domaine. Les services eux-mêmes ne sont joignables ni depuis internet, ni depuis le réseau du client : il n'existe pas d'autre chemin, et il n'en sera pas ouvert.

https://<passerelle>/<api>/<version>/<ressource>

Chaque appel porte un jeton OAuth 2.0. Sans jeton, la passerelle répond 401 ; avec un jeton valable mais sans abonnement à l'API visée, 403.

Obtenir ses accès

Deux chemins, selon ce que le contrat prévoit :

Par l'exploitant — il crée votre application dans l'API Manager, l'abonne aux API de votre périmètre, et vous remet un identifiant et un secret client.

En libre-service, si le module d'abonnements est actif : le portail développeur (https://<api-manager>/devportal) permet de créer une application, de s'abonner et de générer ses clés. Les mêmes opérations existent en API (/subscription/v1/keys, /subscription/v1/catalog), ce qui permet de les automatiser.

Gardez le secret client comme un mot de passe : il ouvre tout votre périmètre. S'il fuit, demandez sa régénération — les clés se remplacent sans interrompre l'application, le temps de basculer.

Obtenir un jeton

curl -s -u "$CLIENT_ID:$CLIENT_SECRET" \
  -X POST https://<passerelle>/oauth2/token \
  -d grant_type=client_credentials
{ "access_token": "eyJ4NXQi…", "token_type": "Bearer", "expires_in": 3600 }

Le jeton vaut une heure. Le redemander à chaque appel fonctionne mais sature l'annuaire : gardez-le en mémoire et renouvelez-le à l'approche de son échéance, ou sur un 401. Ne le stockez pas dans un navigateur.

Appeler une API

curl -s -X POST https://<passerelle>/payment/v1/payment \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
        "accountNumber": "0000000001",
        "msisdn":        "770000000",
        "operator":      "orange",
        "service":       "MOMO",
        "operation":     "cashin",
        "amount":        5000,
        "currency":      "XOF",
        "country":       "SN",
        "orderId":       "CMD-2026-000123",
        "returnUrl":     "https://mon-site/paiement/retour",
        "cancelUrl":     "https://mon-site/paiement/annule"
      }'

partnerCode ne se déclare plus. La passerelle joint à votre requête une affirmation signée nommant votre application ; la plateforme y lit votre code partenaire. Omettez-le : c'est le seul usage qui vous garantisse qu'aucune erreur de recopie ne dirige un paiement ailleurs.

Vous pouvez encore l'envoyer — vos intégrations en place continuent de fonctionner — mais il est désormais vérifié : un code qui n'est pas celui de votre application vaut 403 A00001, sans que le paiement soit engagé. Si vous voyez ce refus, c'est que la valeur envoyée n'est pas la vôtre.

Le compte et le client sont deux acteurs. accountNumber est VOTRE compte sur la plateforme — celui qui est crédité en cashin, débité en cashout ; il vous est ouvert à la signature de votre contrat. msisdn est le numéro du client, à l'autre bout de l'opération. Les confondre produit une demande cohérente en apparence et fausse sur le fond.

Le numéro du client s'écrit sans indicatif, à la longueur que déclare son pays — neuf chiffres au Sénégal, soit 770000000. La plateforme ajoute l'indicatif elle-même et vous le renvoie (221770000000). Un numéro déjà préfixé dépasse la longueur attendue et se fait refuser en BR0001 — MSISDN length does not match.

service est le CODE du service tel que votre contrat l'emploie — MOMO, VMC, DCB — et non son libellé. operator est le nom de l'opérateur ; la casse est sans importance, la plateforme normalise.

orderId est votre référence, et la seule qui vous permettra de vous retrouver. C'est elle que la plateforme conserve et qui apparaît dans l'API des transactions. Fournissez-la toujours : sans elle, la demande est acceptée — 200, frais calculés — mais la transaction n'est jamais enregistrée, et le paiement devient introuvable. Rien ne vous le signale au moment de l'appel. Le schéma publié ne marque pourtant pas ce champ obligatoire : c'est un constat d'exploitation, pas une lecture du contrat.

partnerOrderId existe aussi, mais la plateforme la remplace par une référence à elle (OXCI…) : ne vous en servez pas pour vos rapprochements.

operation vaut cashin (encaissement) ou cashout (décaissement). Le schéma déclare obligatoires accountNumber, operator et service — auxquels s'ajoutent, en pratique, msisdn et orderId. partnerCode y figure encore comme obligatoire, mais ne l'est plus : la plateforme le déduit de votre jeton.

Un paiement n'est pas instantané : la réponse dit qu'il est accepté, pas qu'il est abouti. L'aboutissement vous parvient par rappel web, et se vérifie sur l'API des transactions.

Le catalogue

API Contexte Ce qu'elle fait
Paiement /payment/v1 Encaisser et décaisser.
Transactions /transaction/v1 Rechercher, suivre, rapprocher.
Partenaires /partner/v1 Le référentiel des marchands.
Référentiel /content/v1 Pays, devises, institutions, moyens de paiement.
Comptes /account/v1 · Soldes /balance/v1 Comptes, soldes, règlements, écritures.
Contrats et offres /offer-service/V1 Contrats commerciaux, commissions.
Abonnements API /subscription/v1 Applications, abonnements, clés.
Virements /transfer/v1 · masse /transfer/bulk/v1 Virements sortants.
Abonnement opérateur (DCB) /subscription-dcb/v1 · /rebill/v1 · /dcb-auth/v1 Abonnements sur facture, refacturation, OTP.
Notifications /notification/v1 · rappels /hook/v1 Courriels et rappels web.
Rapports /report/v1 Restitutions.

Toutes ne sont pas ouvertes à tous : votre périmètre dépend de votre contrat et des modules installés chez l'exploitant (voir MODULES.md).

La documentation détaillée

Chaque API publie ses chemins, ses paramètres, ses schémas de corps et de réponse dans le portail développeur : https://<api-manager>/devportal, onglet API Console. Ces définitions ne sont pas écrites à la main — elles sont importées depuis les services eux-mêmes à chaque déploiement, et suivent donc le code.

Une ressource générique /* figure en fin de liste sur chaque API : c'est un relais de compatibilité, pas une ressource à appeler.

Ce que répond la passerelle

Code Signification Ce qu'il faut faire
401 Jeton absent, expiré ou invalide. Redemander un jeton.
403 Jeton valable, mais l'application n'est pas abonnée à cette API. Demander l'abonnement ; ce n'est pas un problème de code.
403 A00001 Le partnerCode envoyé n'est pas celui de votre application. Omettez ce champ : la plateforme le déduit de votre jeton. Le paiement n'a pas été engagé.
404 Chemin inconnu, ou API non déployée chez cet exploitant. Vérifier le chemin dans le portail, puis le périmètre du contrat.
429 Palier de débit dépassé. Ralentir, réessayer avec un délai croissant.
500 / 503 Le service derrière la passerelle est indisponible ou en quarantaine après des échecs répétés. Réessayer ; si cela dure, prévenir l'exploitant — ce n'est pas votre appel qui est en cause.

Les rappels web

Quand un paiement aboutit ou échoue, la plateforme appelle votre URL. C'est le seul moyen d'être averti sans interroger l'API en boucle.

Trois règles, quel que soit le détail du contrat :

  • Répondez vite, en 2xx, et traitez ensuite. Un rappel qui attend votre traitement métier finit en délai dépassé, donc en rejeu.
  • Soyez idempotent : un même paiement peut vous être notifié plusieurs fois. Rapprochez sur votre orderId, pas sur l'ordre d'arrivée — et pas sur partnerOrderId, que la plateforme a remplacé par sa propre référence.
  • Ne faites pas confiance au seul rappel. Il peut se perdre. Confirmez sur l'API des transactions avant de livrer un bien ou un service.

Le format exact du rappel, sa signature et la politique de rejeu sont à confirmer avec l'équipe d'intégration : ils dépendent de la version du module de rappels installée, et ne sont pas fixés dans ce document.

Avant la mise en production

  • Essayez d'abord sur l'installation de démonstration, avec de petits montants.
  • Après votre premier paiement accepté, allez le retrouver dans l'API des transactions. Un 200 dit que la demande est partie, pas qu'elle a laissé une trace : c'est le seul contrôle qui distingue une intégration qui marche d'une intégration qui semble marcher.
  • Vérifiez votre comportement quand un paiement reste en cours plus de quinze minutes : c'est le cas le plus fréquent en conditions réelles, et le plus mal traité.
  • Vérifiez votre comportement sur un 429 et sur un 503.
  • Convenez avec l'exploitant du volume attendu : les paliers de débit se règlent par API et par application.