20 min de lecture

Guide complet d'intégration des paiements SATIM CIB et Edahabia en Algérie

Guide technique étape par étape couvrant la configuration de l'API SATIM, les flux de paiement par carte CIB et Edahabia, la gestion des erreurs et le déploiement en production pour le e-commerce algérien.

Intégration SATIM
Paiement CIB Algérie
Paiement Edahabia
E-Commerce Algérie
Passerelle de paiement
satim-ts
Paiements Node.js

Le paysage des paiements en Algérie

Si vous construisez une plateforme e-commerce ou toute application acceptant les paiements en ligne en Algérie, vous rencontrerez inévitablement SATIM. La Société d'Automatisation des Transactions Interbancaires et de Monétique (SATIM) est le switch national de paiement électronique qui traite virtuellement toutes les transactions par carte en Algérie. Elle se situe entre les marchands, les banques et les réseaux de cartes, agissant comme la couche centrale de routage et de règlement.

Deux types de cartes dominent le marché algérien :

  • CIB (Carte Interbancaire) : la carte de crédit/débit interbancaire standard émise par les banques algériennes. Les cartes CIB portent le logo du réseau CIB et sont acceptées aux terminaux de point de vente et chez les marchands en ligne dans tout le pays.
  • Edahabia : la carte de débit d'Algérie Poste, liée aux comptes CCP (Compte Courant Postal). Avec plus de 20 millions de comptes CCP en Algérie, Edahabia représente la plus grande base potentielle de paiement du pays.

Les deux types de cartes sont traités via la passerelle de paiement SATIM (parfois appelée SATIM e-payment ou SATIM IPAY). D'un point de vue technique, le flux d'intégration est quasiment identique pour les deux. La passerelle détecte automatiquement le type de carte en fonction du numéro entré par le client.

Prérequis

Avant d'écrire la moindre ligne de code, vous avez besoin des éléments suivants :

  1. Un compte marchand auprès d'une banque supportant le e-paiement SATIM (la plupart des grandes banques algériennes le font : BNA, CPA, BEA, BADR, Gulf Bank Algeria, entre autres).
  2. Un Terminal ID (format : E010XXXXXX), fourni via le portail SATIM pour identifier votre terminal marchand.
  3. Un nom d'utilisateur et un mot de passe pour l'API de la passerelle SATIM, fournis via le portail SATIM après approbation de votre compte marchand.
  4. Des identifiants de test pour l'environnement sandbox à test2.satim.dz, également fournis via le portail SATIM.

Le processus d'onboarding est géré via le portail SATIM à cibweb.dz. Suivez les instructions pour soumettre vos documents et recevoir vos identifiants. Les délais varient, commencez donc ce processus tôt. Si vous avez besoin d'aide pour naviguer la certification, nous proposons un accompagnement certification SATIM.

Comment fonctionne le flux de paiement

SATIM utilise un flux de paiement basé sur la redirection, conceptuellement similaire à 3D Secure ou Stripe Checkout. Votre serveur ne manipule jamais les données brutes de carte. Voici la séquence complète :

  1. Enregistrement de la commande : votre backend appelle l'endpoint register.do de SATIM avec le montant de la commande, un numéro de commande unique et les URLs de callback. SATIM répond avec un orderId et une formUrl.
  2. Redirection du client : vous redirigez le navigateur du client vers la formUrl. SATIM héberge la page de paiement où le client entre les détails de sa carte CIB ou Edahabia.
  3. Traitement du paiement : SATIM traite la transaction avec la banque émettrice. Le client peut voir un écran de vérification OTP/mot de passe (similaire à 3DS).
  4. Redirection callback : après le paiement (succès ou échec), SATIM redirige le client vers votre returnUrl ou failUrl avec l'orderId comme paramètre de requête.
  5. Confirmation côté serveur : votre backend appelle l'endpoint acknowledgeTransaction.do pour vérifier le statut de la transaction. C'est l'étape critique ; ne faites jamais confiance à la redirection côté client seule.
Client           Votre serveur       Passerelle SATIM      Banque
   |                  |                    |                  |
   |  Passer commande |                    |                  |
   |----------------->|                    |                  |
   |                  |  register.do       |                  |
   |                  |------------------->|                  |
   |                  |  orderId + formUrl |                  |
   |                  |<-------------------|                  |
   |  Redirection     |                    |                  |
   |  vers formUrl    |                    |                  |
   |<-----------------|                    |                  |
   |  Saisie carte    |                    |                  |
   |---------------------------------------->|                |
   |                  |                    |  Traiter paiement|
   |                  |                    |----------------->|
   |                  |                    |  Réponse auth    |
   |                  |                    |<-----------------|
   |  Redirection     |                    |                  |
   |  vers returnUrl  |                    |                  |
   |<-----------------------------------------|              |
   |  Page chargée    |                    |                  |
   |----------------->|                    |                  |
   |                  | acknowledgeTransaction.do             |
   |                  |------------------->|                  |
   |                  | Statut paiement    |                  |
   |                  |<-------------------|                  |
   |  Commande        |                    |                  |
   |  confirmée       |                    |                  |
   |<-----------------|                    |                  |

Configuration avec satim-ts

Le package @bakissation/satim est un SDK TypeScript de qualité production qui encapsule l'API SATIM avec des types stricts, la validation des entrées, la conversion automatique des montants et une gestion d'erreurs complète.

Installation

1npm install @bakissation/satim

Le SDK supporte ESM et CommonJS, nécessite Node.js 18 ou supérieur, et n'a aucune dépendance externe (il utilise l'API native fetch).

Configuration

L'approche la plus simple passe par les variables d'environnement. Créez un fichier .env :

1SATIM_USERNAME=your_merchant_username 2SATIM_PASSWORD=your_merchant_password 3SATIM_TERMINAL_ID=E010XXXXXX 4SATIM_API_URL=https://test2.satim.dz/payment/rest

Puis initialisez le client :

1import { createSatimClient, fromEnv } from '@bakissation/satim'; 2 3const satim = createSatimClient(fromEnv());

Pour un contrôle plus explicite, passez la configuration directement :

1import { createSatimClient, API_BASE_URLS } from '@bakissation/satim'; 2 3const satim = createSatimClient({ 4 userName: process.env.SATIM_USERNAME!, 5 password: process.env.SATIM_PASSWORD!, 6 terminalId: process.env.SATIM_TERMINAL_ID!, 7 apiBaseUrl: API_BASE_URLS.TEST, // basculer vers API_BASE_URLS.PRODUCTION pour le live 8 language: 'fr', 9 currency: '012', // DZD (ISO 4217) 10});

Implémenter le flux de paiement

Étape 1 : enregistrer la commande

Quand votre client est prêt à payer, créez une commande sur votre backend :

1import { createSatimClient, fromEnv } from '@bakissation/satim'; 2import { randomUUID } from 'crypto'; 3 4const satim = createSatimClient(fromEnv()); 5 6async function createPayment(orderNumber: string, amountDzd: number) { 7 const response = await satim.register({ 8 orderNumber, // Max 10 caractères, doit être unique par transaction 9 amount: amountDzd, // En DZD (minimum 50 DZD), converti automatiquement en unités mineures 10 returnUrl: 'https://yoursite.com/payment/callback', 11 failUrl: 'https://yoursite.com/payment/failed', 12 description: 'Purchase from YourStore', 13 udf1: orderNumber, // Requis : votre référence interne 14 idempotencyKey: randomUUID(), // Empêche les commandes en double lors des retry 15 }); 16 17 if (response.isSuccessful()) { 18 // Sauvegardez response.orderId dans votre base de données, lié à la commande 19 return { 20 orderId: response.orderId, 21 redirectUrl: response.formUrl, 22 }; 23 } 24 25 throw new Error('Failed to register order with SATIM'); 26}

Points clés concernant l'appel register :

  • Gestion des montants : passez les montants en DZD sous forme de nombres entiers ou décimaux (ex. 5000 pour 5 000 DZD, ou 806.5 pour 806,50 DZD). Le SDK convertit automatiquement en unités mineures (centimes) comme requis par l'API.
  • Numéro de commande : maximum 10 caractères. Doit être unique par transaction. Si vous réutilisez un numéro de commande, SATIM retournera le code d'erreur 1.
  • udf1 : requis par SATIM. Utilisez-le pour votre référence interne (numéro de facture, ID de commande, etc.).
  • Idempotence : passez toujours un idempotencyKey en production pour éviter les doubles prélèvements si votre requête est relancée suite à des problèmes réseau.

Étape 2 : rediriger le client

Côté frontend, redirigez le client vers la formUrl retournée par l'appel register :

1// Dans votre gestionnaire de réponse API (frontend) 2window.location.href = redirectUrl;

Ou si vous construisez un backend API-first, retournez l'URL à votre frontend/client mobile et laissez-le gérer la redirection. La page de paiement SATIM supporte le français, l'anglais et l'arabe, configurable via le paramètre language.

Étape 3 : gérer le callback

Après que le client a complété (ou abandonné) le paiement, SATIM le redirige vers votre returnUrl ou failUrl avec un paramètre de requête orderId. Sur votre endpoint de callback, vérifiez le paiement côté serveur :

1import { OrderStatus, interpretOrderStatus } from '@bakissation/satim'; 2 3async function handlePaymentCallback(orderId: string) { 4 const status = await satim.confirm(orderId); 5 6 if (status.isPaid()) { 7 // Paiement réussi, orderStatus === 2 (DEPOSITED) 8 console.log('Payment confirmed for order:', status.orderNumber); 9 console.log('Amount:', status.amount); 10 console.log('Card (masked):', status.pan); // ex. 6280****7215 11 12 // Mettez à jour le statut de votre commande en base de données 13 // Livrez le produit/service 14 return { success: true, orderNumber: status.orderNumber }; 15 } 16 17 // Paiement non réussi 18 console.log('Payment status:', interpretOrderStatus(status.orderStatus)); 19 console.log('Details:', status.actionCodeDescription); 20 return { success: false, reason: status.actionCodeDescription }; 21}

La méthode confirm (alias getOrderStatus) appelle l'endpoint acknowledgeTransaction.do de SATIM. C'est le seul moyen fiable de savoir si un paiement a réussi. Ne vous fiez jamais uniquement à l'URL de redirection sur laquelle le client atterrit, car elle peut être falsifiée ou manipulée.

Étape 4 : remboursements (si nécessaire)

Pour rembourser une transaction complétée :

1async function refundPayment(orderId: string, amountDzd: number) { 2 const result = await satim.refund(orderId, amountDzd); 3 4 if (result.isSuccessful()) { 5 console.log('Refund processed successfully'); 6 return true; 7 } 8 9 console.error('Refund failed:', result.errorMessage); 10 return false; 11}

Les remboursements doivent référencer l'orderId original retourné lors de l'enregistrement. Les remboursements partiels sont supportés en passant un montant inférieur à celui de la transaction originale.

CIB vs Edahabia : ce que les développeurs doivent savoir

Du point de vue de l'intégration API, les paiements CIB et Edahabia sont gérés de manière identique par la passerelle SATIM. Vous n'avez pas besoin de spécifier le type de carte lors de l'enregistrement d'une commande. La passerelle détermine le type de carte à partir du numéro entré par le client sur la page de paiement.

Il y a quelques différences pratiques à connaître :

  • Format du numéro de carte : les cartes CIB commencent typiquement par 6280 (16 chiffres). Les cartes Edahabia suivent le schéma de numérotation d'Algérie Poste. Les deux sont traitées via les mêmes endpoints register.do et acknowledgeTransaction.do.
  • Limites de transaction : les cartes Edahabia peuvent avoir des limites de transaction quotidiennes inférieures à celles des cartes CIB, selon la configuration du titulaire auprès d'Algérie Poste. Votre application devrait gérer gracieusement les refus "limite dépassée".
  • Délais de règlement : le règlement sur votre compte marchand peut différer légèrement entre les transactions CIB et Edahabia, selon l'arrangement de votre banque acquéreuse. C'est une question d'opérations bancaires, pas de code.
  • Vérification OTP : les deux types de cartes peuvent nécessiter la saisie d'un OTP ou mot de passe sur la page de paiement SATIM. Le champ password sur les cartes de test est utilisé à cet effet dans le sandbox.

Si vous avez spécifiquement besoin de gérer des paiements de factures ou un type de transaction particulier, vous pouvez utiliser le paramètre fundingTypeIndicator (ex. 'CP' ou '698'), mais pour les achats e-commerce standard, ce n'est pas nécessaire.

Gestion des erreurs

Le SDK fournit des classes d'erreur typées pour chaque scénario d'échec. Une gestion robuste des erreurs est particulièrement importante pour les intégrations de paiement où les échecs silencieux peuvent entraîner des pertes de revenus ou des doubles prélèvements.

1import { 2 SatimApiError, 3 ValidationError, 4 HttpError, 5 TimeoutError, 6 ConfigError, 7 mapSatimErrorCode, 8} from '@bakissation/satim'; 9 10async function safePayment(orderNumber: string, amount: number) { 11 try { 12 const response = await satim.register({ 13 orderNumber, 14 amount, 15 returnUrl: 'https://yoursite.com/payment/callback', 16 udf1: orderNumber, 17 idempotencyKey: crypto.randomUUID(), 18 }); 19 return response; 20 } catch (error) { 21 if (error instanceof ValidationError) { 22 // Entrée invalide : montant incorrect, champs manquants, etc. 23 console.error(`Validation error [${error.code}]:`, error.message); 24 } else if (error instanceof SatimApiError) { 25 // SATIM a rejeté la requête 26 console.error(`SATIM error [${error.satimErrorCode}]:`, error.message); 27 } else if (error instanceof TimeoutError) { 28 // Timeout de la requête, sans risque de réessayer avec la même clé d'idempotence 29 console.error(`Timeout after ${error.timeoutMs}ms`); 30 } else if (error instanceof HttpError) { 31 // Échec réseau ou HTTP 32 console.error(`HTTP error [${error.httpStatus}]:`, error.message); 33 } else if (error instanceof ConfigError) { 34 // Configuration manquante ou invalide 35 console.error('Config error, missing keys:', error.missingKeys); 36 } 37 throw error; 38 } 39}

Référence des codes d'erreur SATIM

Voici les codes d'erreur retournés par l'API SATIM à travers ses endpoints :

Coderegister.doacknowledgeTransaction.dorefund.do
0SuccèsSuccèsSuccès
1Commande déjà traitée--
2-Erreur d'identifiants de paiement-
3Devise inconnue--
4Paramètre requis manquant--
5Paramètre invalideAccès refuséAccès refusé / Montant invalide
6-Commande non enregistréeCommande non enregistrée
7Erreur systèmeErreur systèmeErreur système
14Mode de paiement invalide--

Codes de statut de commande

Après avoir appelé confirm() ou getOrderStatus(), vérifiez le champ orderStatus :

CodeSignificationAction
0Enregistrée mais non payéeLe client a abandonné ou n'a pas encore complété le paiement
-1Refus inconnuContactez le support SATIM si le problème persiste
1Approuvée (pré-autorisation retenue)En attente de dépôt
2Déposée (paiement complété)Exécutez la commande
3Autorisation annuléeLe paiement a été annulé avant le règlement
4RembourséeLa transaction a été remboursée
6RefuséeLa carte a été refusée par la banque émettrice

Tests avec le sandbox SATIM

SATIM fournit un environnement sandbox à https://test2.satim.dz/payment/rest pour les tests d'intégration. Utilisez les cartes de test suivantes :

Numéro de carteCVV2ExpirationMot de passeScénario
628058111000721537301/2027123456Paiement réussi
628058111000671289701/2027123456Carte temporairement bloquée
628058061006111026001/2027123456Solde insuffisant
628058061006121904901/2027123456Limite dépassée
628058111000651420501/2027123456CVV2 incorrect
628058061006101199201/2027123456Carte de crédit valide

Lors des tests :

  1. Configurez votre SATIM_API_URL à https://test2.satim.dz/payment/rest.
  2. Utilisez les identifiants de test fournis par votre banque (pas vos identifiants de production).
  3. Testez chaque scénario : paiement réussi, carte refusée, solde insuffisant, gestion du timeout et prévention des commandes en double.
  4. Vérifiez que votre appel confirm() interprète correctement chaque statut de commande.
  5. Testez le parcours utilisateur complet, y compris ce qui se passe quand le client ferme le navigateur sur la page de paiement SATIM sans compléter la transaction.

Checklist de déploiement en production

Avant de passer en production, parcourez cette checklist :

Configuration

  • Basculer SATIM_API_URL vers https://satim.dz/payment/rest
  • Utiliser les identifiants de production (nom d'utilisateur, mot de passe, terminal ID) de votre banque
  • Stocker tous les identifiants dans des variables d'environnement, jamais dans le code source
  • Vérifier que les fichiers .env sont dans .gitignore
  • Configurer NODE_ENV=production pour désactiver le logging verbeux de développement

Sécurité

  • Utiliser la méthode POST pour tous les appels API SATIM (le SDK le fait par défaut)
  • Toujours vérifier le statut du paiement côté serveur via confirm(), ne jamais faire confiance aux redirections côté client
  • Servir vos URLs de callback uniquement en HTTPS
  • Implémenter des clés d'idempotence sur chaque appel register() pour prévenir les doubles prélèvements
  • Ne jamais logger ou stocker les numéros de carte complets (le SDK ne les expose jamais)

Fiabilité

  • Gérer tous les types d'erreur (SatimApiError, TimeoutError, HttpError, ValidationError)
  • Implémenter une logique de retry pour les scénarios TimeoutError (en utilisant la même clé d'idempotence)
  • Mettre en place du monitoring/alerting pour les paiements échoués
  • Logger les résultats de transaction (en utilisant le logger intégré du SDK ou le vôtre via l'option customLogger)
  • Stocker le orderId SATIM dans votre base de données pour chaque transaction, permettant les vérifications de statut et remboursements futurs

Tests

  • Exécuter des tests end-to-end contre le sandbox avant de basculer en production
  • Tester avec tous les scénarios de cartes sandbox (succès, refus, fonds insuffisants, carte bloquée)
  • Vérifier que le flux de remboursement fonctionne correctement
  • Tester ce qui se passe quand SATIM est injoignable (gestion du timeout)

Conformité

  • Vérifier auprès de votre banque que votre intégration est approuvée pour l'usage en production
  • Vérifier que vos conditions générales d'utilisation et votre politique de confidentialité couvrent les paiements électroniques
  • Conserver les enregistrements de toutes les transactions comme requis par la réglementation commerciale algérienne

Avancé : intégration avec Fastify

Si vous utilisez Fastify comme framework web, le plugin @bakissation/fastify-satim fournit une intégration simplifiée qui enregistre le client SATIM comme décorateur Fastify :

1npm install @bakissation/fastify-satim
1import Fastify from 'fastify'; 2import satimPlugin from '@bakissation/fastify-satim'; 3 4const app = Fastify(); 5 6app.register(satimPlugin, { 7 userName: process.env.SATIM_USERNAME!, 8 password: process.env.SATIM_PASSWORD!, 9 terminalId: process.env.SATIM_TERMINAL_ID!, 10 apiBaseUrl: 'https://satim.dz/payment/rest', 11}); 12 13app.post('/pay', async (request, reply) => { 14 const { orderNumber, amount } = request.body as any; 15 16 const result = await app.satim.register({ 17 orderNumber, 18 amount, 19 returnUrl: 'https://yoursite.com/payment/callback', 20 udf1: orderNumber, 21 }); 22 23 if (result.isSuccessful()) { 24 return reply.redirect(result.formUrl!); 25 } 26 27 return reply.status(500).send({ error: 'Payment registration failed' }); 28});

Cela évite l'instanciation manuelle du client et garantit que le cycle de vie du client SATIM est géré par Fastify.

Besoin d'aide pour votre intégration ?

L'intégration de paiements est un travail à enjeux élevés où les bugs se traduisent directement en perte de revenus ou en problèmes de conformité. Si vous avez besoin d'aide experte pour votre intégration SATIM CIB/Edahabia, de la configuration initiale et la coordination bancaire au déploiement en production et au support continu, je propose du consulting dédié pour les systèmes de paiement algériens.

Contactez-moi pour du consulting intégration SATIM

© 2026 Abdelbaki Berkati. Tous droits réservés.