Wave Money a explosé au Sénégal (2018) puis a étendu à la Côte d'Ivoire (2021), au Mali, au Burkina Faso, en Ouganda. Pour un e-commerce panafricain, intégrer Wave dans plusieurs pays est tentant mais piégeux : chaque pays a son endpoint, ses limites, ses devises, ses fees.
TL;DR
- Wave SN : XOF, frais 1 %, leader marché ~52 %.
- Wave CI : XOF, frais 1 % aussi, ~30 % market share, croissance forte.
- Endpoints API séparés selon pays + clés API séparées.
- Architecture recommandée : 1 connector Wave avec config per-country.
Comparaison Wave SN vs Wave CI
| Critère | Wave Sénégal | Wave Côte d'Ivoire |
|---|---|---|
| Lancement | 2018 | 2021 |
| Devise | XOF | XOF |
| Frais commerçant | 1 % | 1 % |
| Plafond paiement | 5M XOF/jour | 3M XOF/jour |
| Endpoint API | api.wave.com (SN) | api.wave.com/ci (CI) |
| Webhook | HMAC-SHA256 | HMAC-SHA256 |
| Reversement | T+1 IBAN UEMOA | T+1 IBAN UEMOA |
| Sandbox | ✗ | ✗ |
| Market share | ~52 % | ~30 % |
| Concurrence | OM, Free | MTN MoMo, Orange CI |
L'absence de sandbox dans les deux pays oblige à tester en prod avec petits montants.
Architecture connector multi-pays
`ts
// lib/payments/wave/index.ts
type WaveCountry = 'sn' | 'ci' | 'ml' | 'bf' | 'ug';
interface WaveConfig {
country: WaveCountry;
apiKey: string;
webhookSecret: string;
apiBase: string;
currency: string;
maxAmountPerDay: number;
}
const WAVE_CONFIGS: Record
sn: { country: 'sn', apiBase: 'https://api.wave.com', currency: 'XOF', maxAmountPerDay: 5_000_000 },
ci: { country: 'ci', apiBase: 'https://api.wave.com/ci', currency: 'XOF', maxAmountPerDay: 3_000_000 },
ml: { country: 'ml', apiBase: 'https://api.wave.com/ml', currency: 'XOF', maxAmountPerDay: 2_000_000 },
bf: { country: 'bf', apiBase: 'https://api.wave.com/bf', currency: 'XOF', maxAmountPerDay: 2_000_000 },
ug: { country: 'ug', apiBase: 'https://api.wave.com/ug', currency: 'UGX', maxAmountPerDay: 7_500_000 },
};
function getWaveConfig(country: WaveCountry): WaveConfig {
const base = WAVE_CONFIGS[country];
const apiKey = process.env[WAVE_${country.toUpperCase()}_API_KEY];
const webhookSecret = process.env[WAVE_${country.toUpperCase()}_WEBHOOK_SECRET];
if (!apiKey || !webhookSecret) {
throw new Error(Missing Wave config for country: ${country});
}
return { ...base, apiKey, webhookSecret };
}
export async function initWavePayment(country: WaveCountry, orderId: string, amountXof: number) {
const config = getWaveConfig(country);
if (amountXof > config.maxAmountPerDay) {
throw new Error(Amount exceeds Wave ${country.toUpperCase()} daily cap);
}
const res = await fetch(${config.apiBase}/v1/checkout/sessions, {
method: 'POST',
headers: {
'Authorization': Bearer ${config.apiKey},
'Content-Type': 'application/json',
},
body: JSON.stringify({
amount: String(amountXof),
currency: config.currency,
success_url: https://kolonell.com/checkout/success?order=${orderId},
error_url: https://kolonell.com/checkout/error?order=${orderId},
client_reference: orderId,
}),
});
return res.json();
}
`
Besoin d'un site web professionnel ?
Kolonell crée des sites web qui attirent des clients, optimisés pour le marché sénégalais. Devis gratuit en 2 minutes.
Webhook handler unifié
`ts
// app/api/webhooks/wave/[country]/route.ts
export async function POST(req: NextRequest, { params }: { params: { country: string }}) {
const country = params.country as WaveCountry;
const config = getWaveConfig(country);
const rawBody = await req.text();
const signature = req.headers.get('wave-signature') ?? '';
const expected = crypto
.createHmac('sha256', config.webhookSecret)
.update(rawBody)
.digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
return NextResponse.json({ error: 'invalid_signature' }, { status: 401 });
}
const event = JSON.parse(rawBody);
// ... idempotence + persist
}
`
URL exposée : https://kolonell.com/api/webhooks/wave/sn et https://kolonell.com/api/webhooks/wave/ci.
Détection automatique du pays
Dans le checkout, détecter le pays depuis :
- Le numéro saisi (préfixe E.164)
- La géolocalisation IP
- La sélection manuelle utilisateur
`ts
function detectWaveCountry(msisdn: string): WaveCountry | null {
if (msisdn.startsWith('+221')) return 'sn';
if (msisdn.startsWith('+225')) return 'ci';
if (msisdn.startsWith('+223')) return 'ml';
if (msisdn.startsWith('+226')) return 'bf';
if (msisdn.startsWith('+256')) return 'ug';
return null;
}
`
Stratégie multi-comptes Wave
Pour un e-commerce panafricain, deux options :
Option A — Un compte Wave par pays
- Compte Wave SN avec entité légale SN
- Compte Wave CI avec entité légale CI
- Etc.
- Reversement IBAN local par pays
Option B — Un compte Wave dans le pays principal
- Compte SN seul, déclarer le CA international
- Tolérance pour les paiements minoritaires CI/ML
- Reversement central XOF
Option A est plus propre fiscalement mais plus lourde. Option B fonctionne tant que le CA hors-pays principal reste <30 %.
Pièges fréquents
- Confondre les clés API — utiliser clé SN sur endpoint CI = 401. Toujours préfixer avec le pays.
- Plafond journalier — au-delà, transactions rejetées sans message clair côté client. Toujours valider amount avant init.
- Webhook URL multi-pays — préférer route paramétrée
/wave/[country]que des routes séparées. - Reporting fiscal — chaque CA pays = obligation déclarative locale. Compter ces déclarations dans votre process compta.
Cas réel — boutique e-commerce Dakar → Abidjan
Boutique mode SN, ouverture marché CI 2025 :
- 6 mois après lancement CI : 22 % du CA total
- Wave CI = 68 % des paiements CI (vs 52 % SN)
- Différence : Wave CI capte plus jeune que SN où OM est plus enraciné
FAQ
Q : Wave CI accepte les paiements depuis numéros SN ?
R : Non, le payeur doit avoir un compte Wave CI (numéro CI). Pour un client SN qui veut payer en CI, il faudrait un payment SN.
Q : Délai onboarding Wave CI vs SN ?
R : SN : 5-10 jours ouvrés. CI : 7-15 jours ouvrés (KYC plus strict, RCCM CI obligatoire).
Q : Wave US ou Europe ?
R : Pas de présence Wave en dehors de l'Afrique en mai 2026. Stripe reste l'option pour ces marchés.
Conclusion
Wave multi-pays est faisable et rentable pour un e-commerce qui scale au-delà du Sénégal. La complexité technique est gérable avec une bonne abstraction connector. Le vrai challenge est légal/fiscal : multiplier les entités locales coûte du temps administratif. Tester d'abord avec Option B (compte unique), monter en complexité quand le CA pays secondaire dépasse 30 %.
Mohamed Bah
Fondateur, Kolonell
Passionné par le digital et l'entrepreneuriat en Afrique, Mohamed accompagne les entreprises sénégalaises dans leur transformation digitale depuis 2020. Fondateur de Kolonell, il croit que chaque PME mérite une présence en ligne professionnelle et accessible.

