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

# Étape 4 : Bonnes pratiques

> Sécurité essentielle et gestion des erreurs pour la production

## Sécurité

### 1. Protégez vos clés API

<Warning>
  **N'exposez jamais** les clés API dans le code frontend ou les dépôts publics !
</Warning>

```bash theme={null}
# Fichier .env (ajoutez à .gitignore)
ONECLICK_API_KEY=your_key_here
```

<CodeGroup>
  ```javascript Node.js theme={null}
  const apiKey = process.env.ONECLICK_API_KEY;
  ```

  ```python Python theme={null}
  import os
  api_key = os.getenv('ONECLICK_API_KEY')
  ```

  ```php PHP theme={null}
  <?php
  $apiKey = getenv('ONECLICK_API_KEY');
  ?>
  ```
</CodeGroup>

### 2. Backend uniquement

Appelez toujours l'API Navio depuis votre backend, jamais depuis le frontend :

```javascript theme={null}
// ❌ INCORRECT - Frontend
fetch("https://api.oneclickdz.com/v3/ocpay/createLink", {
  headers: { "X-Access-Token": "YOUR_KEY" }, // Exposé aux utilisateurs !
});

// ✅ CORRECT - Backend
// Le frontend appelle VOTRE API, votre backend appelle OneClick
fetch("/api/create-payment", { method: "POST" });
```

### 3. Validez les entrées

```javascript theme={null}
function validateOrderData(data) {
  if (!Number.isInteger(data.amount)) {
    throw new Error("Amount must be integer");
  }

  if (data.amount < 500 || data.amount > 500000) {
    throw new Error("Amount must be between 500 and 500,000 DZD");
  }

  if (!data.title || data.title.trim().length === 0) {
    throw new Error("Title is required");
  }

  return data;
}
```

### 4. Vérifiez avant de traiter

<Warning>
  Vérifiez toujours le statut du paiement sur le backend avant de traiter les commandes !
</Warning>

```javascript theme={null}
async function fulfillOrder(orderId) {
  const order = await db.orders.findOne({ id: orderId });

  // CRITICAL: Verify payment status
  const response = await fetch(
    `https://api.oneclickdz.com/v3/ocpay/checkPayment/${order.paymentRef}`,
    {
      headers: { "X-Access-Token": process.env.ONECLICK_API_KEY },
    }
  );

  const data = await response.json();

  if (data.data.status !== "CONFIRMED") {
    throw new Error("Payment not confirmed");
  }

  // Sûr de traiter
  await processOrder(order);
}
```

## Gestion des erreurs

### Gérer les erreurs API

<CodeGroup>
  ```javascript Node.js theme={null}
  async function createPaymentSafe(orderId, amount, title) {
    try {
      const response = await fetch(
        "https://api.oneclickdz.com/v3/ocpay/createLink",
        {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            "X-Access-Token": process.env.ONECLICK_API_KEY,
          },
          body: JSON.stringify({
            productInfo: { title, amount },
          }),
        }
      );

      if (!response.ok) {
        if (response.status === 403) {
          throw new Error("Merchant not validated");
        }
        throw new Error("API request failed");
      }

      const data = await response.json();

      if (!data.success) {
        throw new Error(data.error?.message || "Unknown error");
      }

      return data.data;
    } catch (error) {
      console.error("Payment creation failed:", error);
      throw error;
    }
  }
  ```

  ```python Python theme={null}
  def create_payment_safe(order_id, amount, title):
      try:
          response = requests.post(
              'https://api.oneclickdz.com/v3/ocpay/createLink',
              headers={
                  'Content-Type': 'application/json',
                  'X-Access-Token': os.getenv('ONECLICK_API_KEY')
              },
              json={
                  'productInfo': {'title': title, 'amount': amount}
              }
          )

          if response.status_code == 403:
              raise Exception('Merchant not validated')

          response.raise_for_status()

          data = response.json()

          if not data['success']:
              raise Exception(data['error'].get('message', 'Unknown error'))

          return data['data']

      except Exception as e:
          print(f'Payment creation failed: {e}')
          raise
  ```

  ```php PHP theme={null}
  <?php
  function createPaymentSafe($orderId, $amount, $title) {
      try {
          $ch = curl_init('https://api.oneclickdz.com/v3/ocpay/createLink');
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
          curl_setopt($ch, CURLOPT_POST, true);
          curl_setopt($ch, CURLOPT_HTTPHEADER, [
              'Content-Type: application/json',
              'X-Access-Token: ' . getenv('ONECLICK_API_KEY')
          ]);
          curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
              'productInfo' => ['title' => $title, 'amount' => $amount]
          ]));

          $response = curl_exec($ch);
          $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

          if ($httpCode === 403) {
              throw new Exception('Merchant not validated');
          }

          if ($httpCode !== 200) {
              throw new Exception('API request failed');
          }

          $data = json_decode($response, true);

          if (!$data['success']) {
              throw new Exception($data['error']['message'] ?? 'Unknown error');
          }

          return $data['data'];

      } catch (Exception $e) {
          error_log('Payment creation failed: ' . $e->getMessage());
          throw $e;
      }
  }
  ?>
  ```
</CodeGroup>

## Tests

### Utilisez le Sandbox

Testez avec les clés sandbox avant la production :

```bash theme={null}
# Développement
ONECLICK_API_KEY=sk_sandbox_abc123...

# Production
ONECLICK_API_KEY=sk_live_xyz789...
```

### Scénarios de test

Testez ces cas :

* ✅ Paiement réussi
* ✅ Paiement échoué
* ✅ Lien de paiement expiré (20 min)
* ✅ Client revient sans payer
* ✅ Erreurs API

## Liste de contrôle pour la production

**Avant de passer en ligne :**

### Sécurité

* [ ] Clés API dans les variables d'environnement
* [ ] Aucun appel API depuis le frontend
* [ ] Validation des entrées implémentée
* [ ] HTTPS activé

### Fonctionnalité

* [ ] La création de commande fonctionne
* [ ] Les liens de paiement se génèrent correctement
* [ ] La vérification du statut fonctionne
* [ ] Traitement des commandes uniquement sur CONFIRMED
* [ ] Tâche cron active

### Tests

* [ ] Tests sandbox terminés
* [ ] Tous les cas limites testés
* [ ] Gestion des erreurs vérifiée

### Surveillance

* [ ] Journalisation des erreurs activée
* [ ] Possibilité de voir les commandes en attente
* [ ] Possibilité de vérifier manuellement le statut

## Erreurs courantes

<Warning>
  **À éviter :**

  * ❌ Coder les clés API en dur
  * ❌ Appeler l'API depuis le frontend
  * ❌ Ne pas sauvegarder paymentRef
  * ❌ Traiter sans vérification
  * ❌ Aucune gestion des erreurs
  * ❌ Vérifier trop fréquemment (respectez les limites de débit)
  * ❌ Ne pas tester en sandbox d'abord
</Warning>

## Bonnes pratiques de base de données

Ajoutez des index pour les performances :

```sql theme={null}
-- Accélérer les requêtes de commandes en attente
CREATE INDEX idx_orders_pending
ON orders(status, payment_ref)
WHERE status = 'PENDING';

-- Accélérer les recherches par paymentRef
CREATE INDEX idx_payment_ref ON orders(payment_ref);
```

## Journalisation

Journalisez les événements importants :

```javascript theme={null}
// Journaliser la création de paiement
console.log("[Payment] Created", {
  orderId,
  paymentRef,
  amount,
  timestamp: new Date(),
});

// Journaliser les changements de statut
console.log("[Payment] Status changed", {
  orderId,
  oldStatus: "PENDING",
  newStatus: "PAID",
  timestamp: new Date(),
});
```

## Prochaines étapes

<CardGroup cols={2}>
  <Card title="Référence API" icon="book" href="/fr/api-reference/ocpay/create-link">
    Documentation API complète
  </Card>

  <Card title="Contacter le support" icon="headset" href="/fr/contact">
    Obtenez l'aide de notre équipe
  </Card>

  <Card title="Tableau de bord" icon="gauge" href="https://enterprise.oneclickdz.com/">
    Surveillez vos paiements
  </Card>

  <Card title="Guide de sécurité" icon="shield" href="/fr/security-best-practices">
    Pratiques de sécurité avancées
  </Card>
</CardGroup>

## Vous êtes prêt ! 🎉

Vous disposez maintenant de tout le nécessaire pour accepter des paiements avec Navio. Commencez par le sandbox, testez soigneusement, puis passez en production !
