Passer au contenu principal

Documentation Index

Fetch the complete documentation index at: https://docs.oneclickdz.com/llms.txt

Use this file to discover all available pages before exploring further.

Vue d’ensemble

La première étape de l’intégration des recharges mobiles consiste à récupérer la liste des forfaits disponibles depuis l’API. Les forfaits incluent tous les opérateurs (Mobilis, Djezzy, Ooredoo, Pixx) avec des options de montants dynamiques et fixes.
Les forfaits sont stables et changent rarement. Mettez-les en cache dans votre base de données pour réduire les appels API et améliorer les performances.

Référence API

Consultez la documentation API complète pour l’endpoint GET /v3/mobile/plans

Comprendre les types de forfaits

Forfaits dynamiques

Les forfaits dynamiques permettent des montants variables dans une plage min/max :
{
  "code": "PREPAID_DJEZZY",
  "name": "Djezzy Prepaid",
  "operator": "Djezzy",
  "cost": 0.98,
  "isEnabled": true,
  "min_amount": 50,
  "max_amount": 5000
}
Cas d’usage :
  • Recharges prépayées (crédit)
  • Paiements de factures postpayées (facture)
  • Crédit d’appels internationaux

Forfaits fixes

Les forfaits fixes ont des montants prédéterminés :
{
  "code": "PIXX_500",
  "name": "Pixx 500 DA",
  "operator": "Pixx",
  "cost": 0.97,
  "isEnabled": true,
  "amount": 500
}
Cas d’usage :
  • Offres promotionnelles spéciales
  • Packs data
  • Activations de services

Forfaits GetMenu

Forfaits spéciaux qui récupèrent les offres disponibles pour un numéro spécifique :
{
  "code": "GETMENU_Mobilis",
  "name": "Mobilis GetMenu",
  "operator": "Mobilis",
  "cost": 0.98,
  "isEnabled": true,
  "min_amount": 50,
  "max_amount": 5000
}
Retourne : Un tableau de suggested_offers avec tous les forfaits disponibles pour ce numéro spécifique.

Récupérer les forfaits depuis l’API

Requête de base

curl https://api.oneclickdz.com/v3/mobile/plans \
  -H "X-Access-Token: YOUR_API_KEY"

Structure de la réponse

{
  "success": true,
  "data": {
    "dynamicPlans": [
      {
        "code": "PREPAID_MOBILIS",
        "name": "📱 PREPAID | عادي",
        "operator": "Mobilis",
        "cost": 0.96,
        "isEnabled": true,
        "min_amount": 40,
        "max_amount": 3999
      },
      {
        "code": "GROS_MOBILIS",
        "name": "📱 GROS MOBILIS | جملة",
        "operator": "GMobilis",
        "isEnabled": true,
        "min_amount": 5000,
        "max_amount": 300000
      }
    ],
    "fixedPlans": [
      {
        "code": "MIX500_MOBILIS",
        "name": "📱🌐 AUTO | MIX 500",
        "operator": "Mobilis",
        "isEnabled": true,
        "cost": 0.96,
        "amount": 500
      },
      {
        "code": "MIX1000_OOREDOO",
        "name": "📱🌐 AUTO | MIX 1000",
        "operator": "Ooredoo",
        "isEnabled": true,
        "cost": 0.99,
        "amount": 1000
      }
    ]
  },
  "meta": {
    "timestamp": "2025-10-29T00:35:59.220Z"
  }
}

Comprendre le champ Cost

Le champ cost représente votre multiplicateur de prix de gros :
Exemple : cost = 0.98Pour une recharge de 1000 DZD :
  • Valeur nominale : 1000 DZD (ce que l’utilisateur reçoit)
  • Votre coût : 1000 × 0,98 = 980 DZD (ce que vous payez)
  • Votre marge : 1000 - 980 = 20 DZD (2 %)

Mettre les forfaits en cache dans la base de données

Comme les forfaits changent rarement, mettez-les en cache localement avec vos tarifs :

Schéma de base de données

CREATE TABLE mobile_plans (
    id SERIAL PRIMARY KEY,
    code VARCHAR(100) UNIQUE NOT NULL,
    name VARCHAR(255) NOT NULL,
    operator VARCHAR(50) NOT NULL,
    type VARCHAR(20) NOT NULL, -- 'dynamic' or 'fixed'
    
    -- Cost info
    wholesale_cost DECIMAL(5,4) NOT NULL,
    sell_price_multiplier DECIMAL(5,4) NOT NULL,
    
    -- Amount limits
    min_amount INTEGER,
    max_amount INTEGER,
    fixed_amount INTEGER,
    
    -- Status
    is_enabled BOOLEAN DEFAULT true,
    is_visible BOOLEAN DEFAULT true,
    
    -- Metadata
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    last_synced_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_mobile_plans_operator ON mobile_plans(operator);
CREATE INDEX idx_mobile_plans_enabled ON mobile_plans(is_enabled);
CREATE INDEX idx_mobile_plans_code ON mobile_plans(code);

Fonction de synchronisation

const db = require('./database');

async function syncMobilePlans() {
  try {
    console.log('🔄 Syncing mobile plans...');
    
    // Fetch plans from API
    const plans = await fetchMobilePlans();
    
    // Calculate your pricing
    const PROFIT_MARGIN = 0.05; // 5% profit
    
    for (const plan of plans) {
      const isFixed = !!plan.amount;
      
      const planData = {
        code: plan.code,
        name: plan.name,
        operator: plan.operator,
        type: isFixed ? 'fixed' : 'dynamic',
        wholesaleCost: plan.cost,
        sellPriceMultiplier: plan.cost * (1 + PROFIT_MARGIN),
        minAmount: plan.min_amount || null,
        maxAmount: plan.max_amount || null,
        fixedAmount: plan.amount || null,
        isEnabled: plan.isEnabled,
        lastSyncedAt: new Date()
      };
      
      // Upsert (insert or update)
      await db.mobilePlans.upsert({
        where: { code: plan.code },
        update: planData,
        create: planData
      });
    }
    
    console.log(`✅ Successfully synced ${plans.length} plans`);
    
    // Log statistics
    const stats = {
      total: plans.length,
      dynamic: plans.filter(p => !p.amount).length,
      fixed: plans.filter(p => p.amount).length,
      enabled: plans.filter(p => p.isEnabled).length
    };
    
    console.log('📊 Plan statistics:', stats);
    
    return stats;
  } catch (error) {
    console.error('❌ Failed to sync plans:', error);
    throw error;
  }
}

// Run sync on startup
syncMobilePlans();

// Schedule daily sync at midnight
const cron = require('node-cron');
cron.schedule('0 0 * * *', () => {
  console.log('⏰ Running scheduled plan sync...');
  syncMobilePlans();
});

Servir les forfaits aux utilisateurs

Lorsque les utilisateurs demandent des forfaits, servez-les depuis votre base de données avec vos tarifs :
async function getUserPlans(filters = {}) {
  const { operator, type, enabled = true } = filters;
  
  const query = { isEnabled: enabled, isVisible: true };
  
  if (operator) query.operator = operator;
  if (type) query.type = type;
  
  const plans = await db.mobilePlans.findMany({
    where: query,
    orderBy: [
      { operator: 'asc' },
      { fixedAmount: 'asc' },
      { name: 'asc' }
    ]
  });
  
  // Transform for user display (remove wholesale cost!)
  return plans.map(plan => ({
    code: plan.code,
    name: plan.name,
    operator: plan.operator,
    type: plan.type,
    minAmount: plan.minAmount,
    maxAmount: plan.maxAmount,
    amount: plan.fixedAmount,
    // Don't expose wholesale cost!
    // Only expose what user needs
  }));
}

// API endpoint
app.get('/api/mobile/plans', async (req, res) => {
  try {
    const { operator } = req.query;
    const plans = await getUserPlans({ operator });
    res.json({ success: true, data: { plans } });
  } catch (error) {
    res.status(500).json({ 
      success: false, 
      error: error.message 
    });
  }
});

Filtrer les forfaits

Par opérateur

const mobilisPlans = await getUserPlans({ operator: 'Mobilis' });
const djezzyPlans = await getUserPlans({ operator: 'Djezzy' });
const ooredooPlans = await getUserPlans({ operator: 'Ooredoo' });

Par numéro de téléphone

function getOperatorFromPhone(phone) {
  const prefixMap = {
    '065': ['Mobilis'],
    '066': ['Mobilis', 'Ooredoo'],
    '067': ['Mobilis'],
    '077': ['Djezzy', 'Mobilis'],
    '078': ['Djezzy'],
    '055': ['Ooredoo', 'Djezzy', 'Mobilis'],
    '056': ['Ooredoo'],
    '068': ['Pixx']
  };
  
  const prefix = phone.substring(0, 3);
  return prefixMap[prefix] || [];
}

async function getPlansForPhone(phone) {
  const operators = getOperatorFromPhone(phone);
  
  if (operators.length === 0) {
    throw new Error('Invalid phone number prefix');
  }
  
  const plans = await db.mobilePlans.findMany({
    where: {
      operator: { in: operators },
      isEnabled: true,
      isVisible: true
    }
  });
  
  return plans;
}

Bonnes pratiques

Mettez toujours les forfaits en cache dans votre base de données. Les forfaits changent rarement et le cache améliore considérablement les performances.
N’exposez jamais le champ cost aux utilisateurs finaux. N’affichez que vos tarifs de détail.
Mettez en place une tâche cron quotidienne pour synchroniser les forfaits. Cela garantit que vous disposez des dernières offres et disponibilités.
Vérifiez toujours isEnabled avant d’afficher les forfaits. Les forfaits désactivés peuvent être temporairement indisponibles en raison de problèmes avec l’opérateur.
Calculez votre prix de vente en ajoutant une marge bénéficiaire raisonnable (généralement 3 à 10 %) au coût de gros.
Créez des index sur les champs fréquemment interrogés (operator, code, isEnabled) pour des recherches rapides.

Étapes suivantes

Étape 2 : Validation

Apprenez à valider les numéros de téléphone et les saisies utilisateur

Référence API des forfaits

Documentation API complète pour GET /v3/mobile/plans

API de solde du compte

Apprenez à vérifier le solde de votre compte

Guide des tarifs

Comprendre la tarification et la structure des coûts de l’API

Format de réponse

En savoir plus sur les structures de réponse de l’API

Référence des modèles

Voir tous les modèles de données et schémas