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.
| Concept | Ou ? | Role | Exemple |
|---|---|---|---|
TransactionType.min_amount / max_amount | Dans la definition du type | Limites globales techniques du type de transaction | TRANSFER : min=100, max=5000000 (personne ne peut transferer moins de 100 ni plus de 5M) |
TransactionLimit | Entite separee | Limites 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 :
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" ?
| Concept | Role | Exemple |
|---|---|---|
TransactionChannel | Referentiel de tous les canaux existants | MOBILE_MONEY, CARD, BANK_TRANSFER, CASH, NXPAY_WALLET |
AuthorizedChannel | Matrice d'autorisation : quel canal peut etre utilise pour quel type de transaction | TRANSFER autorise sur MOBILE_MONEY et NXPAY_WALLET, mais PAS sur CASH |
Exemple concret :
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 :
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
| Concept | Ou ? | Role | Exemple |
|---|---|---|---|
PaymentMethodType | Configuration service | Template des moyens de paiement disponibles | MTN_CG, VODAFONE_CG, VISA, MASTERCARD |
CountryPaymentMethodType | Configuration service | Disponibilite par pays avec capacites | MTN_CG au Congo : peut payer, peut recharger, peut retirer |
PaymentMethod | Ledger-Wallets service | Instance d'un moyen de paiement pour un utilisateur | Le compte MTN de Jean (+242 06 123 4567) |
Flow :
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 :
| Code | Description | has_commission | is_field_agent | can_be_zoned | requires_merchant |
|---|---|---|---|---|---|
distribution | Agent de distribution (cash in/out) | ✓ | ✓ | ✓ | ✓ |
compliance | Agent de verification KYC | ✗ | ✓ | ✓ | ✗ |
internal | Agent interne NXPay | ✓ | ✗ | ✗ | ✗ |
field | Agent terrain generique | ✓ | ✓ | ✓ | ✗ |
master | Agent maitre (gere d'autres agents) | ✓ | ✗ | ✓ | ✓ |
Utilisation :
- Les
CommissionRulepeuvent etre specifiques a unagent_type_id - Les agents
distributiondoivent etre rattaches a un marchand (requires_merchant=true) - Les agents
field_agentpeuvent etre affectes a des zones geographiques (can_be_zoned=true)
Exemple :
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 ?
| Concept | Portee | Exemple | Usage |
|---|---|---|---|
Setting | Global pour toute la plateforme | maintenance_mode=false, max_daily_transactions=10000 | Parametres globaux partages par tous les services |
ServiceConfig | Specifique a un service et un environnement | orchestrator.timeout=30000 (production), auth.jwt_expiry=3600 (development) | Configuration par service et environnement |
Exemple :
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: 604800Les 26 entites du service (liste complete)
🌍 Geographie et devises (5)
- Country - Pays (Congo, Cameroun, RDC...)
- Currency - Devises (XAF, USD, EUR...)
- CountryCurrency - Association pays-devises
- City - Villes avec coordonnees GPS
- CountryPaymentMethodType - Disponibilite des moyens de paiement par pays
💳 Transactions (4)
- TransactionType - Types de transactions (TRANSFER, CASH_IN, PAYMENT...)
- TransactionChannel - Canaux disponibles (MOBILE_MONEY, CARD, CASH...)
- AuthorizedChannel - Matrice type/canal autorise
- TransactionBetween - Matrice role source/role destination
💰 Frais (3)
- FeeType - Types de frais (COMMISSION, TAX, SERVICE_FEE...)
- TransactionTypeFee - Configuration de calcul par type de transaction
- FeeTier - Paliers pour les frais degressifs/progressifs
🚦 Limites (1)
- TransactionLimit - Limites par entite/periode
🎯 Commissions (2)
- CommissionRule - Regles de redistribution des frais
- AgentType - Types d'agents avec capacites
💳 Moyens de paiement (1)
- PaymentMethodType - Types de moyens de paiement (MTN, Airtel, VISA...)
🌐 Regles inter-pays (2)
- CountryTransactionRule - Regles entre paires de pays
- CountryTransactionThreshold - Seuils KYC par pays
✅ Conformite et KYC (2)
- IdentityDocumentType - Types de documents acceptes
- Profession - Professions avec evaluation de risque
📍 Agents et zones (2)
- Zone - Decoupage geographique des villes
- ActivitySector - Profils economiques des zones
⚙️ Parametres systeme (2)
- Setting - Parametres globaux cle-valeur
- ServiceConfig - Configuration par service/environnement
📢 Notifications et services (2)
- NotificationChannel - Canaux de notification (SMS, EMAIL, PUSH...)
- SystemServiceType - Types de services exposes (PAYMENT, TRANSFER...)
Table des matieres
- Modele de donnees
- Geographie et devises
- Types de transactions et canaux
- Systeme de frais
- Limites de transactions
- Commissions
- Moyens de paiement par pays
- Regles entre pays
- Conformite et KYC
- Agents et zones
- Parametres systeme
- Canaux de notification et types de service
- Patterns API communs
- Exemples d'integration
1. Modele de donnees
Vue d'ensemble des relations
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
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
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
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
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
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
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 :
| Schema | Contenu | Raison |
|---|---|---|
shared | Country, Currency, CountryCurrency, City | Donnees partagees, referencees par d'autres services |
configuration | Tout 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.
| Champ | Type | Description |
|---|---|---|
code | varchar(2) | Code ISO 3166-1 alpha-2, unique (ex: CG, CM, FR) |
code3 | varchar(3) | Code ISO 3166-1 alpha-3, unique (ex: COG, CMR, FRA) |
name / name_en | varchar(100) | Nom en francais / anglais |
region | varchar(50) | Region geographique |
phone_code | varchar(10) | Indicatif telephonique (+242, +237) |
numeric_code | varchar(3) | Code ISO numerique |
time_zone | varchar(50) | Fuseau horaire |
risk_level | enum | low, medium, high, blocked |
sanction_status | enum | none, partial, full |
is_active | boolean | Pays 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 risqueCurrency
Referentiel des devises ISO 4217.
| Champ | Type | Description |
|---|---|---|
code | varchar(3) | Code ISO (EUR, USD, XAF), normalise en majuscules |
numeric_code | varchar(3) | Code numerique ISO (978, 840, 950), padde a 3 chiffres |
symbol | varchar(10) | Symbole (FCFA, $, EUR) |
minor_unit | integer | Nombre de decimales (2 pour EUR, 0 pour JPY) |
reporting_threshold | decimal(15,2) | Seuil de reporting reglementaire |
CountryCurrency
Association N-N entre pays et devises.
| Champ | Type | Description |
|---|---|---|
country_id | uuid | FK → Country |
currency_id | uuid | FK → Currency |
is_primary | boolean | Devise principale du pays |
effective_from | date | Date d'effet |
Un pays peut avoir plusieurs devises. Une seule est marquee is_primary.
City
Villes rattachees a un pays.
| Champ | Type | Description |
|---|---|---|
country_id | uuid | Reference vers Country (indexe, sans FK cross-schema) |
name | varchar(100) | Nom de la ville |
code | varchar(20) | Code ville |
latitude / longitude | decimal | Coordonnees GPS |
3. Types de transactions et canaux
TransactionType
Definit les types de transactions disponibles sur la plateforme.
| Champ | Type | Description |
|---|---|---|
code | varchar(20) | Identifiant unique (TRANSFER, PAYMENT, CASH_IN, CASH_OUT, BILL_PAYMENT...) |
name | varchar(100) | Libelle |
category | varchar(50) | Categorie metier |
requires_kyc | boolean | Necessite une verification KYC |
min_amount / max_amount | decimal(15,4) | Montants limites globaux |
default_currency_id | uuid | Devise 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...).
| Champ | Type | Description |
|---|---|---|
code | varchar(20) | Identifiant unique |
name | varchar(100) | Libelle |
AuthorizedChannel
Definit quels canaux sont autorises pour chaque type de transaction.
| Champ | Type | Description |
|---|---|---|
transaction_type_id | uuid | FK → TransactionType |
transaction_channel_id | uuid | FK → TransactionChannel |
is_active | boolean | Autorisation 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.
| Champ | Type | Description |
|---|---|---|
transaction_type_id | uuid | FK → TransactionType |
from_role | varchar(50) | Role source (user, merchant, agent...) |
to_role | varchar(50) | Role destination |
is_authorized | boolean | Transaction 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.
| Champ | Type | Description |
|---|---|---|
code | varchar(20) | Identifiant unique (COMMISSION, TAX, SERVICE_FEE...) |
name | varchar(100) | Libelle |
is_mandatory | boolean | Frais obligatoire |
calculation_order | integer | Ordre de calcul (les frais sont calcules sequentiellement) |
TransactionTypeFee
Configuration de calcul d'un frais pour un type de transaction donne.
| Champ | Type | Description |
|---|---|---|
transaction_type_id | uuid | FK → TransactionType |
fee_type_id | uuid | FK → FeeType |
calculation_method | enum | fixed, percentage, ou tiered |
amount | decimal(15,4) | Montant fixe (si fixed) |
percentage | decimal(5,4) | Pourcentage (si percentage) |
min_amount / max_amount | decimal(15,4) | Plafonnement min/max du frais calcule |
paid_by | enum | sender, recipient, platform, merchant |
effective_from / effective_to | date | Periode de validite |
scheduled_status | enum | active, 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.
| Champ | Type | Description |
|---|---|---|
transaction_type_fee_id | uuid | FK → TransactionTypeFee |
tier_order | integer | Ordre du palier (1, 2, 3...) |
min_amount / max_amount | decimal(15,4) | Tranche de montant |
fixed_amount | decimal(15,4) | Frais fixe pour cette tranche |
percentage | decimal(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_orderunique et sequentiel
Exemple (frais degressifs sur un TRANSFER) :
| Palier | Tranche | Frais |
|---|---|---|
| 1 | 0 - 10 000 FCFA | 200 FCFA fixe |
| 2 | 10 000 - 100 000 FCFA | 1.5% |
| 3 | 100 000+ FCFA | 1% (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.
// 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 :
- Identifie la methode de calcul (fixed, percentage, tiered)
- Pour
tiered: trouve le palier applicable selon le montant - Calcule le frais brut
- Applique le plafonnement min/max si configure
- 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.
| Champ | Type | Description |
|---|---|---|
transaction_type_id | uuid | FK → TransactionType |
limit_type | enum | per_transaction, daily, monthly |
entity_type | enum | user, merchant, agent, organization, role, global, customer |
entity_id | uuid | ID specifique (null pour les limites globales/role) |
amount | decimal(15,4) | Montant plafond |
currency_id | uuid | FK → Currency (optionnel) |
effective_from / effective_to | date | Periode de validite |
scheduled_status | enum | active, 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 prioritaireGET /transaction-limits/applicable/:transactionTypeId
Retourne les limites applicables consolidees (per_transaction, daily, monthly) pour un type de transaction, en appliquant la hierarchie ci-dessus.
// 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.
// 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
| Champ | Type | Description |
|---|---|---|
rule_type | varchar(50) | FEE_SPLIT, AGENT_COMMISSION, CASHBACK, REFERRAL_BONUS |
transaction_type_id | uuid | FK → TransactionType |
beneficiary_type | varchar(50) | PLATFORM, CORPORATE, MERCHANT, AGENT, EMPLOYEE, CLIENT, PROVIDER |
agent_type_id | uuid | FK → AgentType (optionnel) |
provider_id | uuid | Reference fournisseur (optionnel) |
calculation_type | varchar(20) | Methode de calcul |
percentage | decimal(5,2) | Part en pourcentage |
fixed_amount | decimal(15,4) | Montant fixe |
is_split | boolean | Fait partie d'un partage |
split_group_id | uuid | Identifiant du groupe de partage |
fallback_beneficiary_type | varchar(50) | Beneficiaire de repli |
priority_order | integer | Priorite d'evaluation |
min_amount / max_amount | decimal(15,4) | Tranche de montant applicable |
country_code | varchar(3) | Pays specifique (null = global) |
effective_from / effective_to | date | Periode 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 :
{
"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
// 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.
| Champ | Type | Description |
|---|---|---|
code | varchar(50) | Identifiant unique (distribution, compliance, internal...) |
has_commission | boolean | Peut recevoir des commissions |
requires_merchant | boolean | Necessite un rattachement marchand |
requires_pdv | boolean | Necessite un point de vente |
is_internal | boolean | Agent interne NXPay |
is_field_agent | boolean | Agent terrain |
can_be_zoned | boolean | Peut etre affecte a des zones |
default_commission_rate | decimal(5,2) | Taux de commission par defaut |
display_order | integer | Ordre d'affichage |
7. Moyens de paiement par pays
PaymentMethodType
Types de moyens de paiement globaux.
| Champ | Type | Description |
|---|---|---|
code | varchar(20) | MOBILE_MONEY, NXPAY_CARD, BANK_ACCOUNT, CRYPTO... |
category | enum | internal (gere par NXPay) ou external (tiers) |
form_type | enum | INTERNAL_CARD, EXTERNAL_CARD, MOBILE_MONEY, BANK, CRYPTO, OTHER |
logo | varchar(255) | URL du logo |
color | varchar(20) | Couleur associee (#FFCC00) |
CountryPaymentMethodType
Disponibilite et capacites par pays avec surcharge possible.
| Champ | Type | Description |
|---|---|---|
country_id | uuid | FK → Country |
payment_method_type_id | uuid | FK → PaymentMethodType |
is_available | boolean | Disponible dans ce pays |
can_pay | boolean | Permet les paiements (null = defaut du type) |
can_fund | boolean | Permet l'approvisionnement |
can_receive | boolean | Permet la reception |
can_withdraw | boolean | Permet le retrait |
effective_from / effective_to | date | Periode 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.
| Champ | Type | Description |
|---|---|---|
from_country_id | uuid | FK → Country (pays source) |
to_country_id | uuid | FK → Country (pays destination) |
transaction_type_id | uuid | FK → TransactionType |
is_allowed | boolean | Transaction autorisee entre ces pays |
min_amount / max_amount | decimal(15,4) | Montants specifiques inter-pays |
currency_id | uuid | Devise applicable |
requires_kyc_level | varchar(20) | Niveau KYC requis |
effective_from / effective_to | date | Periode 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.
| Champ | Type | Description |
|---|---|---|
country_id | uuid | FK → Country |
transaction_type_id | uuid | FK → TransactionType (optionnel, null = tous) |
threshold_type | enum | unverified_user, incomplete_profile, daily, single |
amount | decimal(15,4) | Montant seuil |
currency_id | uuid | Devise |
scheduled_status | enum | active, 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.
| Champ | Type | Description |
|---|---|---|
code | varchar(50) | PASSPORT, NATIONAL_ID, DRIVER_LICENSE, RESIDENCE_PERMIT... |
name / name_fr / name_en | varchar(100) | Libelles multilingues |
requires_expiry_date | boolean | Date d'expiration obligatoire |
requires_issue_date | boolean | Date de delivrance obligatoire |
requires_document_number | boolean | Numero de document obligatoire |
requires_country | boolean | Pays de delivrance obligatoire |
has_front_side | boolean | Photo recto requise |
has_back_side | boolean | Photo verso requise |
display_order | integer | Ordre d'affichage |
Profession
Referentiel des professions avec evaluation de risque.
| Champ | Type | Description |
|---|---|---|
profession | varchar(200) | Nom de la profession |
risk_level | varchar(20) | Niveau de risque (low, medium, high) |
reason | text | Justification du niveau de risque |
category | varchar(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.
| Champ | Type | Description |
|---|---|---|
city_id | uuid | Reference vers City |
activity_sector_id | uuid | FK → ActivitySector |
supervisor_id | uuid | Reference vers l'agent superviseur |
code | varchar(20) | Code unique par ville (BZV-CENTRE, BZV-POTO...) |
boundary_geojson | jsonb | Frontiere geographique au format GeoJSON |
max_agents | integer | Nombre maximum d'agents dans la zone |
ActivitySector
Caracterisation economique des zones.
| Champ | Type | Description |
|---|---|---|
code | varchar(50) | PORT, INDUSTRIAL, CENTRAL_BUSINESS, MARKET, RESIDENTIAL, RURAL... |
economic_level | enum | high, medium, low |
transaction_volume_estimate | enum | very_high, high, medium, low |
risk_level | enum | high, medium, low (pour AML/KYC) |
11. Parametres systeme
Setting
Parametres globaux cle-valeur pour toute la plateforme.
| Champ | Type | Description |
|---|---|---|
key | varchar(100) | Cle unique |
value | text | Valeur |
type | enum | string, number, boolean, json |
is_encrypted | boolean | Valeur chiffree |
ServiceConfig
Configuration specifique par microservice et par environnement.
| Champ | Type | Description |
|---|---|---|
service_name | varchar(50) | Nom du service (auth, orchestrator...) |
config_key | varchar(100) | Cle de configuration |
config_value | text | Valeur |
value_type | varchar(20) | Type de valeur |
environment | varchar(20) | Environnement (development, test, production) |
is_encrypted | boolean | Valeur chiffree |
12. Canaux de notification et types de service
NotificationChannel
Configuration des canaux de notification disponibles.
| Champ | Type | Description |
|---|---|---|
code | varchar(50) | SMS, EMAIL, PUSH, WHATSAPP, IN_APP |
name / name_fr / name_en | varchar(100) | Libelles multilingues |
channel_type | varchar(50) | OTP, MARKETING, TRANSACTIONAL, ALERT |
provider | varchar(100) | WIREPICK, MAILGUN, FIREBASE, CUSTOM |
is_default_for_otp | boolean | Canal par defaut pour les OTP |
supports_attachments | boolean | Support des pieces jointes |
config | jsonb | Configuration specifique au provider |
SystemServiceType
Types de services systeme exposes sur la plateforme.
| Champ | Type | Description |
|---|---|---|
code | varchar(50) | PAYMENT, TRANSFER, CASH_IN, CASH_OUT, BILL_PAYMENT, AIRTIME |
name / name_fr / name_en | varchar(100) | Libelles multilingues |
category | varchar(50) | PAYMENT, TRANSFER, CASH, BILL, AIRTIME, INFORMATION |
icon | varchar(255) | URL de l'icone |
display_order | integer | Ordre 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 SupprimerRecherche avancee
Toutes les entites supportent POST /v1/{entite}/search avec :
{
"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 :
// 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 :
| Champ | Comportement |
|---|---|
effective_from | Date de debut de validite (defaut : aujourd'hui) |
effective_to | Date de fin de validite (null = pas de fin) |
scheduled_status | scheduled (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 enregistrementFormat de reponse
Toutes les reponses suivent le format standardise :
// 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
| Code | HTTP | Description |
|---|---|---|
SUCCESS | 200 | Reussite |
CREATED | 201 | Entite creee |
BAD_REQUEST | 400 | Donnees invalides |
RESOURCE_NOT_FOUND | 404 | Entite introuvable |
CONFLICT | 409 | Violation d'unicite (code, pair deja existante) |
VALIDATION_ERROR | 422 | Erreur de validation metier |
DATABASE_ERROR | 500 | Erreur base de donnees |
Seeding des donnees de reference
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 geographiquesSeeds SQL supplementaires dans tools/database/seeds/ :
commission-rules-seed.sqlidentity-document-types-seed.sqlnotification-channels-seed.sqlsystem-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
| Service | Pattern d'integration | Donnees consommees |
|---|---|---|
| Orchestrator | HTTP Adapter (Clean Architecture) | Transaction types, frais, paliers, limites, devises |
| Ledger-Wallets | Appels HTTP directs | Types 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.
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 OKAppels 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
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
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 --> KExemple concret — Frais degressifs sur TRANSFER :
// 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 FCFA14.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.
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 creeEndpoints appeles par Ledger-Wallets :
GET /v1/payment-method-types/code/{code} # Resolution par code
GET /v1/payment-method-types/{id} # Resolution par ID14.5 Validation des limites — Hierarchie d'application
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 :
// 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.
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 :
{
"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) :
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 → minorUnit14.8 Resilience — Valeurs par defaut
Si le service Configuration est indisponible, l'Orchestrator utilise des limites par defaut pour ne pas bloquer les transactions :
{
"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.