> ## 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 avec redirection (API direct)

> Intégrer les paiements redirect dans votre application

## Vue d'ensemble

Les paiements en application utilisent le type `redirect` qui permet de contrôler l'expérience utilisateur dans votre application tout en redirigeant le client vers son application de paiement mobile pour finaliser le paiement.

Pour plus de détails : [/api-reference/demandes-de-paiement/créer-une-demande-de-paiement](/api-reference/demandes-de-paiement/créer-une-demande-de-paiement)

## Caractéristiques

* **Contrôle de l'expérience** : Vous contrôlez le flux dans votre application
* **Redirection vers l'app** : Le client est redirigé vers son application de paiement mobile (Wave, Orange Money, Djamo, etc.)
* **Callbacks personnalisés** : Vous définissez les URLs de succès et d'erreur
* **Retour automatique** : Le client est automatiquement redirigé vers votre application après le paiement

## Cas d'usage

* Applications mobiles natives
* Applications web avec intégration personnalisée
* Expériences de paiement contrôlées par le développeur
* Intégrations nécessitant un contrôle total du flux

## Créer une demande de paiement redirect

Pour créer une demande de paiement redirect, utilisez l'endpoint `/partner_api/payment_requests` avec le type `redirect`.

### Paramètres requis

* `storeId` : Identifiant du magasin
* `amountCents` : Montant en centimes (minimum 100 centimes)
* `currency` : Code devise (ISO 4217), généralement "XOF"
* `reference` : Référence unique du paiement (1-100 caractères)
* `paymentDetails.type` : `"redirect"`
* `paymentDetails.data.paymentMethod` : Méthode de paiement (wave, orange, mtn, moov, djamo)
* `paymentDetails.data.successUrl` : **URL de redirection en cas de succès** (requis)
* `paymentDetails.data.errorUrl` : **URL de redirection en cas d'erreur** (requis)

### Contourner le checkout Jeko (optionnel — encaissement direct fournisseur)

Par défaut, une demande `redirect` renvoie une URL de paiement hébergée pour guider le payeur jusqu'à son opérateur.\
Ce flux est recommandé car il gère pour vous les cas limites propres à chaque opérateur (redirections, contraintes d'interface, variations de parcours).

Si vous connaissez déjà **le numéro du payeur** et **la méthode** (`paymentMethod`), vous pouvez activer le mode direct pour envoyer le payeur vers son fournisseur de paiement sans étape intermédiaire.\
Ce mode est surtout adapté si vous voulez construire votre propre expérience de checkout et gérer vous-même les cas limites propres à chaque opérateur.

* `paymentDetails.data.forceProviderDirect` : `true` pour activer ce mode ; sinon omis ou `false` (flux standard).
* `paymentDetails.data.payerPhone` : numéro mobile du payeur (MSISDN, en pratique souvent au format international, ex. `+2250765432108`) ; **obligatoire** lorsque `forceProviderDirect` est `true`.

### Exemple de requête

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.jeko.africa/partner_api/payment_requests" \
    -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",
      "amountCents": 10000,
      "currency": "XOF",
      "reference": "PAY-APP-2024-001",
      "paymentDetails": {
        "type": "redirect",
        "data": {
          "paymentMethod": "wave",
          "successUrl": "https://myapp.com/payment/success?reference=PAY-APP-2024-001",
          "errorUrl": "https://myapp.com/payment/error?reference=PAY-APP-2024-001"
        }
      }
    }'
  ```

  ```php PHP theme={null}
  <?php
  $ch = curl_init('https://api.jeko.africa/partner_api/payment_requests');
  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',
      'amountCents' => 10000,
      'currency' => 'XOF',
      'reference' => 'PAY-APP-2024-001',
      'paymentDetails' => [
          'type' => 'redirect',
          'data' => [
              'paymentMethod' => 'wave',
              'successUrl' => 'https://myapp.com/payment/success?reference=PAY-APP-2024-001',
              'errorUrl' => 'https://myapp.com/payment/error?reference=PAY-APP-2024-001'
          ]
      ]
  ]));

  $response = curl_exec($ch);
  curl_close($ch);
  $paymentRequest = 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_requests', {
    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',
      amountCents: 10000,
      currency: 'XOF',
      reference: 'PAY-APP-2024-001',
      paymentDetails: {
        type: 'redirect',
        data: {
          paymentMethod: 'wave',
          successUrl: 'https://myapp.com/payment/success?reference=PAY-APP-2024-001',
          errorUrl: 'https://myapp.com/payment/error?reference=PAY-APP-2024-001'
        }
      }
    })
  });

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

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

  uri = URI('https://api.jeko.africa/partner_api/payment_requests')
  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',
    amountCents: 10000,
    currency: 'XOF',
    reference: 'PAY-APP-2024-001',
    paymentDetails: {
      type: 'redirect',
      data: {
        paymentMethod: 'wave',
        successUrl: 'https://myapp.com/payment/success?reference=PAY-APP-2024-001',
        errorUrl: 'https://myapp.com/payment/error?reference=PAY-APP-2024-001'
      }
    }
  }.to_json

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

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

  url = 'https://api.jeko.africa/partner_api/payment_requests'
  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',
      'amountCents': 10000,
      'currency': 'XOF',
      'reference': 'PAY-APP-2024-001',
      'paymentDetails': {
          'type': 'redirect',
          'data': {
              'paymentMethod': 'wave',
              'successUrl': 'https://myapp.com/payment/success?reference=PAY-APP-2024-001',
              'errorUrl': 'https://myapp.com/payment/error?reference=PAY-APP-2024-001'
          }
      }
  }

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

### Réponse réussie

```json theme={null}
{
  "id": "d22c81f3-ee04-4ec5-8bd2-cd8af5dabcfc",
  "storeId": "59ae202a-f583-4a15-970f-9e99bd1e0baa",
  "reference": "PAY-APP-2024-001",
  "type": "redirect",
  "paymentMethod": "wave",
  "status": "pending",
  "redirectUrl": "https://pay.jeko.africa/payment/d22c81f3-ee04-4ec5-8bd2-cd8af5dabcfc"
}
```

**Important** : Le champ `redirectUrl` contient l'URL vers laquelle vous devez rediriger le client. Cette URL redirigera ensuite le client vers son application de paiement mobile.

## Flux de paiement

1. **Créer la demande** : Créez une demande de paiement redirect avec vos URLs de callback
2. **Rediriger le client** : Redirigez le client vers `redirectUrl`
3. **Redirection automatique** : JEKO redirige le client vers son application de paiement mobile
4. **Paiement client** : Le client complète le paiement dans son application
5. **Retour automatique** : Le client est redirigé vers votre `successUrl` ou `errorUrl`
6. **Notification** : Vous recevez également une notification via webhook

## Intégration dans votre application

### Exemple : Application web

```javascript theme={null}
async function initiatePayment(orderId, amount) {
  // Créer la demande de paiement
  const response = await fetch('https://api.jeko.africa/partner_api/payment_requests', {
    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',
      amountCents: amount,
      currency: 'XOF',
      reference: `ORDER-${orderId}`,
      paymentDetails: {
        type: 'redirect',
        data: {
          paymentMethod: 'wave', // ou la méthode sélectionnée par l'utilisateur
          successUrl: `https://myapp.com/payment/success?order=${orderId}`,
          errorUrl: `https://myapp.com/payment/error?order=${orderId}`
        }
      }
    })
  });
  
  const paymentRequest = await response.json();
  
  // Rediriger le client vers l'URL de redirection
  window.location.href = paymentRequest.redirectUrl;
}
```

### Exemple : Application mobile (React Native)

```javascript theme={null}
import { Linking } from 'react-native';

async function initiatePayment(orderId, amount) {
  // Créer la demande de paiement
  const response = await fetch('https://api.jeko.africa/partner_api/payment_requests', {
    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',
      amountCents: amount,
      currency: 'XOF',
      reference: `ORDER-${orderId}`,
      paymentDetails: {
        type: 'redirect',
        data: {
          paymentMethod: 'wave',
          successUrl: `myapp://payment/success?order=${orderId}`,
          errorUrl: `myapp://payment/error?order=${orderId}`
        }
      }
    })
  });
  
  const paymentRequest = await response.json();
  
  // Ouvrir l'URL de redirection
  Linking.openURL(paymentRequest.redirectUrl);
}
```

### Gérer les callbacks

#### Page de succès

```javascript theme={null}
// Dans votre page /payment/success
function PaymentSuccessPage() {
  const params = new URLSearchParams(window.location.search);
  const reference = params.get('reference');
  const orderId = params.get('order');
  
  // Vérifier le statut du paiement via l'API
  useEffect(() => {
    checkPaymentStatus(reference).then(status => {
      if (status === 'success') {
        // Mettre à jour la commande comme payée
        updateOrderStatus(orderId, 'paid');
        // Afficher un message de succès
        showSuccessMessage('Paiement effectué avec succès !');
      }
    });
  }, [reference, orderId]);
  
  return <div>Paiement réussi !</div>;
}
```

#### Page d'erreur

```javascript theme={null}
// Dans votre page /payment/error
function PaymentErrorPage() {
  const params = new URLSearchParams(window.location.search);
  const reference = params.get('reference');
  const orderId = params.get('order');
  
  // Vérifier le statut du paiement via l'API
  useEffect(() => {
    checkPaymentStatus(reference).then(status => {
      if (status === 'error') {
        // Afficher un message d'erreur
        showErrorMessage('Le paiement a échoué. Veuillez réessayer.');
      }
    });
  }, [reference, orderId]);
  
  return <div>Le paiement a échoué. Veuillez réessayer.</div>;
}
```

## Vérifier le statut

Pour vérifier le statut d'une demande de paiement :

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

  ```php PHP theme={null}
  <?php
  $paymentRequestId = 'd22c81f3-ee04-4ec5-8bd2-cd8af5dabcfc';
  $ch = curl_init("https://api.jeko.africa/partner_api/payment_requests/{$paymentRequestId}");
  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);
  $paymentRequest = json_decode($response, true);
  ?>
  ```

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

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

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

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

  payment_request_id = 'd22c81f3-ee04-4ec5-8bd2-cd8af5dabcfc'
  uri = URI("https://api.jeko.africa/partner_api/payment_requests/#{payment_request_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_request = JSON.parse(response.body)
  ```

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

  payment_request_id = 'd22c81f3-ee04-4ec5-8bd2-cd8af5dabcfc'
  url = f'https://api.jeko.africa/partner_api/payment_requests/{payment_request_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_request = response.json()
  ```
</CodeGroup>

**Réponse avec transaction réussie** :

```json theme={null}
{
  "id": "d22c81f3-ee04-4ec5-8bd2-cd8af5dabcfc",
  "storeId": "59ae202a-f583-4a15-970f-9e99bd1e0baa",
  "reference": "PAY-APP-2024-001",
  "type": "redirect",
  "paymentMethod": "wave",
  "status": "success",
  "transaction": {
    "id": "txn_1234567890",
    "amount": {
      "amount": 10000,
      "currency": "XOF"
    },
    "fees": {
      "amount": 100,
      "currency": "XOF"
    },
    "status": "success",
    "counterpartLabel": "Customer Name",
    "counterpartIdentifier": "+2250701234567",
    "description": "Payment for order #12345",
    "executedAt": "2024-01-15 14:30:25"
  }
}
```

## Méthodes de paiement supportées

* `"wave"` : Wave Mobile Money
* `"orange"` : Orange Money
* `"mtn"` : MTN Mobile Money
* `"moov"` : Moov Money
* `"djamo"` : DJAMO

## URLs de callback

### Format des URLs

Les URLs de succès et d'erreur doivent être des URLs HTTPS valides. Vous pouvez inclure des paramètres de requête pour identifier la transaction :

```
https://myapp.com/payment/success?reference=PAY-APP-2024-001&order=12345
https://myapp.com/payment/error?reference=PAY-APP-2024-001&order=12345
```

### Deep links (applications mobiles)

Pour les applications mobiles, vous pouvez utiliser des deep links :

```
myapp://payment/success?reference=PAY-APP-2024-001
myapp://payment/error?reference=PAY-APP-2024-001
```

**Important** : Assurez-vous que votre application est configurée pour gérer ces deep links.

## Bonnes pratiques

1. **URLs sécurisées** : Utilisez toujours HTTPS pour les URLs de callback
2. **Paramètres de requête** : Incluez des paramètres pour identifier la transaction (référence, orderId, etc.)
3. **Vérification du statut** : Toujours vérifier le statut du paiement via l'API après le callback
4. **Gestion des erreurs** : Implémentez une gestion d'erreurs robuste pour les cas d'échec
5. **Webhooks** : Utilisez les webhooks comme source de vérité principale, les callbacks comme fallback
6. **Expérience utilisateur** : Affichez des messages clairs sur les pages de succès et d'erreur
7. **Timeouts** : Gérez les cas où le client ne revient pas de l'application de paiement

## Cas d'usage avancés

### Sélection dynamique de la méthode de paiement

Permettez à l'utilisateur de choisir sa méthode de paiement avant de créer la demande :

```javascript theme={null}
function PaymentMethodSelector({ orderId, amount }) {
  const [selectedMethod, setSelectedMethod] = useState('wave');
  
  const methods = ['wave', 'orange', 'mtn', 'moov', 'djamo'];
  
  const handlePayment = async () => {
    await initiatePayment(orderId, amount, selectedMethod);
  };
  
  return (
    <div>
      <h3>Sélectionnez votre méthode de paiement</h3>
      {methods.map(method => (
        <button
          key={method}
          onClick={() => setSelectedMethod(method)}
          className={selectedMethod === method ? 'selected' : ''}
        >
          {method.toUpperCase()}
        </button>
      ))}
      <button onClick={handlePayment}>Payer</button>
    </div>
  );
}
```

### Gestion des timeouts

Si le client ne revient pas après un certain temps, vérifiez le statut :

```javascript theme={null}
function PaymentPage({ orderId, amount }) {
  const [paymentStatus, setPaymentStatus] = useState('pending');
  
  useEffect(() => {
    // Créer la demande de paiement
    initiatePayment(orderId, amount).then(paymentRequest => {
      // Rediriger le client
      window.location.href = paymentRequest.redirectUrl;
      
      // Vérifier le statut toutes les 5 secondes (timeout après 5 minutes)
      const interval = setInterval(async () => {
        const status = await checkPaymentStatus(paymentRequest.id);
        setPaymentStatus(status);
        
        if (status !== 'pending') {
          clearInterval(interval);
        }
      }, 5000);
      
      // Timeout après 5 minutes
      setTimeout(() => {
        clearInterval(interval);
        if (paymentStatus === 'pending') {
          // Gérer le timeout
          handlePaymentTimeout(orderId);
        }
      }, 300000);
    });
  }, [orderId, amount]);
  
  return <div>Redirection en cours...</div>;
}
```
