Skip to content

Service Configuration - Documentation Produit

Le service Configuration est le referentiel central de la plateforme NXPay. Il stocke et expose toutes les donnees de reference et regles metier qui parametrent le comportement de l'ensemble des microservices : pays, devises, frais, limites, commissions, moyens de paiement, conformite KYC, agents, zones geographiques.

Base URL : http://configuration:3000/v1 (interne) | http://localhost:8080/api/config (via Nginx)


Vue d'ensemble simplifiee

Pourquoi ce service existe ?

  • Centraliser toutes les regles metier en un seul endroit
  • Modifier les parametres sans toucher au code
  • Garantir la coherence entre tous les services
  • Faciliter l'ajout de nouveaux pays, devises ou types de transactions

Clarification des concepts cles

🔄 TransactionType vs TransactionLimit (Limites)

Confusion frequente : Il y a DEUX niveaux de limites differents dans le systeme.

ConceptOu ?RoleExemple
TransactionType.min_amount / max_amountDans la definition du typeLimites globales techniques du type de transactionTRANSFER : min=100, max=5000000 (personne ne peut transferer moins de 100 ni plus de 5M)
TransactionLimitEntite separeeLimites par entite (user, merchant, role, global) et par periode (per_transaction, daily, monthly)User123 : 500k par transaction, 2M par jour, 10M par mois

Exemple concret :

text
TransactionType "TRANSFER" dit : "minimum 100 FCFA, maximum 5 000 000 FCFA" (technique)

TransactionLimit pour "utilisateur non verifie" dit : "maximum 50 000 FCFA par transaction" (metier)

TransactionLimit pour "Jean (user123)" dit : "maximum 500 000 FCFA par jour" (personnalise)

→ Jean peut faire un TRANSFER entre 100 FCFA (min du type) et 50 000 FCFA (limite la plus restrictive)
→ Jean peut faire maximum 500 000 FCFA par jour (sa limite personnalisee)

🔀 TransactionChannel vs AuthorizedChannel

Confusion frequente : Quelle est la difference entre un "canal" et un "canal autorise" ?

ConceptRoleExemple
TransactionChannelReferentiel de tous les canaux existantsMOBILE_MONEY, CARD, BANK_TRANSFER, CASH, NXPAY_WALLET
AuthorizedChannelMatrice d'autorisation : quel canal peut etre utilise pour quel type de transactionTRANSFER autorise sur MOBILE_MONEY et NXPAY_WALLET, mais PAS sur CASH

Exemple concret :

text
TransactionChannel (referentiel)
├── MOBILE_MONEY        (existe comme canal)
├── CARD                (existe comme canal)
├── BANK_TRANSFER       (existe comme canal)
├── CASH                (existe comme canal)
└── NXPAY_WALLET        (existe comme canal)

AuthorizedChannel pour "TRANSFER"
├── ✓ MOBILE_MONEY      (is_active = true)
├── ✓ NXPAY_WALLET      (is_active = true)
├── ✗ CASH              (is_active = false - on ne peut pas transferer via cash)
└── ✗ CARD              (is_active = false)

AuthorizedChannel pour "CASH_IN"
├── ✓ CASH              (is_active = true - on peut deposer du cash)
├── ✓ MOBILE_MONEY      (is_active = true)
└── ✗ NXPAY_WALLET      (is_active = false - on ne peut pas deposer via le wallet interne)

👥 TransactionBetween (Autorisations entre roles)

Definit qui peut envoyer de l'argent a qui.

Exemple :

text
TransactionType: TRANSFER
├── user → user          ✓ autorise (P2P classique)
├── user → merchant      ✓ autorise (paiement)
├── merchant → user      ✓ autorise (remboursement)
├── user → agent         ✗ interdit (un client ne peut pas "transferer" a un agent, il doit utiliser CASH_OUT)
└── agent → agent        ✗ interdit

💳 PaymentMethodType vs PaymentMethod

ConceptOu ?RoleExemple
PaymentMethodTypeConfiguration serviceTemplate des moyens de paiement disponiblesMTN_CG, VODAFONE_CG, VISA, MASTERCARD
CountryPaymentMethodTypeConfiguration serviceDisponibilite par pays avec capacitesMTN_CG au Congo : peut payer, peut recharger, peut retirer
PaymentMethodLedger-Wallets serviceInstance d'un moyen de paiement pour un utilisateurLe compte MTN de Jean (+242 06 123 4567)

Flow :

text
1. Configuration definit : "MTN_CG existe, c'est du MOBILE_MONEY externe"
2. Configuration dit : "Au Congo, MTN_CG peut payer, recharger et retirer"
3. Jean cree son wallet et ajoute son compte MTN
4. Ledger-Wallets cree un PaymentMethod pour Jean qui reference le PaymentMethodType MTN_CG

🎯 AgentType (Types d'agents)

Entite manquante dans la vue d'ensemble ! Les types d'agents definissent les capacites et roles des agents.

Types d'agents disponibles :

CodeDescriptionhas_commissionis_field_agentcan_be_zonedrequires_merchant
distributionAgent de distribution (cash in/out)
complianceAgent de verification KYC
internalAgent interne NXPay
fieldAgent terrain generique
masterAgent maitre (gere d'autres agents)

Utilisation :

  • Les CommissionRule peuvent etre specifiques a un agent_type_id
  • Les agents distribution doivent etre rattaches a un marchand (requires_merchant=true)
  • Les agents field_agent peuvent etre affectes a des zones geographiques (can_be_zoned=true)

Exemple :

text
CommissionRule pour CASH_IN
├── beneficiary_type: PLATFORM    40%
├── beneficiary_type: MERCHANT    35%
└── beneficiary_type: AGENT       25% (agent_type_id = "distribution")

⚙️ Setting vs ServiceConfig

Confusion frequente : Quelle est la difference ?

ConceptPorteeExempleUsage
SettingGlobal pour toute la plateformemaintenance_mode=false, max_daily_transactions=10000Parametres globaux partages par tous les services
ServiceConfigSpecifique a un service et un environnementorchestrator.timeout=30000 (production), auth.jwt_expiry=3600 (development)Configuration par service et environnement

Exemple :

text
Setting (global)
├── maintenance_mode: false
├── platform_name: "NXPay"
└── support_email: "support@nxpay.com"

ServiceConfig (par service)
├── Service: orchestrator | Environment: production
│   ├── timeout: 30000
│   ├── max_retries: 3
│   └── cache_ttl: 300
└── Service: auth | Environment: production
    ├── jwt_expiry: 3600
    └── refresh_token_expiry: 604800

Les 26 entites du service (liste complete)

🌍 Geographie et devises (5)

  1. Country - Pays (Congo, Cameroun, RDC...)
  2. Currency - Devises (XAF, USD, EUR...)
  3. CountryCurrency - Association pays-devises
  4. City - Villes avec coordonnees GPS
  5. CountryPaymentMethodType - Disponibilite des moyens de paiement par pays

💳 Transactions (4)

  1. TransactionType - Types de transactions (TRANSFER, CASH_IN, PAYMENT...)
  2. TransactionChannel - Canaux disponibles (MOBILE_MONEY, CARD, CASH...)
  3. AuthorizedChannel - Matrice type/canal autorise
  4. TransactionBetween - Matrice role source/role destination

💰 Frais (3)

  1. FeeType - Types de frais (COMMISSION, TAX, SERVICE_FEE...)
  2. TransactionTypeFee - Configuration de calcul par type de transaction
  3. FeeTier - Paliers pour les frais degressifs/progressifs

🚦 Limites (1)

  1. TransactionLimit - Limites par entite/periode

🎯 Commissions (2)

  1. CommissionRule - Regles de redistribution des frais
  2. AgentType - Types d'agents avec capacites

💳 Moyens de paiement (1)

  1. PaymentMethodType - Types de moyens de paiement (MTN, Airtel, VISA...)

🌐 Regles inter-pays (2)

  1. CountryTransactionRule - Regles entre paires de pays
  2. CountryTransactionThreshold - Seuils KYC par pays

✅ Conformite et KYC (2)

  1. IdentityDocumentType - Types de documents acceptes
  2. Profession - Professions avec evaluation de risque

📍 Agents et zones (2)

  1. Zone - Decoupage geographique des villes
  2. ActivitySector - Profils economiques des zones

⚙️ Parametres systeme (2)

  1. Setting - Parametres globaux cle-valeur
  2. ServiceConfig - Configuration par service/environnement

📢 Notifications et services (2)

  1. NotificationChannel - Canaux de notification (SMS, EMAIL, PUSH...)
  2. SystemServiceType - Types de services exposes (PAYMENT, TRANSFER...)

Table des matieres

  1. Modele de donnees
  2. Geographie et devises
  3. Types de transactions et canaux
  4. Systeme de frais
  5. Limites de transactions
  6. Commissions
  7. Moyens de paiement par pays
  8. Regles entre pays
  9. Conformite et KYC
  10. Agents et zones
  11. Parametres systeme
  12. Canaux de notification et types de service
  13. Patterns API communs
  14. Exemples d'integration

1. Modele de donnees

Vue d'ensemble des relations

mermaid
erDiagram
    %% ── GEOGRAPHIE & DEVISES (schema: shared) ──
    Country ||--o{ CountryCurrency : "devises"
    Country ||--o{ City : "villes"
    Country ||--o{ CountryPaymentMethodType : "moyens de paiement"
    Country ||--o{ CountryTransactionRule : "regles (source)"
    Country ||--o{ CountryTransactionThreshold : "seuils KYC"
    Currency ||--o{ CountryCurrency : "pays"
    Currency ||--o{ TransactionType : "devise par defaut"
    Currency ||--o{ TransactionLimit : "devise"
    Currency ||--o{ CountryTransactionRule : "devise"
    Currency ||--o{ CountryTransactionThreshold : "devise"
    PaymentMethodType ||--o{ CountryPaymentMethodType : "disponibilite"

    %% ── TRANSACTIONS ──
    TransactionType ||--o{ AuthorizedChannel : "canaux autorises"
    TransactionType ||--o{ TransactionBetween : "autorisations roles"
    TransactionType ||--o{ TransactionTypeFee : "frais"
    TransactionType ||--o{ TransactionLimit : "limites"
    TransactionType ||--o{ CommissionRule : "commissions"
    TransactionType ||--o{ CountryTransactionRule : "regles inter-pays"
    TransactionType ||--o{ CountryTransactionThreshold : "seuils"
    TransactionChannel ||--o{ AuthorizedChannel : "types autorises"

    %% ── FRAIS ──
    FeeType ||--o{ TransactionTypeFee : "configurations"
    TransactionTypeFee ||--o{ FeeTier : "paliers"

    %% ── COMMISSIONS ──
    AgentType ||--o{ CommissionRule : "agent_type"

    %% ── ZONES ──
    City ||--o{ Zone : "zones"
    ActivitySector ||--o{ Zone : "secteur"

Diagramme detaille - Geographie et devises

mermaid
erDiagram
    Country {
        uuid id PK
        varchar(2) code UK "ISO 3166-1 alpha-2"
        varchar(3) code3 UK "ISO 3166-1 alpha-3"
        varchar(100) name
        varchar(100) name_en
        varchar(50) region
        varchar(10) phone_code
        varchar(3) numeric_code
        varchar(50) time_zone
        enum risk_level "low | medium | high | blocked"
        enum sanction_status "none | partial | full"
        boolean is_active
    }

    Currency {
        uuid id PK
        varchar(3) code UK "ISO 4217"
        varchar(3) numeric_code
        varchar(10) symbol
        integer minor_unit "decimales (0-4)"
        decimal reporting_threshold
    }

    CountryCurrency {
        uuid id PK
        uuid country_id FK
        uuid currency_id FK
        boolean is_primary "une seule par pays"
        date effective_from
    }

    City {
        uuid id PK
        uuid country_id "ref Country (cross-schema)"
        varchar(100) name
        varchar(20) code
        decimal latitude
        decimal longitude
    }

    Country ||--o{ CountryCurrency : "devises"
    Currency ||--o{ CountryCurrency : "pays"
    Country ||--o{ City : "villes"

Diagramme detaille - Transactions et canaux

mermaid
erDiagram
    TransactionType {
        uuid id PK
        varchar(20) code UK "TRANSFER, CASH_IN..."
        varchar(100) name
        varchar(50) category
        boolean requires_kyc
        decimal min_amount
        decimal max_amount
        uuid default_currency_id FK
    }

    TransactionChannel {
        uuid id PK
        varchar(20) code UK "MOBILE_MONEY, CARD..."
        varchar(100) name
    }

    AuthorizedChannel {
        uuid id PK
        uuid transaction_type_id FK
        uuid transaction_channel_id FK
        boolean is_active
    }

    TransactionBetween {
        uuid id PK
        uuid transaction_type_id FK
        varchar(50) from_role "user, merchant, agent"
        varchar(50) to_role
        boolean is_authorized
    }

    TransactionType ||--o{ AuthorizedChannel : "canaux"
    TransactionChannel ||--o{ AuthorizedChannel : "types"
    TransactionType ||--o{ TransactionBetween : "autorisations"

Diagramme detaille - Systeme de frais

mermaid
erDiagram
    FeeType {
        uuid id PK
        varchar(20) code UK "COMMISSION, TAX..."
        varchar(100) name
        boolean is_mandatory
        integer calculation_order "ordre de calcul"
    }

    TransactionTypeFee {
        uuid id PK
        uuid transaction_type_id FK
        uuid fee_type_id FK
        enum calculation_method "fixed | percentage | tiered"
        decimal amount "si fixed"
        decimal percentage "si percentage"
        decimal min_amount "plafond min"
        decimal max_amount "plafond max"
        enum paid_by "sender | recipient | platform | merchant"
        date effective_from
        date effective_to
        enum scheduled_status "active | scheduled | cancelled"
    }

    FeeTier {
        uuid id PK
        uuid transaction_type_fee_id FK
        integer tier_order "1, 2, 3..."
        decimal min_amount "debut tranche"
        decimal max_amount "fin tranche (null = ouvert)"
        decimal fixed_amount
        decimal percentage
    }

    TransactionType ||--o{ TransactionTypeFee : "frais"
    FeeType ||--o{ TransactionTypeFee : "configurations"
    TransactionTypeFee ||--o{ FeeTier : "paliers (si tiered)"

Diagramme detaille - Limites et commissions

mermaid
erDiagram
    TransactionLimit {
        uuid id PK
        uuid transaction_type_id FK
        enum limit_type "per_transaction | daily | monthly"
        enum entity_type "user | merchant | agent | organization | role | global"
        uuid entity_id "null pour global/role"
        decimal amount
        uuid currency_id FK
        date effective_from
        date effective_to
        enum scheduled_status "active | scheduled | cancelled"
    }

    CommissionRule {
        uuid id PK
        varchar(50) rule_type "FEE_SPLIT, AGENT_COMMISSION..."
        uuid transaction_type_id FK
        varchar(50) beneficiary_type "PLATFORM, MERCHANT, AGENT..."
        uuid agent_type_id FK "optionnel"
        uuid provider_id "optionnel"
        varchar(20) calculation_type
        decimal percentage
        decimal fixed_amount
        boolean is_split
        uuid split_group_id "groupe de partage"
        varchar(50) fallback_beneficiary_type
        integer priority_order
        decimal min_amount
        decimal max_amount
        varchar(3) country_code "null = global"
        date effective_from
        date effective_to
    }

    AgentType {
        uuid id PK
        varchar(50) code UK
        boolean has_commission
        boolean requires_merchant
        boolean requires_pdv
        boolean is_internal
        boolean is_field_agent
        boolean can_be_zoned
        decimal default_commission_rate
        integer display_order
    }

    TransactionType ||--o{ TransactionLimit : "limites"
    TransactionType ||--o{ CommissionRule : "commissions"
    AgentType ||--o{ CommissionRule : "agent_type"

Diagramme detaille - Regles inter-pays et KYC

mermaid
erDiagram
    CountryTransactionRule {
        uuid id PK
        uuid from_country_id FK
        uuid to_country_id FK
        uuid transaction_type_id FK
        boolean is_allowed
        decimal min_amount
        decimal max_amount
        uuid currency_id FK
        varchar(20) requires_kyc_level
        date effective_from
        date effective_to
    }

    CountryTransactionThreshold {
        uuid id PK
        uuid country_id FK
        uuid transaction_type_id FK "null = tous"
        enum threshold_type "unverified_user | incomplete_profile | daily | single"
        decimal amount
        uuid currency_id FK
        enum scheduled_status "active | scheduled | cancelled"
    }

    IdentityDocumentType {
        uuid id PK
        varchar(50) code UK "PASSPORT, NATIONAL_ID..."
        varchar(100) name
        varchar(100) name_fr
        varchar(100) name_en
        boolean requires_expiry_date
        boolean requires_issue_date
        boolean requires_document_number
        boolean requires_country
        boolean has_front_side
        boolean has_back_side
        integer display_order
    }

    Profession {
        uuid id PK
        varchar(200) profession
        varchar(20) risk_level "low | medium | high"
        text reason
        varchar(50) category
    }

    Country ||--o{ CountryTransactionRule : "source"
    Country ||--o{ CountryTransactionRule : "destination"
    Country ||--o{ CountryTransactionThreshold : "seuils"
    TransactionType ||--o{ CountryTransactionRule : "type"
    TransactionType ||--o{ CountryTransactionThreshold : "type"

Diagramme detaille - Moyens de paiement, zones et systeme

mermaid
erDiagram
    PaymentMethodType {
        uuid id PK
        varchar(20) code UK "MOBILE_MONEY, NXPAY_CARD..."
        varchar(100) name
        enum category "internal | external"
        enum form_type "INTERNAL_CARD | EXTERNAL_CARD | MOBILE_MONEY | BANK | CRYPTO | OTHER"
        varchar(255) logo
        varchar(20) color
    }

    CountryPaymentMethodType {
        uuid id PK
        uuid country_id FK
        uuid payment_method_type_id FK
        boolean is_available
        boolean can_pay "null = herite du type"
        boolean can_fund
        boolean can_receive
        boolean can_withdraw
        date effective_from
        date effective_to
    }

    Zone {
        uuid id PK
        uuid city_id "ref City"
        uuid activity_sector_id FK
        uuid supervisor_id "ref agent"
        varchar(20) code UK "BZV-CENTRE..."
        jsonb boundary_geojson
        integer max_agents
    }

    ActivitySector {
        uuid id PK
        varchar(50) code UK "PORT, MARKET, RURAL..."
        enum economic_level "high | medium | low"
        enum transaction_volume_estimate "very_high | high | medium | low"
        enum risk_level "high | medium | low"
    }

    Setting {
        uuid id PK
        varchar(100) key UK
        text value
        enum type "string | number | boolean | json"
        boolean is_encrypted
    }

    ServiceConfig {
        uuid id PK
        varchar(50) service_name
        varchar(100) config_key
        text config_value
        varchar(20) value_type
        varchar(20) environment "development | test | production"
        boolean is_encrypted
    }

    NotificationChannel {
        uuid id PK
        varchar(50) code UK "SMS, EMAIL, PUSH..."
        varchar(50) channel_type "OTP | MARKETING | TRANSACTIONAL | ALERT"
        varchar(100) provider "WIREPICK, MAILGUN, FIREBASE..."
        boolean is_default_for_otp
        boolean supports_attachments
        jsonb config
    }

    SystemServiceType {
        uuid id PK
        varchar(50) code UK "PAYMENT, TRANSFER..."
        varchar(50) category "PAYMENT | TRANSFER | CASH | BILL | AIRTIME"
        varchar(255) icon
        integer display_order
    }

    Country ||--o{ CountryPaymentMethodType : "disponibilite"
    PaymentMethodType ||--o{ CountryPaymentMethodType : "par pays"
    City ||--o{ Zone : "zones"
    ActivitySector ||--o{ Zone : "secteur"

Schemas de base de donnees

Le service utilise deux schemas PostgreSQL :

SchemaContenuRaison
sharedCountry, Currency, CountryCurrency, CityDonnees partagees, referencees par d'autres services
configurationTout le reste (22 entites)Donnees propres au service

Tous les ID sont des UUID v4 auto-generes. Toutes les entites ont created_at et updated_at.


2. Geographie et devises

Country

Referentiel des pays avec evaluation de risque pour la conformite.

ChampTypeDescription
codevarchar(2)Code ISO 3166-1 alpha-2, unique (ex: CG, CM, FR)
code3varchar(3)Code ISO 3166-1 alpha-3, unique (ex: COG, CMR, FRA)
name / name_envarchar(100)Nom en francais / anglais
regionvarchar(50)Region geographique
phone_codevarchar(10)Indicatif telephonique (+242, +237)
numeric_codevarchar(3)Code ISO numerique
time_zonevarchar(50)Fuseau horaire
risk_levelenumlow, medium, high, blocked
sanction_statusenumnone, partial, full
is_activebooleanPays actif/inactif

Endpoint cle : GET /countries/:id/configuration retourne la configuration complete d'un pays en une seule requete : devises, moyens de paiement, types de transactions, limites, regles, seuils, frais.

Routes specifiques :

GET  /countries/:id/active-payment-methods   Moyens de paiement actifs
GET  /countries/:id/transaction-types        Types de transactions disponibles
GET  /countries/:id/limits                   Limites de transactions
GET  /countries/:id/rules                    Regles inter-pays
GET  /countries/:id/thresholds               Seuils KYC
GET  /countries/:id/fees                     Structure des frais (avec paliers)
GET  /countries/:id/cities                   Villes du pays
GET  /countries/:id/zones                    Zones geographiques
PATCH /countries/:id/risk-level              Modifier le niveau de risque

Currency

Referentiel des devises ISO 4217.

ChampTypeDescription
codevarchar(3)Code ISO (EUR, USD, XAF), normalise en majuscules
numeric_codevarchar(3)Code numerique ISO (978, 840, 950), padde a 3 chiffres
symbolvarchar(10)Symbole (FCFA, $, EUR)
minor_unitintegerNombre de decimales (2 pour EUR, 0 pour JPY)
reporting_thresholddecimal(15,2)Seuil de reporting reglementaire

CountryCurrency

Association N-N entre pays et devises.

ChampTypeDescription
country_iduuidFK → Country
currency_iduuidFK → Currency
is_primarybooleanDevise principale du pays
effective_fromdateDate d'effet

Un pays peut avoir plusieurs devises. Une seule est marquee is_primary.

City

Villes rattachees a un pays.

ChampTypeDescription
country_iduuidReference vers Country (indexe, sans FK cross-schema)
namevarchar(100)Nom de la ville
codevarchar(20)Code ville
latitude / longitudedecimalCoordonnees GPS

3. Types de transactions et canaux

TransactionType

Definit les types de transactions disponibles sur la plateforme.

ChampTypeDescription
codevarchar(20)Identifiant unique (TRANSFER, PAYMENT, CASH_IN, CASH_OUT, BILL_PAYMENT...)
namevarchar(100)Libelle
categoryvarchar(50)Categorie metier
requires_kycbooleanNecessite une verification KYC
min_amount / max_amountdecimal(15,4)Montants limites globaux
default_currency_iduuidDevise par defaut (FK → Currency)

C'est l'entite pivot du service : les frais, limites, commissions, regles et autorisations y sont rattaches.

TransactionChannel

Canaux de paiement disponibles (MOBILE_MONEY, CARD, BANK_TRANSFER, CASH, NXPAY_WALLET...).

ChampTypeDescription
codevarchar(20)Identifiant unique
namevarchar(100)Libelle

AuthorizedChannel

Definit quels canaux sont autorises pour chaque type de transaction.

ChampTypeDescription
transaction_type_iduuidFK → TransactionType
transaction_channel_iduuidFK → TransactionChannel
is_activebooleanAutorisation active

Exemple : le type CASH_IN peut etre autorise sur MOBILE_MONEY et CASH, mais pas sur CARD.

TransactionBetween

Regles d'autorisation entre roles utilisateur.

ChampTypeDescription
transaction_type_iduuidFK → TransactionType
from_rolevarchar(50)Role source (user, merchant, agent...)
to_rolevarchar(50)Role destination
is_authorizedbooleanTransaction autorisee entre ces roles

Exemple : TRANSFER est autorise de user vers user, mais pas de user vers agent.


4. Systeme de frais

Le systeme de frais est hierarchique a 3 niveaux :

FeeType                 Quel type de frais ? (COMMISSION, TAX, PLATFORM_FEE, PROCESSING_FEE...)
  └── TransactionTypeFee    Comment le calculer pour ce type de transaction ?
        └── FeeTier              Quels paliers pour le mode "tiered" ?

FeeType

Types de frais globaux de la plateforme.

ChampTypeDescription
codevarchar(20)Identifiant unique (COMMISSION, TAX, SERVICE_FEE...)
namevarchar(100)Libelle
is_mandatorybooleanFrais obligatoire
calculation_orderintegerOrdre de calcul (les frais sont calcules sequentiellement)

TransactionTypeFee

Configuration de calcul d'un frais pour un type de transaction donne.

ChampTypeDescription
transaction_type_iduuidFK → TransactionType
fee_type_iduuidFK → FeeType
calculation_methodenumfixed, percentage, ou tiered
amountdecimal(15,4)Montant fixe (si fixed)
percentagedecimal(5,4)Pourcentage (si percentage)
min_amount / max_amountdecimal(15,4)Plafonnement min/max du frais calcule
paid_byenumsender, recipient, platform, merchant
effective_from / effective_todatePeriode de validite
scheduled_statusenumactive, scheduled, cancelled

Regle metier : il ne peut y avoir qu'une seule configuration active par couple (transaction_type, fee_type) a une date donnee. A la creation d'une nouvelle configuration, les precedentes sont automatiquement desactivees.

Versioning : chaque modification cree une nouvelle version. L'historique est consultable via GET /transaction-type-fees/:id/versions.

Planification : on peut creer une configuration avec effective_from dans le futur et scheduled_status=scheduled. Elle deviendra active a la date prevue.

FeeTier

Paliers de frais pour le mode tiered. Permet de definir des frais degressifs ou progressifs selon le montant.

ChampTypeDescription
transaction_type_fee_iduuidFK → TransactionTypeFee
tier_orderintegerOrdre du palier (1, 2, 3...)
min_amount / max_amountdecimal(15,4)Tranche de montant
fixed_amountdecimal(15,4)Frais fixe pour cette tranche
percentagedecimal(5,4)Pourcentage pour cette tranche

Regles de validation :

  • Les paliers doivent etre contigus (pas de trous)
  • Le premier palier doit commencer a min_amount=0
  • Le dernier palier peut avoir max_amount=null (ouvert)
  • Pas de chevauchement entre tranches
  • tier_order unique et sequentiel

Exemple (frais degressifs sur un TRANSFER) :

PalierTrancheFrais
10 - 10 000 FCFA200 FCFA fixe
210 000 - 100 000 FCFA1.5%
3100 000+ FCFA1% (plafonne a 5 000 FCFA)

Simulation de frais

POST /transaction-type-fees/simulate

Calcule le montant exact des frais pour un montant donne, quel que soit le mode de calcul.

json
// Requete
{
  "transaction_type_fee_id": "uuid",
  "amount": 50000
}

// Reponse
{
  "amount": 50000,
  "calculation_method": "tiered",
  "applicable_tier": { "tier_order": 2, "min_amount": 10000, "max_amount": 100000 },
  "calculated_fee": 750,
  "capped_fee": 750,
  "breakdown": {
    "percentage": 1.5,
    "min_cap": null,
    "max_cap": 5000,
    "was_capped": false
  }
}

Le simulateur :

  1. Identifie la methode de calcul (fixed, percentage, tiered)
  2. Pour tiered : trouve le palier applicable selon le montant
  3. Calcule le frais brut
  4. Applique le plafonnement min/max si configure
  5. Retourne le detail complet du calcul

5. Limites de transactions

TransactionLimit

Definit des plafonds de montant par type de transaction, type de limite et type d'entite.

ChampTypeDescription
transaction_type_iduuidFK → TransactionType
limit_typeenumper_transaction, daily, monthly
entity_typeenumuser, merchant, agent, organization, role, global, customer
entity_iduuidID specifique (null pour les limites globales/role)
amountdecimal(15,4)Montant plafond
currency_iduuidFK → Currency (optionnel)
effective_from / effective_todatePeriode de validite
scheduled_statusenumactive, scheduled, cancelled

Hierarchie des limites

Les limites sont evaluees par ordre de specificite. La plus restrictive s'applique :

user/customer (specifique)     ← la plus prioritaire
  └── merchant/agent
        └── organization
              └── role
                    └── global              ← la moins prioritaire

GET /transaction-limits/applicable/:transactionTypeId

Retourne les limites applicables consolidees (per_transaction, daily, monthly) pour un type de transaction, en appliquant la hierarchie ci-dessus.

json
// Reponse
{
  "perTransaction": { "id": "...", "amount": 500000, "entity_type": "global" },
  "daily": { "id": "...", "amount": 2000000, "entity_type": "role" },
  "monthly": { "id": "...", "amount": 10000000, "entity_type": "global" },
  "limits": [ /* toutes les limites brutes */ ]
}

Simulation de limites

POST /transaction-limits/simulate

Verifie si un montant respecte les limites configurees.

json
// Requete
{
  "limit_type": "per_transaction",
  "entity_type": "user",
  "entity_id": "uuid-optionnel",
  "transaction_type_id": "uuid",
  "test_amount": 750000,
  "test_date": "2025-01-15"
}

// Reponse
{
  "allowed": false,
  "message": "Le montant 750000 depasse la limite de 500000",
  "limit_info": { "amount": 500000, "limit_type": "per_transaction" },
  "suggestions": [
    "Reduire le montant a 500000 maximum",
    "Diviser en plusieurs transactions"
  ]
}

Validation croisee

A la creation, le systeme verifie la coherence entre les types de limites :

  • per_transaction < daily < monthly (si les 3 existent pour la meme entite)
  • Pas de chevauchement de periodes pour le meme tuple (limit_type, entity_type, transaction_type, entity_id)

6. Commissions

Le systeme de commissions permet de definir comment les frais collectes sont redistribues entre les differents acteurs (plateforme, marchands, agents, etc.).

CommissionRule

ChampTypeDescription
rule_typevarchar(50)FEE_SPLIT, AGENT_COMMISSION, CASHBACK, REFERRAL_BONUS
transaction_type_iduuidFK → TransactionType
beneficiary_typevarchar(50)PLATFORM, CORPORATE, MERCHANT, AGENT, EMPLOYEE, CLIENT, PROVIDER
agent_type_iduuidFK → AgentType (optionnel)
provider_iduuidReference fournisseur (optionnel)
calculation_typevarchar(20)Methode de calcul
percentagedecimal(5,2)Part en pourcentage
fixed_amountdecimal(15,4)Montant fixe
is_splitbooleanFait partie d'un partage
split_group_iduuidIdentifiant du groupe de partage
fallback_beneficiary_typevarchar(50)Beneficiaire de repli
priority_orderintegerPriorite d'evaluation
min_amount / max_amountdecimal(15,4)Tranche de montant applicable
country_codevarchar(3)Pays specifique (null = global)
effective_from / effective_todatePeriode de validite

Configurations de partage

Les regles de commission sont groupees par split_group_id. Un groupe represente une configuration complete de redistribution.

POST /commission-rules/configurations cree un groupe entier :

json
{
  "transaction_type_id": "uuid-du-CASH_IN",
  "rule_type": "FEE_SPLIT",
  "rules": [
    { "beneficiary_type": "PLATFORM", "percentage": 40 },
    { "beneficiary_type": "MERCHANT", "percentage": 35 },
    { "beneficiary_type": "AGENT", "percentage": 25, "agent_type_id": "uuid-distribution" }
  ],
  "effective_from": "2025-01-01"
}

Regle metier : pour FEE_SPLIT, le total des pourcentages doit etre egal a 100%.

A la creation, les configurations precedentes pour le meme type de transaction sont automatiquement desactivees.

Simulation de commissions

POST /commission-rules/configurations/simulate

json
// Requete
{
  "transactionTypeId": "uuid",
  "feeAmount": 1500,
  "countryCode": "CG",
  "effectiveDate": "2025-06-15"
}

// Reponse
{
  "totalAmount": 1500,
  "distributions": [
    { "beneficiary_type": "PLATFORM", "percentage": 40, "amount": 600 },
    { "beneficiary_type": "MERCHANT", "percentage": 35, "amount": 525 },
    { "beneficiary_type": "AGENT", "percentage": 25, "amount": 375 }
  ],
  "validationStatus": "valid",
  "totalPercentage": 100,
  "message": "Distribution valide (100%)"
}

AgentType

Types d'agents avec leurs capacites.

ChampTypeDescription
codevarchar(50)Identifiant unique (distribution, compliance, internal...)
has_commissionbooleanPeut recevoir des commissions
requires_merchantbooleanNecessite un rattachement marchand
requires_pdvbooleanNecessite un point de vente
is_internalbooleanAgent interne NXPay
is_field_agentbooleanAgent terrain
can_be_zonedbooleanPeut etre affecte a des zones
default_commission_ratedecimal(5,2)Taux de commission par defaut
display_orderintegerOrdre d'affichage

7. Moyens de paiement par pays

PaymentMethodType

Types de moyens de paiement globaux.

ChampTypeDescription
codevarchar(20)MOBILE_MONEY, NXPAY_CARD, BANK_ACCOUNT, CRYPTO...
categoryenuminternal (gere par NXPay) ou external (tiers)
form_typeenumINTERNAL_CARD, EXTERNAL_CARD, MOBILE_MONEY, BANK, CRYPTO, OTHER
logovarchar(255)URL du logo
colorvarchar(20)Couleur associee (#FFCC00)

CountryPaymentMethodType

Disponibilite et capacites par pays avec surcharge possible.

ChampTypeDescription
country_iduuidFK → Country
payment_method_type_iduuidFK → PaymentMethodType
is_availablebooleanDisponible dans ce pays
can_paybooleanPermet les paiements (null = defaut du type)
can_fundbooleanPermet l'approvisionnement
can_receivebooleanPermet la reception
can_withdrawbooleanPermet le retrait
effective_from / effective_todatePeriode de validite

Les champs can_* a null heritent du comportement par defaut du PaymentMethodType. Quand ils sont renseignes, ils surchargent le defaut pour ce pays specifique.


8. Regles entre pays

CountryTransactionRule

Regles de transactions entre paires de pays.

ChampTypeDescription
from_country_iduuidFK → Country (pays source)
to_country_iduuidFK → Country (pays destination)
transaction_type_iduuidFK → TransactionType
is_allowedbooleanTransaction autorisee entre ces pays
min_amount / max_amountdecimal(15,4)Montants specifiques inter-pays
currency_iduuidDevise applicable
requires_kyc_levelvarchar(20)Niveau KYC requis
effective_from / effective_todatePeriode de validite

Exemple : les transferts (TRANSFER) de CG vers CM sont autorises entre 1 000 et 5 000 000 FCFA, avec KYC niveau 2 requis.

CountryTransactionThreshold

Seuils declenchant des exigences de verification par pays.

ChampTypeDescription
country_iduuidFK → Country
transaction_type_iduuidFK → TransactionType (optionnel, null = tous)
threshold_typeenumunverified_user, incomplete_profile, daily, single
amountdecimal(15,4)Montant seuil
currency_iduuidDevise
scheduled_statusenumactive, scheduled, cancelled

Exemple : au Congo, un utilisateur non verifie (unverified_user) est plafonne a 50 000 FCFA par transaction.


9. Conformite et KYC

IdentityDocumentType

Types de documents acceptes pour la verification d'identite.

ChampTypeDescription
codevarchar(50)PASSPORT, NATIONAL_ID, DRIVER_LICENSE, RESIDENCE_PERMIT...
name / name_fr / name_envarchar(100)Libelles multilingues
requires_expiry_datebooleanDate d'expiration obligatoire
requires_issue_datebooleanDate de delivrance obligatoire
requires_document_numberbooleanNumero de document obligatoire
requires_countrybooleanPays de delivrance obligatoire
has_front_sidebooleanPhoto recto requise
has_back_sidebooleanPhoto verso requise
display_orderintegerOrdre d'affichage

Profession

Referentiel des professions avec evaluation de risque.

ChampTypeDescription
professionvarchar(200)Nom de la profession
risk_levelvarchar(20)Niveau de risque (low, medium, high)
reasontextJustification du niveau de risque
categoryvarchar(50)Secteur (Commerce, Services, Agriculture...)

Les professions a risque eleve (ex: "Changeur de monnaie", "Commerce de metaux precieux") declenchent des controles supplementaires lors du KYC.


10. Agents et zones

Zone

Decoupage geographique pour l'affectation des agents terrain.

ChampTypeDescription
city_iduuidReference vers City
activity_sector_iduuidFK → ActivitySector
supervisor_iduuidReference vers l'agent superviseur
codevarchar(20)Code unique par ville (BZV-CENTRE, BZV-POTO...)
boundary_geojsonjsonbFrontiere geographique au format GeoJSON
max_agentsintegerNombre maximum d'agents dans la zone

ActivitySector

Caracterisation economique des zones.

ChampTypeDescription
codevarchar(50)PORT, INDUSTRIAL, CENTRAL_BUSINESS, MARKET, RESIDENTIAL, RURAL...
economic_levelenumhigh, medium, low
transaction_volume_estimateenumvery_high, high, medium, low
risk_levelenumhigh, medium, low (pour AML/KYC)

11. Parametres systeme

Setting

Parametres globaux cle-valeur pour toute la plateforme.

ChampTypeDescription
keyvarchar(100)Cle unique
valuetextValeur
typeenumstring, number, boolean, json
is_encryptedbooleanValeur chiffree

ServiceConfig

Configuration specifique par microservice et par environnement.

ChampTypeDescription
service_namevarchar(50)Nom du service (auth, orchestrator...)
config_keyvarchar(100)Cle de configuration
config_valuetextValeur
value_typevarchar(20)Type de valeur
environmentvarchar(20)Environnement (development, test, production)
is_encryptedbooleanValeur chiffree

12. Canaux de notification et types de service

NotificationChannel

Configuration des canaux de notification disponibles.

ChampTypeDescription
codevarchar(50)SMS, EMAIL, PUSH, WHATSAPP, IN_APP
name / name_fr / name_envarchar(100)Libelles multilingues
channel_typevarchar(50)OTP, MARKETING, TRANSACTIONAL, ALERT
providervarchar(100)WIREPICK, MAILGUN, FIREBASE, CUSTOM
is_default_for_otpbooleanCanal par defaut pour les OTP
supports_attachmentsbooleanSupport des pieces jointes
configjsonbConfiguration specifique au provider

SystemServiceType

Types de services systeme exposes sur la plateforme.

ChampTypeDescription
codevarchar(50)PAYMENT, TRANSFER, CASH_IN, CASH_OUT, BILL_PAYMENT, AIRTIME
name / name_fr / name_envarchar(100)Libelles multilingues
categoryvarchar(50)PAYMENT, TRANSFER, CASH, BILL, AIRTIME, INFORMATION
iconvarchar(255)URL de l'icone
display_orderintegerOrdre d'affichage dans l'app

13. Patterns API communs

CRUD standard

Chaque entite expose un ensemble standardise de routes :

POST   /v1/{entite}                 Creer
GET    /v1/{entite}                 Lister (pagination : ?page=1&limit=20)
GET    /v1/{entite}/active          Lister les actifs uniquement
GET    /v1/{entite}/:id             Obtenir par ID
GET    /v1/{entite}/code/:code      Obtenir par code
PATCH  /v1/{entite}/:id             Mettre a jour
PATCH  /v1/{entite}/:id/activate    Activer
PATCH  /v1/{entite}/:id/deactivate  Desactiver
DELETE /v1/{entite}/:id             Supprimer

Recherche avancee

Toutes les entites supportent POST /v1/{entite}/search avec :

json
{
  "name": "dollar",          // Recherche ILIKE (insensible a la casse)
  "code": "usd",
  "is_active": true,
  "created_after": "2025-01-01",
  "created_before": "2025-12-31",
  "page": 1,
  "limit": 20,
  "sort_by": "code",
  "sort_order": "ASC"
}

Operations en masse

Les entites supportent des operations bulk :

json
// POST /v1/{entite}/bulk-activate ou bulk-deactivate
{ "ids": ["uuid1", "uuid2", "uuid3"] }

// Reponse
{ "success": 2, "failed": 1, "errors": [{ "id": "uuid3", "error": "Not found" }] }

// POST /v1/{entite}/bulk-update
{ "updates": [{ "id": "uuid1", "name": "Nouveau nom" }, { "id": "uuid2", "is_active": false }] }

Gestion des periodes (effective dating)

Les entites temporelles (frais, limites, seuils, regles) supportent :

ChampComportement
effective_fromDate de debut de validite (defaut : aujourd'hui)
effective_toDate de fin de validite (null = pas de fin)
scheduled_statusscheduled (futur), active (en cours), cancelled (annule)

Routes dediees :

GET    /v1/{entite}/scheduled         Configurations planifiees
GET    /v1/{entite}/:id/active        Configuration active actuelle
GET    /v1/{entite}/:id/versions      Historique des versions
PATCH  /v1/{entite}/:id/cancel        Annuler une configuration planifiee
POST   /v1/{entite}/validate          Valider avant enregistrement

Format de reponse

Toutes les reponses suivent le format standardise :

json
// Succes
{
  "success": true,
  "code": "SUCCESS",
  "data": { /* entite ou tableau */ },
  "meta": { "total": 100, "page": 1, "limit": 20 }
}

// Erreur
{
  "success": false,
  "code": "CONFLICT",
  "data": null,
  "errors": ["A currency with this code already exists"]
}

Codes d'erreur metier

CodeHTTPDescription
SUCCESS200Reussite
CREATED201Entite creee
BAD_REQUEST400Donnees invalides
RESOURCE_NOT_FOUND404Entite introuvable
CONFLICT409Violation d'unicite (code, pair deja existante)
VALIDATION_ERROR422Erreur de validation metier
DATABASE_ERROR500Erreur base de donnees

Seeding des donnees de reference

bash
cd services/configuration
npm run seed:countries          # 195+ pays
npm run seed:cities             # Villes Congo/Cameroun (avec GPS)
npm run seed:activity-sectors   # 12 secteurs economiques
npm run seed:zones              # Zones geographiques

Seeds SQL supplementaires dans tools/database/seeds/ :

  • commission-rules-seed.sql
  • identity-document-types-seed.sql
  • notification-channels-seed.sql
  • system-service-types-seed.sql

Tous les seeders sont idempotents (ON CONFLICT DO NOTHING).


14. Exemples d'integration inter-services

Le service Configuration est consomme par les autres microservices via des appels HTTP internes. Voici les flux d'integration reels du projet.

Services consommateurs

ServicePattern d'integrationDonnees consommees
OrchestratorHTTP Adapter (Clean Architecture)Transaction types, frais, paliers, limites, devises
Ledger-WalletsAppels HTTP directsTypes de moyens de paiement

Variable d'environnement : CONFIGURATION_SERVICE_URL (defaut : http://configuration:3000)

14.1 Transfert P2P — Flux complet

Ce diagramme montre le workflow complet d'un transfert d'argent entre deux utilisateurs, incluant la resolution du type de transaction, le calcul des frais, et la validation des limites.

mermaid
sequenceDiagram
    participant Client
    participant Nginx
    participant Orchestrator
    participant Configuration
    participant Ledger as Ledger-Wallets
    participant Notif as Notifications

    Client->>Nginx: POST /api/transactions/transfer
    Nginx->>Orchestrator: POST /v1/transactions/transfer

    rect rgb(240, 248, 255)
        Note over Orchestrator,Configuration: Phase 1 - Resolution du type de transaction
        Orchestrator->>Configuration: GET /v1/transaction-types/code/TRANSFER
        Configuration-->>Orchestrator: { id, code, minAmount, maxAmount }
    end

    rect rgb(240, 255, 240)
        Note over Orchestrator,Configuration: Phase 2 - Resolution de la devise
        Orchestrator->>Configuration: GET /v1/currencies/code/XAF
        Configuration-->>Orchestrator: { id, code, symbol, minor_unit }
    end

    rect rgb(255, 248, 240)
        Note over Orchestrator,Configuration: Phase 3 - Validation des limites
        Orchestrator->>Configuration: GET /v1/transaction-limits/applicable/{typeId}?entityType=user&entityId={senderId}
        Configuration-->>Orchestrator: { perTransaction: 500000, daily: 2000000, monthly: 10000000 }
        Note over Orchestrator: Verifie montant <= perTransaction
    end

    rect rgb(248, 240, 255)
        Note over Orchestrator,Configuration: Phase 4 - Calcul des frais
        Orchestrator->>Configuration: GET /v1/transaction-type-fees/transaction-type/{typeId}
        Configuration-->>Orchestrator: [ { id, calculation_method: "tiered", fee_type, paid_by } ]
        Orchestrator->>Configuration: GET /v1/fee-tiers/transaction-type-fee/{feeId}
        Configuration-->>Orchestrator: [ { tier_order: 1, min: 0, max: 10000, fixed: 200 }, ... ]
        Note over Orchestrator: Calcule le frais selon le palier applicable
    end

    rect rgb(255, 255, 240)
        Note over Orchestrator,Ledger: Phase 5 - Execution
        Orchestrator->>Ledger: Debit source + Credit destination
        Ledger-->>Orchestrator: Transaction confirmee
    end

    Orchestrator->>Notif: Notification async (fire-and-forget)
    Orchestrator-->>Nginx: { success: true, data: { transactionId, fees, ... } }
    Nginx-->>Client: 200 OK

Appels Configuration dans ce flux :

GET /v1/transaction-types/code/TRANSFER
GET /v1/currencies/code/XAF
GET /v1/transaction-limits/applicable/{typeId}?entityType=user&entityId={senderId}
GET /v1/transaction-type-fees/transaction-type/{typeId}
GET /v1/fee-tiers/transaction-type-fee/{feeId}

14.2 Cash-In Agent — Flux avec resolution de devise

mermaid
sequenceDiagram
    participant Agent as App Agent
    participant Orchestrator
    participant Configuration
    participant Ledger as Ledger-Wallets

    Agent->>Orchestrator: POST /v1/transactions/agent-cash-in
    Orchestrator->>Configuration: GET /v1/transaction-types/code/AGENT_CASH_IN
    Configuration-->>Orchestrator: { id, code, minAmount: 500, maxAmount: 5000000 }

    Note over Orchestrator: Valide montant dans [500, 5000000]

    Orchestrator->>Configuration: GET /v1/currencies/code/XAF
    Configuration-->>Orchestrator: { id: "uuid-xaf", code: "XAF", symbol: "FCFA" }

    Orchestrator->>Ledger: Credit wallet client + Debit float agent
    Ledger-->>Orchestrator: OK

    Orchestrator-->>Agent: { success: true, transactionId: "..." }

14.3 Calcul des frais — 3 methodes de calcul

mermaid
flowchart TD
    A["Orchestrator: CalculateFeesUseCase"] --> B["GET /v1/transaction-type-fees/transaction-type/{id}"]
    B --> C{calculation_method ?}

    C -->|fixed| D["Frais = amount<br/>(ex: 200 FCFA)"]
    C -->|percentage| E["Frais = montant × percentage<br/>Plafonne entre min_amount et max_amount"]
    C -->|tiered| F["GET /v1/fee-tiers/transaction-type-fee/{feeId}"]

    F --> G["Trouve le palier applicable<br/>selon min_amount <= montant < max_amount"]
    G --> H{"Le palier a un<br/>fixed_amount ?"}
    H -->|Oui| I["Frais = fixed_amount du palier"]
    H -->|Non| J["Frais = montant × percentage du palier"]

    D --> K["Retourne le frais calcule"]
    E --> K
    I --> K
    J --> K

Exemple concret — Frais degressifs sur TRANSFER :

json
// 1. GET /v1/transaction-type-fees/transaction-type/{transferTypeId}
// Reponse :
{
  "success": true,
  "data": [{
    "id": "fee-uuid-1",
    "fee_type": { "code": "SERVICE_FEE", "name": "Frais de service" },
    "calculation_method": "tiered",
    "paid_by": "sender",
    "effective_from": "2025-01-01",
    "scheduled_status": "active"
  }]
}

// 2. GET /v1/fee-tiers/transaction-type-fee/fee-uuid-1
// Reponse :
{
  "success": true,
  "data": [
    { "tier_order": 1, "min_amount": 0,      "max_amount": 10000,  "fixed_amount": 200, "percentage": null },
    { "tier_order": 2, "min_amount": 10000,   "max_amount": 100000, "fixed_amount": null, "percentage": 0.015 },
    { "tier_order": 3, "min_amount": 100000,  "max_amount": null,   "fixed_amount": null, "percentage": 0.01 }
  ]
}

// Calcul pour un transfert de 50 000 FCFA :
// → Palier 2 applicable (10000 <= 50000 < 100000)
// → Frais = 50000 × 1.5% = 750 FCFA

14.4 Resolution de moyen de paiement — Ledger-Wallets

Le service Ledger-Wallets appelle directement le service Configuration (sans adapter) pour resoudre les types de moyens de paiement.

mermaid
sequenceDiagram
    participant Orchestrator
    participant Ledger as Ledger-Wallets
    participant Configuration

    Orchestrator->>Ledger: Creer wallet avec moyen de paiement

    rect rgb(240, 248, 255)
        Note over Ledger,Configuration: Resolution du type de moyen de paiement
        Ledger->>Configuration: GET /v1/payment-method-types/code/MTN_CG
        Configuration-->>Ledger: { id, code: "MTN_CG", name: "MTN Mobile Money", category: "external", form_type: "MOBILE_MONEY" }
    end

    Note over Ledger: Cree le payment method avec le payment_method_type_id resolu
    Ledger-->>Orchestrator: Payment method cree

Endpoints appeles par Ledger-Wallets :

GET /v1/payment-method-types/code/{code}    # Resolution par code
GET /v1/payment-method-types/{id}           # Resolution par ID

14.5 Validation des limites — Hierarchie d'application

mermaid
flowchart TD
    A["Orchestrator: ProcessTransferUseCase"] --> B["GET /v1/transaction-limits/applicable/{typeId}<br/>?entityType=user&entityId={userId}"]

    B --> C["Configuration: recherche les limites"]

    C --> D{"Limite specifique<br/>a l'utilisateur ?"}
    D -->|Oui| E["Retourne limite user"]
    D -->|Non| F{"Limite par<br/>role/merchant ?"}
    F -->|Oui| G["Retourne limite role"]
    F -->|Non| H["Retourne limite globale"]

    E --> I["Orchestrator valide :<br/>montant <= perTransaction<br/>cumul jour <= daily<br/>cumul mois <= monthly"]
    G --> I
    H --> I

    I --> J{Valide ?}
    J -->|Oui| K["Continue le workflow"]
    J -->|Non| L["Erreur 400 :<br/>TRANSACTION_LIMIT_EXCEEDED"]

Exemple de reponse :

json
// GET /v1/transaction-limits/applicable/{typeId}?entityType=user&entityId=uuid-user-1
{
  "success": true,
  "data": {
    "perTransaction": { "id": "lim-1", "amount": 500000, "entity_type": "global" },
    "daily":          { "id": "lim-2", "amount": 2000000, "entity_type": "role" },
    "monthly":        { "id": "lim-3", "amount": 10000000, "entity_type": "global" },
    "limits": [
      { "id": "lim-1", "limit_type": "per_transaction", "entity_type": "global", "amount": 500000 },
      { "id": "lim-2", "limit_type": "daily", "entity_type": "role", "amount": 2000000 },
      { "id": "lim-3", "limit_type": "monthly", "entity_type": "global", "amount": 10000000 }
    ]
  }
}

14.6 Configuration complete d'un pays — Endpoint d'agregation

Cet endpoint retourne toutes les donnees de configuration d'un pays en un seul appel. Utile pour l'initialisation d'un client mobile.

mermaid
flowchart LR
    A["GET /v1/countries/{id}/configuration"] --> B["Country"]
    A --> C["CountryCurrency[]"]
    A --> D["CountryPaymentMethodType[]"]
    A --> E["TransactionType[]"]
    A --> F["TransactionLimit[]"]
    A --> G["CountryTransactionRule[]"]
    A --> H["CountryTransactionThreshold[]"]
    A --> I["TransactionTypeFee[] + FeeTier[]"]

Reponse type :

json
{
  "success": true,
  "data": {
    "country": { "code": "CG", "name": "Congo", "risk_level": "low" },
    "currencies": [
      { "code": "XAF", "symbol": "FCFA", "is_primary": true }
    ],
    "paymentMethods": [
      { "code": "MTN_CG", "category": "external", "can_pay": true, "can_fund": true }
    ],
    "transactionTypes": [
      { "code": "TRANSFER", "min_amount": 100, "max_amount": 5000000 },
      { "code": "CASH_IN", "min_amount": 500, "max_amount": 2000000 }
    ],
    "limits": [
      { "transaction_type": "TRANSFER", "limit_type": "per_transaction", "amount": 500000 }
    ],
    "rules": [
      { "to_country": "CM", "transaction_type": "TRANSFER", "is_allowed": true }
    ],
    "thresholds": [
      { "threshold_type": "unverified_user", "amount": 50000, "currency": "XAF" }
    ],
    "fees": [
      { "transaction_type": "TRANSFER", "calculation_method": "tiered", "tiers": [...] }
    ]
  }
}

14.7 Mapping snake_case / camelCase

L'adapter HTTP de l'Orchestrator transforme les reponses du service Configuration (snake_case) vers le format interne (camelCase) :

text
Configuration API (snake_case)          Orchestrator interne (camelCase)
─────────────────────────────          ──────────────────────────────────
min_amount                       →     minAmount
max_amount                       →     maxAmount
transaction_type_id              →     transactionTypeId
fee_type_id                      →     feeTypeId
calculation_method               →     calculationMethod
effective_from                   →     effectiveFrom
scheduled_status                 →     scheduledStatus
minor_unit                       →     minorUnit

14.8 Resilience — Valeurs par defaut

Si le service Configuration est indisponible, l'Orchestrator utilise des limites par defaut pour ne pas bloquer les transactions :

json
{
  "perTransaction": 500000,
  "daily": 1000000,
  "weekly": 5000000,
  "monthly": 20000000
}

Attention : Ce mecanisme de fallback ne s'applique qu'aux limites. Si la resolution du type de transaction ou de la devise echoue, la transaction est rejetee.

NxPay — Plateforme fintech CEMAC