> ## 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.

# Envoi de Recharges Internet

> Soumettre des commandes de recharge internet ADSL et 4G avec gestion des erreurs

## Vue d'ensemble

Envoyez des commandes de recharge internet après avoir validé les numéros de téléphone et vérifié la disponibilité des produits. Les commandes sont traitées avec l'opérateur et se complètent généralement en 3-45 secondes.

<Warning>
  **Validez toujours les numéros en premier** avec `/check-number` pour minimiser les échecs et les remboursements.
</Warning>

## Référence API

<Card title="POST /v3/internet/send" icon="paper-plane" href="/fr/api-reference/internet/send-topup">
  Documentation complète de l'endpoint
</Card>

## Soumission de base d'une commande

<CodeGroup>
  ```javascript Node.js theme={null}
  async function sendInternetTopup(orderData) {
    const response = await fetch(
      "https://api.oneclickdz.com/v3/internet/send",
      {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "X-Access-Token": process.env.API_KEY,
        },
        body: JSON.stringify({
          type: orderData.type,      // 'ADSL' or '4G'
          number: orderData.number,   // Phone number
          value: orderData.value,     // Card value
          ref: orderData.ref,         // Your unique reference
        }),
      }
    );

    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.error?.message || `HTTP ${response.status}`);
    }

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

  // Usage
  const order = await sendInternetTopup({
    type: 'ADSL',
    number: '036362608',
    value: 1000,
    ref: `order-${Date.now()}`
  });

  console.log('Top-up sent:', order.topupId);
  ```

  ```python Python theme={null}
  import requests
  import os
  import time

  def send_internet_topup(order_data):
      response = requests.post(
          'https://api.oneclickdz.com/v3/internet/send',
          headers={
              'Content-Type': 'application/json',
              'X-Access-Token': os.getenv('API_KEY')
          },
          json={
              'type': order_data['type'],
              'number': order_data['number'],
              'value': order_data['value'],
              'ref': order_data['ref']
          }
      )
      
      if not response.ok:
          error = response.json()
          raise Exception(error.get('error', {}).get('message', f'HTTP {response.status_code}'))
      
      return response.json()['data']

  # Usage
  order = send_internet_topup({
      'type': 'ADSL',
      'number': '036362608',
      'value': 1000,
      'ref': f'order-{int(time.time() * 1000)}'
  })

  print(f'Top-up sent: {order["topupId"]}')
  ```

  ```php PHP theme={null}
  <?php

  function sendInternetTopup($orderData) {
      $data = [
          'type' => $orderData['type'],
          'number' => $orderData['number'],
          'value' => $orderData['value'],
          'ref' => $orderData['ref']
      ];
      
      $ch = curl_init('https://api.oneclickdz.com/v3/internet/send');
      curl_setopt($ch, CURLOPT_POST, true);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
      curl_setopt($ch, CURLOPT_HTTPHEADER, [
          'Content-Type: application/json',
          'X-Access-Token: ' . getenv('API_KEY')
      ]);
      curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
      
      $response = curl_exec($ch);
      $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
      curl_close($ch);
      
      if ($httpCode >= 400) {
          $error = json_decode($response, true);
          throw new Exception($error['error']['message'] ?? "HTTP {$httpCode}");
      }
      
      $result = json_decode($response, true);
      return $result['data'];
  }

  // Usage
  $order = sendInternetTopup([
      'type' => 'ADSL',
      'number' => '036362608',
      'value' => 1000,
      'ref' => 'order-' . (int)(microtime(true) * 1000)
  ]);

  echo "Top-up sent: {$order['topupId']}\n";
  ?>
  ```

  ```bash cURL theme={null}
  curl https://api.oneclickdz.com/v3/internet/send \
    -X POST \
    -H "Content-Type: application/json" \
    -H "X-Access-Token: YOUR_API_KEY" \
    -d '{
      "type": "ADSL",
      "number": "036362608",
      "value": 1000,
      "ref": "order-123456"
    }'
  ```
</CodeGroup>

## Réponse en cas de succès

```json theme={null}
{
  "success": true,
  "data": {
    "topupId": "6901616fe9e88196b4eb64b2",
    "topupRef": "order-123456"
  },
  "meta": {
    "timestamp": "2025-11-01T12:00:00.000Z"
  }
}
```

## Validation avant commande

Validez toujours avant d'envoyer des commandes :

<CodeGroup>
  ```javascript Node.js theme={null}
  async function validateAndSend(orderData) {
    // Étape 1 : Valider le numéro de téléphone
    try {
      await validateInternetNumber(orderData.type, orderData.number);
    } catch (error) {
      throw new Error(`Invalid phone number: ${error.message}`);
    }

    // Step 2: Check product availability
    const products = await loadInternetProducts(orderData.type);
    const product = products.find(
      p => p.value === orderData.value && p.available
    );
    
    if (!product) {
      throw new Error(`Product ${orderData.value} DA not available for ${orderData.type}`);
    }

    // Step 3: Check balance
    const balance = await getBalance();
    if (balance < product.cost) {
      throw new Error(
        `Insufficient balance. Required: ${product.cost} DA, Available: ${balance} DA`
      );
    }

    // Étape 4 : Envoyer la commande
    console.log(`Sending ${orderData.type} ${orderData.value} DA to ${orderData.number}`);
    const result = await sendInternetTopup(orderData);
    
    return {
      topupId: result.topupId,
      topupRef: result.topupRef,
      cost: product.cost,
      type: orderData.type,
      number: orderData.number,
      value: orderData.value
    };
  }

  async function getBalance() {
    const response = await fetch(
      "https://api.oneclickdz.com/v3/account/balance",
      {
        headers: { "X-Access-Token": process.env.API_KEY },
      }
    );
    const result = await response.json();
    return result.data.balance;
  }

  // Usage
  try {
    const result = await validateAndSend({
      type: 'ADSL',
      number: '036362608',
      value: 1000,
      ref: `order-${Date.now()}`
    });
    
    console.log('✅ Order placed successfully');
    console.log(`  Top-up ID: ${result.topupId}`);
    console.log(`  Cost: ${result.cost} DA`);
  } catch (error) {
    console.error('❌ Order failed:', error.message);
  }
  ```

  ```python Python theme={null}
  def validate_and_send(order_data):
      # Étape 1 : Valider le numéro de téléphone
      try:
          validate_internet_number(order_data['type'], order_data['number'])
      except Exception as e:
          raise ValueError(f"Invalid phone number: {e}")
      
      # Step 2: Check product availability
      products = load_internet_products(order_data['type'])
      product = next(
          (p for p in products if p['value'] == order_data['value'] and p['available']),
          None
      )
      
      if not product:
          raise ValueError(
              f"Product {order_data['value']} DA not available for {order_data['type']}"
          )
      
      # Step 3: Check balance
      balance = get_balance()
      if balance < product['cost']:
          raise ValueError(
              f"Insufficient balance. Required: {product['cost']} DA, Available: {balance} DA"
          )
      
      # Étape 4 : Envoyer la commande
      print(f"Sending {order_data['type']} {order_data['value']} DA to {order_data['number']}")
      result = send_internet_topup(order_data)
      
      return {
          'topupId': result['topupId'],
          'topupRef': result['topupRef'],
          'cost': product['cost'],
          'type': order_data['type'],
          'number': order_data['number'],
          'value': order_data['value']
      }

  def get_balance():
      response = requests.get(
          'https://api.oneclickdz.com/v3/account/balance',
          headers={'X-Access-Token': os.getenv('API_KEY')}
      )
      response.raise_for_status()
      return response.json()['data']['balance']

  # Usage
  try:
      result = validate_and_send({
          'type': 'ADSL',
          'number': '036362608',
          'value': 1000,
          'ref': f'order-{int(time.time() * 1000)}'
      })
      
      print('✅ Order placed successfully')
      print(f"  Top-up ID: {result['topupId']}")
      print(f"  Cost: {result['cost']} DA")
  except ValueError as e:
      print(f'❌ Order failed: {e}')
  ```

  ```php PHP theme={null}
  <?php

  function validateAndSend($orderData) {
      // Étape 1 : Valider le numéro de téléphone
      try {
          validateInternetNumber($orderData['type'], $orderData['number']);
      } catch (Exception $e) {
          throw new Exception("Invalid phone number: " . $e->getMessage());
      }
      
      // Step 2: Check product availability
      $products = loadInternetProducts($orderData['type']);
      $product = null;
      foreach ($products as $p) {
          if ($p['value'] === $orderData['value'] && $p['available']) {
              $product = $p;
              break;
          }
      }
      
      if ($product === null) {
          throw new Exception(
              "Product {$orderData['value']} DA not available for {$orderData['type']}"
          );
      }
      
      // Step 3: Check balance
      $balance = getBalance();
      if ($balance < $product['cost']) {
          throw new Exception(
              "Insufficient balance. Required: {$product['cost']} DA, Available: {$balance} DA"
          );
      }
      
      // Étape 4 : Envoyer la commande
      error_log("Sending {$orderData['type']} {$orderData['value']} DA to {$orderData['number']}");
      $result = sendInternetTopup($orderData);
      
      return [
          'topupId' => $result['topupId'],
          'topupRef' => $result['topupRef'],
          'cost' => $product['cost'],
          'type' => $orderData['type'],
          'number' => $orderData['number'],
          'value' => $orderData['value']
      ];
  }

  function getBalance() {
      $ch = curl_init('https://api.oneclickdz.com/v3/account/balance');
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
      curl_setopt($ch, CURLOPT_HTTPHEADER, [
          'X-Access-Token: ' . getenv('API_KEY')
      ]);
      $response = curl_exec($ch);
      curl_close($ch);
      
      $result = json_decode($response, true);
      return $result['data']['balance'];
  }

  // Usage
  try {
      $result = validateAndSend([
          'type' => 'ADSL',
          'number' => '036362608',
          'value' => 1000,
          'ref' => 'order-' . (int)(microtime(true) * 1000)
      ]);
      
      echo "✅ Order placed successfully\n";
      echo "  Top-up ID: {$result['topupId']}\n";
      echo "  Cost: {$result['cost']} DA\n";
  } catch (Exception $e) {
      echo "❌ Order failed: " . $e->getMessage() . "\n";
  }
  ?>
  ```
</CodeGroup>

## Suivi des Transactions

Stockez les détails de la commande dans votre base de données :

```javascript theme={null}
async function createOrderTransaction(userId, orderDetails) {
  const transaction = {
    userId,
    topupId: orderDetails.topupId,
    ref: orderDetails.topupRef,
    type: orderDetails.type,
    number: orderDetails.number,
    value: orderDetails.value,
    cost: orderDetails.cost,
    status: 'HANDLING',
    createdAt: new Date(),
    updatedAt: new Date()
  };
  
  await db.internetOrders.insertOne(transaction);
  
  console.log('Transaction enregistrée :', transaction.topupId);
  return transaction;
}

// Utilisation
const orderResult = await validateAndSend(orderData);
await createOrderTransaction(userId, orderResult);
```

## Génération de Références Uniques

Assurez-vous que chaque commande possède une référence unique :

```javascript theme={null}
function generateOrderReference(userId, type) {
  const timestamp = Date.now();
  const random = Math.random().toString(36).substring(2, 8);
  return `${type.toLowerCase()}-${userId}-${timestamp}-${random}`;
}

// Utilisation
const ref = generateOrderReference(123, 'ADSL');
// Exemple : 'adsl-123-1730448000000-x7k2m9'
```

## Gestion des erreurs

<CodeGroup>
  ```javascript Node.js theme={null}
  async function sendTopupSafely(orderData) {
    try {
      const result = await sendInternetTopup(orderData);
      return { success: true, data: result };
    } catch (error) {
      console.error('Order failed:', error);
      
      const message = error.message.toLowerCase();
      
      if (message.includes('err_phone')) {
        return {
          success: false,
          error: 'INVALID_PHONE',
          message: 'Invalid phone number for this service type'
        };
      }
      
      if (message.includes('err_stock')) {
        return {
          success: false,
          error: 'OUT_OF_STOCK',
          message: 'This card value is currently out of stock'
        };
      }
      
      if (message.includes('insufficient_balance')) {
        return {
          success: false,
          error: 'LOW_BALANCE',
          message: 'Insufficient account balance'
        };
      }
      
      if (message.includes('duplicated_ref')) {
        return {
          success: false,
          error: 'DUPLICATE_REF',
          message: 'This reference has already been used'
        };
      }
      
      return {
        success: false,
        error: 'UNKNOWN',
        message: 'Failed to process order. Please try again.'
      };
    }
  }
  ```

  ```python Python theme={null}
  def send_topup_safely(order_data):
      try:
          result = send_internet_topup(order_data)
          return {'success': True, 'data': result}
      except Exception as error:
          message = str(error).lower()
          
          if 'err_phone' in message:
              return {
                  'success': False,
                  'error': 'INVALID_PHONE',
                  'message': 'Invalid phone number for this service type'
              }
          
          if 'err_stock' in message:
              return {
                  'success': False,
                  'error': 'OUT_OF_STOCK',
                  'message': 'This card value is currently out of stock'
              }
          
          if 'insufficient_balance' in message:
              return {
                  'success': False,
                  'error': 'LOW_BALANCE',
                  'message': 'Insufficient account balance'
              }
          
          if 'duplicated_ref' in message:
              return {
                  'success': False,
                  'error': 'DUPLICATE_REF',
                  'message': 'This reference has already been used'
              }
          
          return {
              'success': False,
              'error': 'UNKNOWN',
              'message': 'Failed to process order. Please try again.'
          }
  ```

  ```php PHP theme={null}
  <?php

  function sendTopupSafely($orderData) {
      try {
          $result = sendInternetTopup($orderData);
          return ['success' => true, 'data' => $result];
      } catch (Exception $error) {
          $message = strtolower($error->getMessage());
          
          if (strpos($message, 'err_phone') !== false) {
              return [
                  'success' => false,
                  'error' => 'INVALID_PHONE',
                  'message' => 'Invalid phone number for this service type'
              ];
          }
          
          if (strpos($message, 'err_stock') !== false) {
              return [
                  'success' => false,
                  'error' => 'OUT_OF_STOCK',
                  'message' => 'This card value is currently out of stock'
              ];
          }
          
          if (strpos($message, 'insufficient_balance') !== false) {
              return [
                  'success' => false,
                  'error' => 'LOW_BALANCE',
                  'message' => 'Insufficient account balance'
              ];
          }
          
          if (strpos($message, 'duplicated_ref') !== false) {
              return [
                  'success' => false,
                  'error' => 'DUPLICATE_REF',
                  'message' => 'This reference has already been used'
              ];
          }
          
          return [
              'success' => false,
              'error' => 'UNKNOWN',
              'message' => 'Failed to process order. Please try again.'
          ];
      }
  }
  ?>
  ```
</CodeGroup>

## Bonnes pratiques

<CardGroup cols={2}>
  <Card title="Valider en premier" icon="check">
    Toujours utiliser `/check-number` avant d'envoyer
  </Card>

  <Card title="Vérifier le stock" icon="box">
    Vérifier la disponibilité du produit avant la commande
  </Card>

  <Card title="Références uniques" icon="fingerprint">
    Générer un `ref` unique pour chaque commande
  </Card>

  <Card title="Stocker immédiatement" icon="database">
    Sauvegarder `topupId` dès la soumission réussie
  </Card>
</CardGroup>

## Après la soumission de la commande

<Steps>
  <Step title="Stocker l'ID de recharge">
    Sauvegarder `topupId` dans votre base de données immédiatement
  </Step>

  <Step title="Démarrer l'interrogation">
    Commencer à vérifier le statut toutes les 5-10 secondes
  </Step>

  <Step title="Mettre à jour l'interface">
    Afficher le message « Traitement de la commande... » à l'utilisateur
  </Step>

  <Step title="Attendre l'état final">
    Continuer l'interrogation jusqu'à FULFILLED, REFUNDED ou QUEUED
  </Step>
</Steps>

## Étapes suivantes

<CardGroup cols={3}>
  <Card title="Suivre le statut" icon="chart-line" href="/fr/internet-topup-guides/4-status-tracking">
    Interroger le statut de la commande jusqu'à son achèvement
  </Card>

  <Card title="Livrer les cartes" icon="file-code" href="/fr/internet-topup-guides/5-card-delivery">
    Livrer les codes de carte aux clients
  </Card>

  <Card title="Référence API" icon="book" href="/fr/api-reference/internet/send-topup">
    Documentation complète de l'endpoint
  </Card>

  <Card title="Valider les numéros" icon="check" href="/fr/internet-topup-guides/2-validation">
    Vérifier les numéros de téléphone d'abord
  </Card>

  <Card title="Vue d'ensemble" icon="book-open" href="/fr/internet-topup-guides/overview">
    Retour à la vue d'ensemble de l'intégration
  </Card>

  <Card title="Vérifier le solde" icon="wallet" href="/fr/api-reference/account/get-balance">
    Obtenir le solde du compte
  </Card>
</CardGroup>
