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

L’endpoint des produits retourne les cartes de recharge internet disponibles pour les services ADSL ou 4G LTE avec les tarifs en temps réel et la disponibilité du stock. Les produits doivent être mis en cache brièvement pour minimiser les appels API.
Mettez en cache les données de produit pendant 5-10 minutes. Les niveaux de stock changent plus fréquemment que pour les cartes-cadeaux.

Référence API

GET /v3/internet/products

Documentation complète de l’endpoint

Chargement de base des produits

async function loadInternetProducts(type) {
  if (!['ADSL', '4G'].includes(type)) {
    throw new Error('Invalid type. Must be ADSL or 4G');
  }

  const response = await fetch(
    `https://api.oneclickdz.com/v3/internet/products?type=${type}`,
    {
      headers: {
        "X-Access-Token": process.env.API_KEY,
      },
    }
  );

  if (!response.ok) {
    throw new Error(`Failed to load products: ${response.status}`);
  }

  const result = await response.json();
  return result.data.products;
}

// Usage
const adslProducts = await loadInternetProducts('ADSL');
const lteProducts = await loadInternetProducts('4G');

console.log(`ADSL: ${adslProducts.length} products`);
console.log(`4G: ${lteProducts.length} products`);

Structure de la réponse

{
  "success": true,
  "data": {
    "products": [
      {
        "value": 500,
        "cost": 490,
        "available": true
      },
      {
        "value": 1000,
        "cost": 980,
        "available": true
      },
      {
        "value": 2000,
        "cost": 1960,
        "available": true
      },
      {
        "value": 5000,
        "cost": 4900,
        "available": false
      }
    ]
  },
  "meta": {
    "timestamp": "2025-11-01T12:00:00.000Z",
    "type": "ADSL"
  }
}

Implémentation du cache

class ProductCache {
  constructor(ttlMinutes = 10) {
    this.cache = new Map();
    this.ttl = ttlMinutes * 60 * 1000;
  }

  async get(type) {
    const cached = this.cache.get(type);
    const now = Date.now();
    
    // Return cached if still valid
    if (cached && (now - cached.timestamp) < this.ttl) {
      console.log(`Returning cached ${type} products`);
      return cached.data;
    }

    // Fetch fresh data
    console.log(`Fetching fresh ${type} products`);
    const products = await loadInternetProducts(type);
    
    this.cache.set(type, {
      data: products,
      timestamp: now,
    });
    
    return products;
  }

  invalidate(type) {
    if (type) {
      this.cache.delete(type);
    } else {
      this.cache.clear();
    }
  }
}

// Usage
const cache = new ProductCache(10); // TTL 10 minutes

// First call - fetches from API
const adsl1 = await cache.get('ADSL');

// Second call within 10 minutes - returns cached
const adsl2 = await cache.get('ADSL');

// Type différent - récupère séparément
const lte = await cache.get('4G');

// Force refresh
cache.invalidate('ADSL');
const adsl3 = await cache.get('ADSL'); // Récupère de nouvelles données

Filtrage des produits disponibles

N’afficher que les produits en stock :
function getAvailableProducts(products) {
  return products.filter(p => p.available);
}

// Usage
const allProducts = await cache.get('ADSL');
const available = getAvailableProducts(allProducts);

console.log(`${available.length}/${allProducts.length} products in stock`);

if (available.length === 0) {
  console.log('No products available at the moment');
}

Application de la marge client

Ajoutez votre marge bénéficiaire aux prix de gros :
function applyMarkup(products, markupPercent = 5) {
  return products
    .filter(p => p.available)
    .map(p => ({
      value: p.value,
      wholesaleCost: p.cost, // Store but don't show
      customerPrice: Math.ceil(p.cost * (1 + markupPercent / 100)),
      available: true,
    }));
}

// Usage
const products = await cache.get('ADSL');
const customerPrices = applyMarkup(products, 5); // 5% markup

customerPrices.forEach(p => {
  console.log(`${p.value} DA card: ${p.customerPrice} DA`);
  // Ne pas journaliser wholesaleCost en production !
});

Construction de l’Interface Produit

Exemple de structure pour afficher les produits aux clients :
async function buildProductOptions(type, markupPercent = 5) {
  const products = await cache.get(type);
  
  return {
    serviceType: type,
    serviceName: type === 'ADSL' ? 'Internet ADSL' : 'Internet 4G LTE',
    options: products
      .filter(p => p.available)
      .map(p => ({
        value: p.value,
        label: `${p.value} DA`,
        price: Math.ceil(p.cost * (1 + markupPercent / 100)),
        inStock: true,
      }))
      .sort((a, b) => a.value - b.value) // Trier par valeur croissante
  };
}

// Utilisation
const adslOptions = await buildProductOptions('ADSL', 5);
const lteOptions = await buildProductOptions('4G', 5);

// Retourne une structure prête pour l'interface :
// {
//   serviceType: 'ADSL',
//   serviceName: 'Internet ADSL',
//   options: [
//     { value: 500, label: '500 DA', price: 515, inStock: true },
//     { value: 1000, label: '1000 DA', price: 1029, inStock: true },
//     ...
//   ]
// }

Chargement des deux types de service

Récupérez les produits ADSL et 4G en parallèle :
async function loadAllInternetProducts() {
  const [adsl, lte] = await Promise.all([
    cache.get('ADSL'),
    cache.get('4G'),
  ]);
  
  return {
    adsl: applyMarkup(adsl, 5),
    lte: applyMarkup(lte, 5),
  };
}

// Usage
const allProducts = await loadAllInternetProducts();
console.log('ADSL:', allProducts.adsl.length, 'products');
console.log('4G:', allProducts.lte.length, 'products');

Bonnes pratiques

Cache 5-10 minutes

Équilibre entre fraîcheur et réduction de la charge API

Filtrer les disponibles uniquement

N’afficher que les produits où available: true

Masquer les prix de gros

Ne jamais afficher les valeurs brutes de cost aux clients

Gérer les erreurs gracieusement

Revenir aux données en cache si l’API est temporairement indisponible

Étapes suivantes

Valider les numéros

Vérifier les numéros de téléphone avant la commande

Envoyer les recharges

Soumettre des commandes avec gestion des erreurs

Référence API

Documentation complète de l’endpoint

Vue d'ensemble

Retour à la vue d’ensemble de l’intégration

Suivre le statut

Surveiller l’exécution des commandes

Livrer les cartes

Livrer les codes de carte en toute sécurité