> ## Documentation Index
> Fetch the complete documentation index at: https://developer.jeko.africa/llms.txt
> Use this file to discover all available pages before exploring further.

# Paiement en ligne (ecommerce / lien de paiement)

> Intégrer les paiements en ligne via les liens de paiement JEKO

## Vue d'ensemble

Les paiements en ligne utilisent des **liens de paiement** partageables. Le client est redirigé vers une page de paiement sécurisée JEKO où il peut sélectionner son moyen de paiement et confirmer la transaction.

Pour plus de détails : [/api-reference/liens-de-paiement/créer-un-lien-de-paiement](/api-reference/liens-de-paiement/cr%C3%A9er-un-lien-de-paiement)

## Cas d'usage

* Sites e-commerce
* Paiements de factures en ligne
* Collecte de fonds
* Commandes en ligne
* Paiements récurrents (avec liens réutilisables)

## Créer un lien de paiement

Pour créer un lien de paiement, utilisez l'endpoint `/partner_api/payment_links`.

### Paramètres requis

* `storeId` : Identifiant du magasin
* `title` : Titre du lien de paiement (10-255 caractères)
* `amountCents` : Montant fixe en centimes (minimum 10000 centimes = 100 XOF)
* `currency` : Code devise (ISO 4217), généralement "XOF"
* `allowMultiplePayments` : (Optionnel) Permet plusieurs paiements sur le même lien (défaut: `false`)

### Exemple : Lien à usage unique

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.jeko.africa/partner_api/payment_links" \
    -H "X-API-KEY: your_api_key_here" \
    -H "X-API-KEY-ID: your_api_key_id_here" \
    -H "Content-Type: application/json" \
    -d '{
      "storeId": "59ae202a-f583-4a15-970f-9e99bd1e0baa",
      "title": "Paiement pour services - Commande #12345",
      "amountCents": 50000,
      "currency": "XOF",
      "allowMultiplePayments": false
    }'
  ```

  ```php PHP theme={null}
  <?php
  $ch = curl_init('https://api.jeko.africa/partner_api/payment_links');
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'X-API-KEY: your_api_key_here',
      'X-API-KEY-ID: your_api_key_id_here',
      'Content-Type: application/json'
  ]);
  curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
      'storeId' => '59ae202a-f583-4a15-970f-9e99bd1e0baa',
      'title' => 'Paiement pour services - Commande #12345',
      'amountCents' => 50000,
      'currency' => 'XOF',
      'allowMultiplePayments' => false
  ]));

  $response = curl_exec($ch);
  curl_close($ch);
  $paymentLink = json_decode($response, true);
  ?>
  ```

  ```javascript Node.js theme={null}
  const fetch = require('node-fetch');

  const response = await fetch('https://api.jeko.africa/partner_api/payment_links', {
    method: 'POST',
    headers: {
      'X-API-KEY': 'your_api_key_here',
      'X-API-KEY-ID': 'your_api_key_id_here',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      storeId: '59ae202a-f583-4a15-970f-9e99bd1e0baa',
      title: 'Paiement pour services - Commande #12345',
      amountCents: 50000,
      currency: 'XOF',
      allowMultiplePayments: false
    })
  });

  const paymentLink = await response.json();
  ```

  ```ruby Ruby theme={null}
  require 'net/http'
  require 'json'
  require 'uri'

  uri = URI('https://api.jeko.africa/partner_api/payment_links')
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true

  request = Net::HTTP::Post.new(uri.path)
  request['X-API-KEY'] = 'your_api_key_here'
  request['X-API-KEY-ID'] = 'your_api_key_id_here'
  request['Content-Type'] = 'application/json'
  request.body = {
    storeId: '59ae202a-f583-4a15-970f-9e99bd1e0baa',
    title: 'Paiement pour services - Commande #12345',
    amountCents: 50000,
    currency: 'XOF',
    allowMultiplePayments: false
  }.to_json

  response = http.request(request)
  payment_link = JSON.parse(response.body)
  ```

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

  url = 'https://api.jeko.africa/partner_api/payment_links'
  headers = {
      'X-API-KEY': 'your_api_key_here',
      'X-API-KEY-ID': 'your_api_key_id_here',
      'Content-Type': 'application/json'
  }
  data = {
      'storeId': '59ae202a-f583-4a15-970f-9e99bd1e0baa',
      'title': 'Paiement pour services - Commande #12345',
      'amountCents': 50000,
      'currency': 'XOF',
      'allowMultiplePayments': False
  }

  response = requests.post(url, headers=headers, json=data)
  payment_link = response.json()
  ```
</CodeGroup>

### Exemple : Lien réutilisable

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.jeko.africa/partner_api/payment_links" \
    -H "X-API-KEY: your_api_key_here" \
    -H "X-API-KEY-ID: your_api_key_id_here" \
    -H "Content-Type: application/json" \
    -d '{
      "storeId": "59ae202a-f583-4a15-970f-9e99bd1e0baa",
      "title": "Dons pour association",
      "amountCents": 10000,
      "currency": "XOF",
      "allowMultiplePayments": true
    }'
  ```

  ```php PHP theme={null}
  <?php
  $ch = curl_init('https://api.jeko.africa/partner_api/payment_links');
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'X-API-KEY: your_api_key_here',
      'X-API-KEY-ID: your_api_key_id_here',
      'Content-Type: application/json'
  ]);
  curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
      'storeId' => '59ae202a-f583-4a15-970f-9e99bd1e0baa',
      'title' => 'Dons pour association',
      'amountCents' => 10000,
      'currency' => 'XOF',
      'allowMultiplePayments' => true
  ]));

  $response = curl_exec($ch);
  curl_close($ch);
  $paymentLink = json_decode($response, true);
  ?>
  ```

  ```javascript Node.js theme={null}
  const fetch = require('node-fetch');

  const response = await fetch('https://api.jeko.africa/partner_api/payment_links', {
    method: 'POST',
    headers: {
      'X-API-KEY': 'your_api_key_here',
      'X-API-KEY-ID': 'your_api_key_id_here',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      storeId: '59ae202a-f583-4a15-970f-9e99bd1e0baa',
      title: 'Dons pour association',
      amountCents: 10000,
      currency: 'XOF',
      allowMultiplePayments: true
    })
  });

  const paymentLink = await response.json();
  ```

  ```ruby Ruby theme={null}
  require 'net/http'
  require 'json'
  require 'uri'

  uri = URI('https://api.jeko.africa/partner_api/payment_links')
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true

  request = Net::HTTP::Post.new(uri.path)
  request['X-API-KEY'] = 'your_api_key_here'
  request['X-API-KEY-ID'] = 'your_api_key_id_here'
  request['Content-Type'] = 'application/json'
  request.body = {
    storeId: '59ae202a-f583-4a15-970f-9e99bd1e0baa',
    title: 'Dons pour association',
    amountCents: 10000,
    currency: 'XOF',
    allowMultiplePayments: true
  }.to_json

  response = http.request(request)
  payment_link = JSON.parse(response.body)
  ```

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

  url = 'https://api.jeko.africa/partner_api/payment_links'
  headers = {
      'X-API-KEY': 'your_api_key_here',
      'X-API-KEY-ID': 'your_api_key_id_here',
      'Content-Type': 'application/json'
  }
  data = {
      'storeId': '59ae202a-f583-4a15-970f-9e99bd1e0baa',
      'title': 'Dons pour association',
      'amountCents': 10000,
      'currency': 'XOF',
      'allowMultiplePayments': True
  }

  response = requests.post(url, headers=headers, json=data)
  payment_link = response.json()
  ```
</CodeGroup>

### Réponse réussie

```json theme={null}
{
  "id": "d22c81f3-ee04-4ec5-8bd2-cd8af5dabcfc",
  "storeId": "59ae202a-f583-4a15-970f-9e99bd1e0baa",
  "title": "Paiement pour services - Commande #12345",
  "amount": {
    "amount": 50000,
    "currency": "XOF"
  },
  "allowMultiplePayments": false,
  "canReceivePayments": true,
  "link": "https://pay.jeko.africa/c/abc123def456"
}
```

**Important** : Le champ `link` contient l'URL partageable à envoyer au client. Le champ `canReceivePayments` indique si le lien peut actuellement accepter de nouveaux paiements.

## Types de liens de paiement

### Liens à usage unique (`allowMultiplePayments: false`)

* **Comportement** : Le lien devient indisponible après le premier paiement réussi
* **Cas d'usage** : Paiements de factures, commandes spécifiques
* **Disponibilité** : `canReceivePayments` passe à `false` après le premier paiement

**Note** : Les liens de paiement n'ont pas de statut (pas de `pending`, `success`, `error`). Utilisez uniquement `canReceivePayments` pour vérifier la disponibilité.

### Liens réutilisables (`allowMultiplePayments: true`)

* **Comportement** : Le lien peut accepter plusieurs paiements
* **Cas d'usage** : Collecte de fonds, dons, abonnements
* **Disponibilité** : `canReceivePayments` reste `true` tant que le lien est actif

## Vérifier la disponibilité d'un lien

Avant de diriger un client vers un lien, vérifiez qu'il peut encore accepter des paiements :

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api.jeko.africa/partner_api/payment_links/{paymentLinkId}" \
    -H "X-API-KEY: your_api_key_here" \
    -H "X-API-KEY-ID: your_api_key_id_here"
  ```

  ```php PHP theme={null}
  <?php
  $paymentLinkId = 'd22c81f3-ee04-4ec5-8bd2-cd8af5dabcfc';
  $ch = curl_init("https://api.jeko.africa/partner_api/payment_links/{$paymentLinkId}");
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'X-API-KEY: your_api_key_here',
      'X-API-KEY-ID: your_api_key_id_here'
  ]);

  $response = curl_exec($ch);
  curl_close($ch);
  $paymentLink = json_decode($response, true);
  ?>
  ```

  ```javascript Node.js theme={null}
  const fetch = require('node-fetch');

  const paymentLinkId = 'd22c81f3-ee04-4ec5-8bd2-cd8af5dabcfc';
  const response = await fetch(
    `https://api.jeko.africa/partner_api/payment_links/${paymentLinkId}`,
    {
      headers: {
        'X-API-KEY': 'your_api_key_here',
        'X-API-KEY-ID': 'your_api_key_id_here'
      }
    }
  );

  const paymentLink = await response.json();
  ```

  ```ruby Ruby theme={null}
  require 'net/http'
  require 'json'
  require 'uri'

  payment_link_id = 'd22c81f3-ee04-4ec5-8bd2-cd8af5dabcfc'
  uri = URI("https://api.jeko.africa/partner_api/payment_links/#{payment_link_id}")
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true

  request = Net::HTTP::Get.new(uri.path)
  request['X-API-KEY'] = 'your_api_key_here'
  request['X-API-KEY-ID'] = 'your_api_key_id_here'

  response = http.request(request)
  payment_link = JSON.parse(response.body)
  ```

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

  payment_link_id = 'd22c81f3-ee04-4ec5-8bd2-cd8af5dabcfc'
  url = f'https://api.jeko.africa/partner_api/payment_links/{payment_link_id}'
  headers = {
      'X-API-KEY': 'your_api_key_here',
      'X-API-KEY-ID': 'your_api_key_id_here'
  }

  response = requests.get(url, headers=headers)
  payment_link = response.json()
  ```
</CodeGroup>

**Réponse** :

```json theme={null}
{
  "id": "d22c81f3-ee04-4ec5-8bd2-cd8af5dabcfc",
  "storeId": "59ae202a-f583-4a15-970f-9e99bd1e0baa",
  "title": "Paiement pour services - Commande #12345",
  "amount": {
    "amount": 50000,
    "currency": "XOF"
  },
  "allowMultiplePayments": false,
  "canReceivePayments": false,
  "link": "https://pay.jeko.africa/c/abc123def456"
}
```

**Important** : Si `canReceivePayments` est `false`, ne dirigez pas le client vers le lien. Cela peut se produire si :

* Le lien est à usage unique et a déjà été utilisé
* Le lien a expiré
* Le lien a été désactivé

### Vérifier si un paiement a été complété (liens à usage unique)

Pour les liens à usage unique (`allowMultiplePayments: false`), vous pouvez vérifier si le paiement a été complété en vérifiant `canReceivePayments` :

* **`canReceivePayments: true`** : Le lien peut encore accepter un paiement (pas encore payé)
* **`canReceivePayments: false`** : Le paiement a été complété (pour les liens à usage unique)

**Exemple** : Vérifier si un paiement a été complété

```javascript theme={null}
async function checkPaymentCompleted(paymentLinkId) {
  const response = await fetch(
    `https://api.jeko.africa/partner_api/payment_links/${paymentLinkId}`,
    {
      headers: {
        'X-API-KEY': apiKey,
        'X-API-KEY-ID': apiKeyId
      }
    }
  );
  
  const paymentLink = await response.json();
  
  // Pour les liens à usage unique, canReceivePayments: false signifie que le paiement a été complété
  if (paymentLink.allowMultiplePayments === false) {
    if (paymentLink.canReceivePayments === false) {
      return { completed: true, message: 'Le paiement a été complété' };
    } else {
      return { completed: false, message: 'Le paiement est en attente' };
    }
  }
  
  // Pour les liens réutilisables, canReceivePayments ne peut pas indiquer si un paiement spécifique a été complété
  // Utilisez les webhooks pour suivre les paiements individuels
  return { completed: null, message: 'Lien réutilisable - utilisez les webhooks pour suivre les paiements' };
}
```

**Note** : Cette méthode fonctionne uniquement pour les liens à usage unique. Pour les liens réutilisables, utilisez les webhooks pour suivre les paiements individuels.

## Flux de paiement

1. **Créer le lien** : Créez un lien de paiement via l'API
2. **Partager le lien** : Envoyez le lien au client (email, SMS, message, etc.)
3. **Client clique** : Le client clique sur le lien et est redirigé vers la page de paiement JEKO
4. **Sélection du moyen** : Le client sélectionne son moyen de paiement
5. **Confirmation** : Le client confirme le paiement
6. **Notification** : Vous recevez une notification via webhook lorsque le paiement est complété

## Intégration dans votre site e-commerce

### Exemple : Bouton de paiement

```html theme={null}
<!-- Dans votre page de commande -->
<button id="pay-button" onclick="createPaymentLink()">
  Payer maintenant
</button>

<script>
async function createPaymentLink() {
  const response = await fetch('https://api.jeko.africa/partner_api/payment_links', {
    method: 'POST',
    headers: {
      'X-API-KEY': 'your_api_key_here',
      'X-API-KEY-ID': 'your_api_key_id_here',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      storeId: '59ae202a-f583-4a15-970f-9e99bd1e0baa',
      title: `Paiement - Commande #${orderId}`,
      amountCents: orderAmount,
      currency: 'XOF',
      allowMultiplePayments: false
    })
  });
  
  const paymentLink = await response.json();
  
  // Rediriger le client vers le lien de paiement
  window.location.href = paymentLink.link;
}
</script>
```

### Exemple : Lien pré-créé

Si vous créez le lien à l'avance (par exemple, lors de la création de la commande), vous pouvez stocker le lien et l'afficher plus tard :

```javascript theme={null}
// Lors de la création de la commande
const paymentLink = await createPaymentLink(orderId, amount);

// Stocker paymentLink.id et paymentLink.link dans votre base de données

// Plus tard, afficher le lien au client
function displayPaymentLink(orderId) {
  // Récupérer le lien depuis votre base de données
  const link = getStoredPaymentLink(orderId);
  
  // Vérifier que le lien peut encore accepter des paiements
  checkLinkAvailability(link.id).then(available => {
    if (available) {
      // Afficher le bouton de paiement
      document.getElementById('pay-button').href = link.link;
    } else {
      // Créer un nouveau lien
      createNewPaymentLink(orderId, amount);
    }
  });
}
```

## Gestion des erreurs

### Lien expiré

Si un client essaie d'utiliser un lien expiré, il recevra un message d'erreur. Vérifiez toujours `canReceivePayments` avant de diriger un client vers un lien.

### Lien déjà utilisé

Pour les liens à usage unique, si le lien a déjà été utilisé, `canReceivePayments` sera `false`. Créez un nouveau lien si nécessaire.

### Polling pour vérifier la complétion du paiement

Pour les liens à usage unique, vous pouvez implémenter un polling pour vérifier si le paiement a été complété :

```javascript theme={null}
async function pollPaymentCompletion(paymentLinkId, maxAttempts = 60, intervalMs = 5000) {
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    const response = await fetch(
      `https://api.jeko.africa/partner_api/payment_links/${paymentLinkId}`,
      {
        headers: {
          'X-API-KEY': apiKey,
          'X-API-KEY-ID': apiKeyId
        }
      }
    );
    
    const paymentLink = await response.json();
    
    // Pour les liens à usage unique, canReceivePayments: false signifie paiement complété
    if (paymentLink.allowMultiplePayments === false && !paymentLink.canReceivePayments) {
      return { completed: true, paymentLink };
    }
    
    // Attendre avant le prochain essai
    await new Promise(resolve => setTimeout(resolve, intervalMs));
  }
  
  return { completed: false, message: 'Timeout - le paiement n\'a pas été complété dans le délai imparti' };
}

// Utilisation
const result = await pollPaymentCompletion(paymentLinkId);
if (result.completed) {
  console.log('Paiement complété !');
  // Mettre à jour la commande, envoyer un email de confirmation, etc.
}
```

**Note** : Le polling est une alternative aux webhooks. Pour une meilleure expérience, utilisez les webhooks comme méthode principale et le polling comme fallback.

Consultez [Gérer les échecs](./failure-reasons) pour plus de détails sur les erreurs.

## Bonnes pratiques

1. **Vérifier la disponibilité** : Toujours vérifier `canReceivePayments` avant de diriger un client vers un lien
2. **Vérifier la complétion** : Pour les liens à usage unique, utilisez `canReceivePayments: false` pour détecter que le paiement a été complété
3. **Liens à usage unique** : Utilisez des liens à usage unique pour les paiements de factures ou commandes spécifiques
4. **Liens réutilisables** : Utilisez des liens réutilisables pour les collectes de fonds ou dons
5. **Titres descriptifs** : Utilisez des titres clairs qui aident le client à identifier le paiement
6. **Webhooks** : Configurez des webhooks pour être notifié automatiquement des paiements (méthode recommandée)
7. **Polling** : Pour les liens à usage unique, vous pouvez utiliser le polling comme alternative aux webhooks pour vérifier la complétion
8. **Expiration** : Les liens peuvent expirer, prévoyez une gestion des liens expirés

## Cas d'usage avancés

### Paiements récurrents

Créez un lien réutilisable pour permettre aux clients de payer régulièrement :

```javascript theme={null}
// Créer un lien réutilisable pour un abonnement mensuel
const subscriptionLink = await createPaymentLink({
  storeId: storeId,
  title: "Abonnement mensuel - Janvier 2024",
  amountCents: 10000,
  currency: "XOF",
  allowMultiplePayments: true
});

// Le même lien peut être utilisé chaque mois
```

### Paiements de factures

Créez un lien à usage unique pour chaque facture :

```javascript theme={null}
// Créer un lien unique pour chaque facture
const invoiceLink = await createPaymentLink({
  storeId: storeId,
  title: `Facture #${invoiceNumber} - ${customerName}`,
  amountCents: invoiceAmount,
  currency: "XOF",
  allowMultiplePayments: false
});

// Envoyer le lien au client par email
sendInvoiceEmail(customerEmail, invoiceLink.link);
```
