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

# Flux de paiement

> Comprendre le flux de paiement complet de la création à la confirmation.

Ce guide explique le flux de paiement complet dans Yabetoo, de la création d'une intention de paiement à la réception de la confirmation via les webhooks.

## Vue d'ensemble

Le flux de paiement Yabetoo suit un processus en deux étapes qui vous donne un contrôle total sur le moment et la manière dont les paiements sont capturés.

```mermaid theme={null}
sequenceDiagram
    participant Client
    participant Serveur
    participant Yabetoo
    participant MobileMoney

    Client->>Serveur: Initier le paiement
    Serveur->>Yabetoo: Créer Payment Intent
    Yabetoo-->>Serveur: Retourner intent + client_secret
    Serveur->>Yabetoo: Confirmer Payment Intent
    Yabetoo->>MobileMoney: Envoyer demande de paiement
    MobileMoney-->>Client: Notification push (entrer PIN)
    Client->>MobileMoney: Confirmer le paiement
    MobileMoney-->>Yabetoo: Paiement confirmé
    Yabetoo-->>Serveur: Webhook: intent.completed
    Serveur-->>Client: Paiement réussi
```

## Étape 1 : Créer une intention de paiement

Une intention de paiement représente votre intention de collecter un paiement. Elle suit le cycle de vie du paiement et stocke les informations sur la transaction.

<CodeGroup>
  ```bash curl theme={null}
  curl https://pay.sandbox.yabetoopay.com/v1/payment-intents \
    -X POST \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer sk_test_XXXXXXXXXXXXXXXXXXXXXXXX" \
    -d '{
      "amount": 5000,
      "currency": "xaf"
    }'
  ```

  ```javascript Node.js theme={null}
  import { Yabetoo } from '@yabetoopay/node';

  const yabetoo = new Yabetoo('sk_test_XXXXXXXXXXXXXXXXXXXXXXXX');

  const paymentIntent = await yabetoo.paymentIntents.create({
    amount: 5000,
    currency: 'xaf',
  });

  // Retourne : { id: "pi_xxx", client_secret: "...", amount: 5000, currency: "xaf" }
  ```

  ```python Python theme={null}
  from yabetoo import Yabetoo

  yabetoo = Yabetoo('sk_test_XXXXXXXXXXXXXXXXXXXXXXXX')

  payment_intent = yabetoo.payment_intents.create(
    amount=5000,
    currency='xaf'
  )

  # Retourne : { id: "pi_xxx", client_secret: "...", amount: 5000, currency: "xaf" }
  ```

  ```php PHP theme={null}
  <?php
  require_once('vendor/autoload.php');

  $yabetoo = new \Yabetoo\YabetooClient('sk_test_XXXXXXXXXXXXXXXXXXXXXXXX');

  $paymentIntent = $yabetoo->paymentIntents->create([
    'amount' => 5000,
    'currency' => 'xaf'
  ]);

  // Retourne : [ 'id' => 'pi_xxx', 'client_secret' => '...', 'amount' => 5000, 'currency' => 'xaf' ]
  ?>
  ```

  ```java Java theme={null}
  import com.yabetoo.YabetooClient;
  import com.yabetoo.model.PaymentIntent;
  import com.yabetoo.param.PaymentIntentCreateParams;

  YabetooClient yabetoo = new YabetooClient("sk_test_XXXXXXXXXXXXXXXXXXXXXXXX");

  PaymentIntentCreateParams params = PaymentIntentCreateParams.builder()
      .setAmount(5000L)
      .setCurrency("xaf")
      .build();

  PaymentIntent paymentIntent = yabetoo.paymentIntents().create(params);

  // Retourne : { id: "pi_xxx", client_secret: "...", amount: 5000, currency: "xaf" }
  ```
</CodeGroup>

À cette étape :

* Aucun argent n'a été transféré
* L'intention est au statut `pending`
* Vous avez un `client_secret` pour l'étape suivante

## Étape 2 : Confirmer l'intention de paiement

La confirmation déclenche le paiement réel. Vous fournissez les détails du moyen de paiement du client (informations Mobile Money).

<CodeGroup>
  ```bash curl theme={null}
  curl https://pay.sandbox.yabetoopay.com/v1/payment-intents \
    -X POST \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer sk_test_XXXXXXXXXXXXXXXXXXXXXXXX" \
    -d '{
      "client_secret": "pi_xxx_secret_yyy",
      "first_name": "Jean",
      "last_name": "Dupont",
      "receipt_email": "jean@exemple.com",
      "payment_method_data": {
        "type": "momo",
        "momo": {
          "country": "cg",
          "msisdn": "+242066594470",
          "operator_name": "mtn"
        }
      }
    }'
  ```

  ```javascript Node.js theme={null}
  import { Yabetoo } from '@yabetoopay/node';

  const yabetoo = new Yabetoo('sk_test_XXXXXXXXXXXXXXXXXXXXXXXX');

  const confirmedIntent = await yabetoo.paymentIntents.confirm({
    client_secret: paymentIntent.client_secret,
    first_name: 'Jean',
    last_name: 'Dupont',
    receipt_email: 'jean@exemple.com',
    payment_method_data: {
      type: 'momo',
      momo: {
        country: 'cg',
        msisdn: '+242066594470',
        operator_name: 'mtn',
      },
    },
  });
  ```

  ```python Python theme={null}
  from yabetoo import Yabetoo

  yabetoo = Yabetoo('sk_test_XXXXXXXXXXXXXXXXXXXXXXXX')

  confirmed_intent = yabetoo.payment_intents.confirm(
    client_secret=payment_intent.client_secret,
    first_name='Jean',
    last_name='Dupont',
    receipt_email='jean@exemple.com',
    payment_method_data={
      'type': 'momo',
      'momo': {
        'country': 'cg',
        'msisdn': '+242066594470',
        'operator_name': 'mtn'
      }
    }
  )
  ```

  ```php PHP theme={null}
  <?php
  require_once('vendor/autoload.php');

  $yabetoo = new \Yabetoo\YabetooClient('sk_test_XXXXXXXXXXXXXXXXXXXXXXXX');

  $confirmedIntent = $yabetoo->paymentIntents->confirm([
    'client_secret' => $paymentIntent->client_secret,
    'first_name' => 'Jean',
    'last_name' => 'Dupont',
    'receipt_email' => 'jean@exemple.com',
    'payment_method_data' => [
      'type' => 'momo',
      'momo' => [
        'country' => 'cg',
        'msisdn' => '+242066594470',
        'operator_name' => 'mtn'
      ]
    ]
  ]);
  ?>
  ```

  ```java Java theme={null}
  import com.yabetoo.YabetooClient;
  import com.yabetoo.model.PaymentIntent;
  import com.yabetoo.param.PaymentIntentConfirmParams;
  import com.yabetoo.param.PaymentMethodData;
  import com.yabetoo.param.MomoData;

  YabetooClient yabetoo = new YabetooClient("sk_test_XXXXXXXXXXXXXXXXXXXXXXXX");

  MomoData momoData = MomoData.builder()
      .setCountry("cg")
      .setMsisdn("+242066594470")
      .setOperatorName("mtn")
      .build();

  PaymentMethodData paymentMethodData = PaymentMethodData.builder()
      .setType("momo")
      .setMomo(momoData)
      .build();

  PaymentIntentConfirmParams params = PaymentIntentConfirmParams.builder()
      .setClientSecret(paymentIntent.getClientSecret())
      .setFirstName("Jean")
      .setLastName("Dupont")
      .setReceiptEmail("jean@exemple.com")
      .setPaymentMethodData(paymentMethodData)
      .build();

  PaymentIntent confirmedIntent = yabetoo.paymentIntents().confirm(params);
  ```
</CodeGroup>

Après la confirmation :

* Le client reçoit une notification push sur son téléphone
* Il entre son code PIN pour autoriser le paiement
* Yabetoo attend la réponse du fournisseur Mobile Money

## Étape 3 : Gérer le résultat

### Réponse synchrone

La requête de confirmation retourne immédiatement avec le statut du paiement :

```json theme={null}
{
  "intent_id": "pi_9aATHBv8UXuD6H5qrSav",
  "amount": 5000,
  "currency": "xaf",
  "status": "succeeded",
  "captured": true
}
```

### Notification Webhook

Pour plus de fiabilité, écoutez toujours les webhooks. Yabetoo envoie un événement `intent.completed` lorsque le paiement réussit :

```javascript theme={null}
// Votre endpoint webhook
app.post("/webhook", (req, res) => {
  const event = req.body;

  if (event.type === "intent.completed") {
    const payment = event.data;
    // Mettre à jour votre base de données
    // Envoyer une confirmation au client
  }

  res.status(200).send("OK");
});
```

## Statuts de paiement

| Statut       | Description                                                            |
| ------------ | ---------------------------------------------------------------------- |
| `pending`    | Intention de paiement créée, pas encore confirmée                      |
| `processing` | Le paiement est en cours de traitement par le fournisseur Mobile Money |
| `succeeded`  | Paiement effectué avec succès                                          |
| `failed`     | Paiement échoué (fonds insuffisants, rejeté, etc.)                     |

## Codes d'erreur courants

Lorsqu'un paiement échoue, vous pouvez recevoir l'un de ces codes d'erreur :

| Code                                                | Description                                                                      |
| --------------------------------------------------- | -------------------------------------------------------------------------------- |
| `LOW_BALANCE_OR_PAYEE_LIMIT_REACHED_OR_NOT_ALLOWED` | Fonds insuffisants, limite de transaction atteinte, ou transaction non autorisée |
| `TIMEOUT`                                           | Le client n'a pas confirmé le paiement à temps                                   |

<Warning>
  Gérez toujours l'erreur `LOW_BALANCE_OR_PAYEE_LIMIT_REACHED_OR_NOT_ALLOWED` gracieusement en informant le client que son paiement n'a pas pu être traité en raison d'un solde insuffisant ou de restrictions sur son compte.
</Warning>

## Bonnes pratiques

1. **Vérifiez toujours les webhooks** - Ne vous fiez pas uniquement à la réponse synchrone
2. **Stockez l'ID de l'intention de paiement** - Liez-le à votre commande pour le suivi
3. **Gérez les échecs gracieusement** - Affichez des messages d'erreur clairs aux utilisateurs
4. **Implémentez l'idempotence** - Prévenez les paiements en double lors des nouvelles tentatives

## Alternative : Sessions de paiement

Pour une intégration plus simple, utilisez les Sessions de paiement. Yabetoo gère l'interface de paiement complète :

<CodeGroup>
  ```bash curl theme={null}
  curl https://buy.api.yabetoopay.com/v1/sessions \
    -X POST \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer sk_test_XXXXXXXXXXXXXXXXXXXXXXXX" \
    -d '{
      "total": 5000,
      "currency": "xaf",
      "accountId": "acct_XXXXXXXX",
      "successUrl": "https://votresite.com/success",
      "cancelUrl": "https://votresite.com/cancel",
      "items": [{
        "productId": "prod_123",
        "productName": "Plan Premium",
        "quantity": 1,
        "price": 5000
      }]
    }'
  ```

  ```javascript Node.js theme={null}
  import { Yabetoo } from '@yabetoopay/node';

  const yabetoo = new Yabetoo('sk_test_XXXXXXXXXXXXXXXXXXXXXXXX');

  const session = await yabetoo.sessions.create({
    total: 5000,
    currency: 'xaf',
    accountId: 'acct_XXXXXXXX',
    successUrl: 'https://votresite.com/success',
    cancelUrl: 'https://votresite.com/cancel',
    items: [
      {
        productId: 'prod_123',
        productName: 'Plan Premium',
        quantity: 1,
        price: 5000,
      },
    ],
  });

  // Redirigez le client vers session.url
  ```

  ```python Python theme={null}
  from yabetoo import Yabetoo
  from yabetoo.models.checkout import CreateCheckoutSession, CheckoutItem

  yabetoo = Yabetoo('sk_test_XXXXXXXXXXXXXXXXXXXXXXXX')

  session = yabetoo.sessions.create(CreateCheckoutSession(
    total=5000,
    currency='xaf',
    account_id='acct_XXXXXXXX',
    success_url='https://votresite.com/success',
    cancel_url='https://votresite.com/cancel',
    items=[
      CheckoutItem(
        product_id='prod_123',
        product_name='Plan Premium',
        quantity=1,
        price=5000
      )
    ]
  ))

  # Redirigez le client vers session.url
  ```

  ```php PHP theme={null}
  <?php
  require_once('vendor/autoload.php');

  $yabetoo = new \Yabetoo\YabetooClient('sk_test_XXXXXXXXXXXXXXXXXXXXXXXX');

  $session = $yabetoo->sessions->create([
    'total' => 5000,
    'currency' => 'xaf',
    'accountId' => 'acct_XXXXXXXX',
    'successUrl' => 'https://votresite.com/success',
    'cancelUrl' => 'https://votresite.com/cancel',
    'items' => [
      [
        'productId' => 'prod_123',
        'productName' => 'Plan Premium',
        'quantity' => 1,
        'price' => 5000
      ]
    ]
  ]);

  // Redirigez le client vers $session->url
  ?>
  ```

  ```java Java theme={null}
  import com.yabetoo.YabetooClient;
  import com.yabetoo.model.CheckoutSession;
  import com.yabetoo.param.CheckoutSessionCreateParams;
  import com.yabetoo.param.CheckoutItem;

  YabetooClient yabetoo = new YabetooClient("sk_test_XXXXXXXXXXXXXXXXXXXXXXXX");

  CheckoutItem item = CheckoutItem.builder()
      .setProductId("prod_123")
      .setProductName("Plan Premium")
      .setQuantity(1)
      .setPrice(5000L)
      .build();

  CheckoutSessionCreateParams params = CheckoutSessionCreateParams.builder()
      .setTotal(5000L)
      .setCurrency("xaf")
      .setAccountId("acct_XXXXXXXX")
      .setSuccessUrl("https://votresite.com/success")
      .setCancelUrl("https://votresite.com/cancel")
      .addItem(item)
      .build();

  CheckoutSession session = yabetoo.sessions().create(params);

  // Redirigez le client vers session.getUrl()
  ```
</CodeGroup>

<Note>
  Pour plus de détails sur chaque étape, consultez la [documentation de l'API Payment Intent](/fr/api-reference/payment-intent/create).
</Note>
