📋 Vue d'ensemble
L'API PayFisc permet aux banques et partenaires financiers d'integrer le systeme de paiement des taxes et impots. Construite avec Go (Fiber v3) pour des performances elevees et une securite maximale.
🔄 Flux de paiement
Le partenaire s'authentifie, initialise un paiement, puis confirme ou annule. Alternativement, le partenaire peut notifier lui-meme via le callback /api/paiement/callback pour declencher une confirmation automatique. Un webhook est envoye apres chaque confirmation ou annulation.
🔐 Authentification
Authentifie un partenaire bancaire et retourne un token JWT.
Corps de la requete
{
"bank_id": "BANK_001",
"api_key": "votre-cle-api-secrete"
}
Parametres
- bank_idstringrequis— Identifiant unique de la banque partenaire
- api_keystringrequis— Cle API secrete fournie lors de l'inscription
Verifications effectuees
| 1 | IP autorisee (whitelist) |
| 2 | User-Agent autorise |
| 3 | Identifiants valides (comparaison timing-safe) |
| 4 | Compte actif et non suspendu |
| 5 | Cle API non expiree |
| 6 | Permissions suffisantes |
| 7 | Limites de transactions respectees |
Reponse succes — 200
{
"status": "success",
"message": "Authentification reussie",
"data": {
"token": "eyJhbGciOi...",
"expires_at": "2026-04-18 22:30:00",
"bank_name": "Banque Partenaire",
"bank_id": "BANK_001",
"permissions": ["process_payments"],
"limits": {
"daily": 10000000,
"monthly": 100000000,
"min_amount": 100,
"max_amount": 5000000
}
}
}
Exemple cURL
curl -X POST https://dev-api-mpako.com/api/auth/login \
-H "Content-Type: application/json" \
-d '{
"bank_id": "BANK_001",
"api_key": "votre-cle-api-secrete"
}'
🚀 Initialiser un paiement
Cree un paiement en attente valide 1 heure. Le comportement varie selon la combinaison taxe_id + province_id.
Structure generale de la requete
- taxe_idintegerrequis— ID de la taxe
- province_idintegerrequis— ID de la province
- criteres.telephonestringrequis— Numero de telephone (10 chiffres max). Les 3 premiers chiffres doivent obligatoirement être l'un des prefixes : 080, 081, 082, 083, 084, 085, 089, 090, 097, 098, 099 — obligatoire pour toutes les taxes
- criteres.typestringoptionnel*— Categorie tarifaire (obligatoire pour le peage)
✂ Taxe d'assainissement — taxe_id: 23 & province_id: 31
Recherche le contribuable par numero de telephone, recupere ses factures impayees/en retard. Le champ type est ignore.
{
"taxe_id": 23,
"province_id": 31,
"criteres": {
"telephone": "0891234567"
}
}
Reponse — contribuable existant connu
{
"status": "success",
"message": "Paiement initialise avec succes",
"data": {
"reference_paiement": "PAY-20260514-ABC123",
"taxe": { "id": 23, "nom": "Taxe d'assainissement", "description": "..." },
"taux": { "id": 1, "nom": "Taux standard", "valeur": 5.00 },
"contribuable": {
"id": 42,
"reference": "CONTRIB-2026-001",
"nom": "KABONGO",
"prenom": "Jean",
"telephone": "0891234567"
},
"factures": [
{
"id": 101,
"reference": "FACT-2026-001",
"montant": 15000.00,
"periode_debut": "2026-01-01",
"periode_fin": "2026-03-31",
"date_echeance": "2026-03-31",
"statut": "impayee"
}
],
"montant_total": 15000.00,
"province_id": 31,
"date_expiration": "2026-05-14 23:30:00"
}
}
🛣 Taxe de Peage — taxe_id: 36 & province_id: 31
Paiement anonyme : aucun compte contribuable n'est requis. Le montant est determine automatiquement selon la categorie tarifaire fournie dans criteres.type (1 passage).
- criteres.typestringrequis— Categorie tarifaire du vehicule (ex: «Moto», «Voiture»)
- criteres.telephonestringrequis— Numero de telephone (10 chiffres max). Les 3 premiers chiffres doivent obligatoirement être l'un des prefixes : 080, 081, 082, 083, 084, 085, 089, 090, 097, 098, 099
{
"taxe_id": 36,
"province_id": 31,
"criteres": {
"type": "Moto",
"telephone": "0891234567"
}
}
Reponse — contribuable anonyme
Les champs id, nom et prenom du contribuable sont null (paiement anonyme). La facture est generee a la volee, son id est aussi null.
{
"status": "success",
"message": "Paiement initialise avec succes",
"data": {
"reference_paiement": "PAY-20260514-XYZ789",
"taxe": { "id": 36, "nom": "Taxe de peage", "description": "..." },
"taux": { "id": 3, "nom": "Taux peage standard", "valeur": 100.00, "description": "Tarif unitaire peage" },
"contribuable": {
"id": null,
"reference": "CONTRIB-20260514-R4T8",
"nom": null,
"prenom": null,
"telephone": "0891234567"
},
"factures": [
{
"id": null,
"reference": "FACT-20260514-K9P2",
"montant": 2500.00,
"periode_debut": "2026-05-14",
"periode_fin": "2026-05-14",
"date_echeance": "2026-05-14",
"statut": "impayee"
}
],
"montant_total": 2500.00,
"province_id": 31,
"date_expiration": "2026-05-14 15:00:00"
}
}
✅ Confirmer un paiement
Confirme un paiement initialise. Cree les enregistrements de paiement, la repartition beneficiaires, et met a jour les factures dans une transaction atomique.
Flux de traitement
Parametres
- reference_paiementstringrequis— Reference obtenue lors de l'initialisation
- methode_paiementstringrequis— mobile_money | banque | especes
Corps de la requete
{
"reference_paiement": "PAY-20260418-ABC123",
"methode_paiement": "mobile_money"
}
Reponse succes — 200
{
"status": "success",
"message": "Paiement confirme avec succes",
"data": {
"reference_paiement": "PAY-20260418-ABC123",
"paiement_id": 256,
"montant_total": 15000.00,
"methode_paiement": "mobile_money",
"nombre_factures": 1,
"taux": {
"id": 1,
"nom": "Taux standard",
"valeur": 5.00
},
"repartition": [
{
"beneficiaire_id": 1,
"nom": "Tresor Public",
"numero_compte": "CD001-00012345",
"type_part": "pourcentage",
"valeur_part": 60,
"montant": 9000.00
},
{
"beneficiaire_id": 2,
"nom": "Province",
"numero_compte": "CD002-00054321",
"type_part": "pourcentage",
"valeur_part": 40,
"montant": 6000.00
}
],
"date_paiement": "2026-04-18 14:35:22"
}
}
❌ Annuler un paiement
Annule un paiement (en attente ou confirme). Si confirme, supprime atomiquement les enregistrements, remet les factures en "impayee", et decremente les compteurs.
Corps de la requete
{
"reference_paiement": "PAY-20260418-ABC123"
}
Reponse succes — 200
{
"status": "success",
"message": "Paiement annule avec succes",
"data": {
"reference_paiement": "PAY-20260418-ABC123",
"status": "annule"
}
}
📞 Callback partenaire entrant
Endpoint public (pas de JWT requis) que le partenaire bancaire utilise pour notifier l'API d'un paiement effectue de son cote. Si le statut est succes et que le paiement est en attente, la confirmation est automatique.
Headers requis
Content-Type: application/json
X-Webhook-Signature: <hmac-sha256-hex(body, secret_webhook)>
# Optionnel si bank_id est dans le body :
X-Bank-ID: BANK_001
Format JSON — a respecter strictement
- reference_paiementstringrequis— Reference obtenue lors de l'initialisation (PAY-...)
- bank_idstringrequis— Identifiant du partenaire bancaire
- statutstringrequis— succes ou echec
- transaction_idstringrequis— Identifiant unique de la transaction cote partenaire
- montantnumberrequis— Montant effectivement debite (float, > 0)
- methode_paiementstringrequis— mobile_money | banque | especes
- metadataobjectoptionnel— Donnees libres (logs, transaction interne, etc.)
Corps de la requete
{
"reference_paiement": "PAY-20260514-XYZ789",
"bank_id": "BANK_001",
"statut": "succes",
"transaction_id": "TXN-2026-00987",
"montant": 2500.00,
"methode_paiement": "mobile_money",
"metadata": {
"operateur": "Airtel Money",
"numero_msisdn": "0891234567"
}
}
Reponse succes — 200
{
"status": "success",
"message": "Callback recu et paiement confirme automatiquement",
"data": {
"reference_paiement": "PAY-20260514-XYZ789",
"statut": "succes",
"message": "Callback recu et paiement confirme automatiquement"
}
}
Calcul de la signature HMAC-SHA256
# Exemple en bash :
BODY='{"reference_paiement":"PAY-...", ...}'
SECRET="votre-secret-webhook"
SIGNATURE=$(echo -n "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | awk '{print $2}')
curl -X POST https://dev-api-mpako.com/api/paiement/callback \
-H "Content-Type: application/json" \
-H "X-Webhook-Signature: $SIGNATURE" \
-H "X-Bank-ID: BANK_001" \
-d "$BODY"
Ce qui est enregistre apres reception du callback
| Champ | Description |
|---|---|
| reference_paiement | Reference du paiement partenaire |
| bank_id | Identifiant de la banque |
| statut | succes | echec | en_attente |
| transaction_id | ID cote partenaire |
| montant | Montant notifie |
| methode_paiement | Mode de paiement |
| metadata_json | Donnees libres JSON |
| signature_valide | 1 si HMAC verifie, 0 sinon |
| ip | IP source du callback |
| date_reception | Horodatage reception |
| date_traitement | Horodatage confirmation (si auto) |
💚 Health Check
Verifie l'etat de l'API et de la connexion a la base de donnees.
{
"status": "ok",
"service": "MPAKO API",
"version": "2.1.0",
"database": "ok",
"uptime": "2026-04-18T14:00:00Z"
}
🔔 Webhooks (Callbacks)
Apres chaque confirmation ou annulation, le systeme envoie automatiquement une notification HTTP POST vers l'URL webhook configuree pour le partenaire.
Configuration webhook
| Champ | Description |
|---|---|
| url_webhook_confirmation | URL appelee apres confirmation |
| url_webhook_annulation | URL appelee apres annulation |
| secret_webhook | Cle HMAC-SHA256 pour signer les payloads |
Headers envoyes
POST {url_webhook}
Content-Type: application/json
X-Webhook-Event: confirmation | annulation
X-Webhook-Timestamp: 2026-04-18T14:35:22Z
X-Webhook-Signature: hmac-sha256-hex-signature
Payload — Confirmation
{
"event": "confirmation",
"timestamp": "2026-04-18T14:35:22Z",
"data": {
"reference_paiement": "PAY20260418143500AB1CD",
"paiement_id": 256,
"montant_total": 15000.00,
"methode_paiement": "mobile_money",
"nombre_factures": 1,
"repartition": [...],
"date_paiement": "2026-04-18 14:35:22"
}
}
Payload — Annulation
{
"event": "annulation",
"timestamp": "2026-04-18T14:40:10Z",
"data": {
"reference_paiement": "PAY20260418143500AB1CD",
"status": "annule"
}
}
📊 Compteurs & Suspension
Compteurs automatiques
A chaque confirmation/annulation, les compteurs du partenaire sont mis a jour :
| Compteur | Confirmation | Annulation |
|---|---|---|
| total_transactions | +1 | -1 |
| total_montant | +montant | -montant |
Suspension de compte
Quand un partenaire est suspendu (suspendu = 1), l'authentification retourne :
{
"status": "error",
"code": "ACCOUNT_SUSPENDED",
"message": "Compte suspendu: Facture impayee depuis le 01/03/2026"
}
💰 Combinaisons taxe + province supportees
| taxe_id | province_id | Nom | criteres.type | Contribuable |
|---|---|---|---|---|
| 23 | 31 | Taxe d'assainissement | Ignore | Existant (par telephone) |
| 26 | 31 | Taxe de Peage | Requis — categorie tarifaire exacte (ex : Moto, Voiture) | Anonyme (id=null, nom=null) |
D'autres combinaisons seront ajoutees progressivement.
⚠️ Codes d'erreur
Toutes les erreurs suivent le format unifie :
{
"status": "error",
"code": "CODE_ERREUR",
"message": "Description lisible"
}
Authentification
| Code | HTTP | Description |
|---|---|---|
| AUTH_FAILED | 401 | Identifiants invalides ou compte inactif |
| ACCOUNT_SUSPENDED | 403 | Compte suspendu (raison indiquee) |
| INVALID_TOKEN | 401 | Token JWT invalide ou expire |
| INVALID_SESSION | 401 | Session invalide, reconnexion requise |
| INSUFFICIENT_PERMISSIONS | 403 | Permissions insuffisantes |
| IP_NOT_AUTHORIZED | 403 | Adresse IP non autorisee |
| USER_AGENT_NOT_AUTHORIZED | 403 | User-Agent non autorise |
Paiement
| Code | HTTP | Description |
|---|---|---|
| UNAUTHORIZED_PAYMENT | 403 | Paiement non associe a votre partenaire |
| INVALID_REQUEST | 400 | Corps de requete invalide (JSON malformate) |
| MISSING_PARAMETERS | 400 | Parametres requis manquants (taxe_id, province_id, etc.) |
| MISSING_TELEPHONE | 400 | Le champ criteres.telephone est obligatoire |
| INVALID_TELEPHONE | 400 | Telephone invalide : chiffres uniquement, 10 max, prefixe obligatoire parmi 080 081 082 083 084 085 089 090 097 098 099 |
| MISSING_TYPE | 400 | criteres.type obligatoire pour taxe_id:36 (peage) |
| TAXE_PROVINCE_NOT_SUPPORTED | 400 | Combinaison taxe_id + province_id non geree |
| INVALID_PAYMENT_STATUS | 400 | Statut incompatible avec l'action |
| INVALID_PAYMENT_DATA | 400 | Donnees du paiement incompletes |
| PAYMENT_EXPIRED | 400 | Paiement expire (+1 heure) |
| ALREADY_CANCELLED | 400 | Paiement deja annule |
| AMOUNT_TOO_LOW | 400 | Montant sous le minimum autorise |
| AMOUNT_TOO_HIGH | 400 | Montant au-dessus du maximum autorise |
| NO_BENEFICIARIES | 400 | Aucun beneficiaire configure pour cette taxe/province |
| TAXE_NOT_FOUND | 404 | Taxe non trouvee ou inactive |
| TARIFF_NOT_FOUND | 404 | Tarif peage non trouve (type ou province invalide) |
| CONTRIBUABLE_NOT_FOUND | 404 | Contribuable non trouve pour ce telephone |
| NO_UNPAID_INVOICES | 404 | Aucune facture impayee pour ce contribuable |
| PAYMENT_NOT_FOUND | 404 | Paiement non trouve avec cette reference |
Callback
| Code | HTTP | Description |
|---|---|---|
| INVALID_SIGNATURE | 401 | Signature X-Webhook-Signature HMAC invalide |
| CALLBACK_STORAGE_ERROR | 500 | Erreur stockage du callback en base |
| CALLBACK_ERROR | 500 | Erreur systeme traitement callback |
Limites & systeme
| Code | HTTP | Description |
|---|---|---|
| DAILY_LIMIT_EXCEEDED | 429 | Limite journaliere atteinte |
| MONTHLY_LIMIT_EXCEEDED | 429 | Limite mensuelle atteinte |
| PARTNER_MAINTENANCE | 503 | Partenaire en maintenance |
| SYSTEM_ERROR | 500 | Erreur systeme interne |