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

# Paiement

> Apprenez à initier et gérer des sessions de paiement via l'API Chariow

L'API de paiement vous permet de créer de manière programmatique des sessions d'achat pour vos clients. Cela est utile pour les vitrines personnalisées, les intégrations ou les flux de vente automatisés.

<Warning>
  **Types de produits non pris en charge** — Les produits suivants ne peuvent pas être utilisés pour initier un checkout via l'API :

  * Produits de type **Service**
  * Produits de type **Coaching**
  * Produits avec tarification **prix libre**

  Pour ceux-ci, redirigez vos clients vers votre [boutique Chariow](https://chariow.com) ou utilisez le **widget Snap** intégré sur votre site web.
</Warning>

<Info>
  Toutes les ventes initiées via l'API checkout auront leur **Canal** défini sur **« API »** dans votre tableau de bord. Cela vous aide à identifier et suivre les ventes provenant de vos intégrations API séparément des autres canaux comme votre vitrine ou le widget Snap.
</Info>

## Achats répétés

La possibilité d'acheter un produit plusieurs fois dépend du type de produit :

| Type de produit    | Achat répété      | Comportement                                                                                                             |
| ------------------ | ----------------- | ------------------------------------------------------------------------------------------------------------------------ |
| **Licence**        | Toujours autorisé | Les clients peuvent acheter des produits licence plusieurs fois. Chaque achat génère une nouvelle clé de licence unique. |
| **Téléchargeable** | Bloqué            | Retourne `already_purchased` si le client a un accès actif.                                                              |
| **Cours**          | Bloqué            | Retourne `already_purchased` si le client a un accès actif.                                                              |
| **Bundle**         | Bloqué            | Retourne `already_purchased` si le client a un accès actif.                                                              |

<Tip>
  Pour les types de produits bloqués, si l'accès d'un client a été **révoqué** (par exemple après un remboursement), il pourra acheter le produit à nouveau. Le système vérifie uniquement les accès **actifs**.
</Tip>

## Aperçu du flux de paiement

L'API de paiement Chariow gère le flux d'achat complet de l'initiation à la finalisation :

<Note>
  Le produit doit être **publié** avant d'initier un paiement. Les produits non publiés retourneront une erreur 404.
</Note>

<Steps>
  <Step title="Initier le paiement">
    Appelez le point de terminaison `/checkout` avec l'ID du produit et les détails du client
  </Step>

  <Step title="Traiter la réponse">
    Vérifiez le champ `step` dans la réponse :

    * **payment** : Redirigez le client vers `checkout_url` pour le paiement
    * **completed** : Vente finalisée immédiatement (produits gratuits)
    * **already\_purchased** : Le client possède déjà ce produit
  </Step>

  <Step title="Traiter le paiement">
    Le client finalise le paiement sur la page de paiement sécurisée Chariow
  </Step>

  <Step title="Recevoir le webhook">
    Recevez une notification des changements de statut de vente via webhooks (recommandé)
  </Step>

  <Step title="Livrer le produit">
    Le client reçoit automatiquement l'accès aux fichiers, licences, cours, etc.
  </Step>
</Steps>

## Types de produits pris en charge

L'API de paiement prend en charge les types de produits Chariow suivants :

* **Produits téléchargeables** : Fichiers numériques (PDF, logiciels, médias)
* **Cours** : Contenu éducatif avec leçons et chapitres
* **Licences** : Clés de licence logicielle avec gestion des activations
* **Bundles** : Collections de plusieurs produits

<Note>
  Les types de produits **Service** et **Coaching** ne sont pas pris en charge via l'API publique. Pour ces produits, redirigez vos clients vers votre boutique Chariow ou utilisez le widget Snap. Les produits à tarification prix libre ne sont pas non plus pris en charge.
</Note>

## Initier un paiement

Créez une nouvelle session de paiement :

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.chariow.com/v1/checkout" \
    -H "Authorization: Bearer sk_live_your_api_key" \
    -H "Content-Type: application/json" \
    -d '{
      "product_id": "prd_abc123",
      "email": "customer@example.com",
      "first_name": "John",
      "last_name": "Doe",
      "phone": {
        "number": "1234567890",
        "country_code": "US"
      },
      "discount_code": "SAVE20"
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.chariow.com/v1/checkout', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer sk_live_your_api_key',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      product_id: 'prd_abc123',
      email: 'customer@example.com',
      first_name: 'John',
      last_name: 'Doe',
      phone: {
        number: '1234567890',
        country_code: 'US'
      },
      discount_code: 'SAVE20'
    })
  });

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

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

  response = requests.post(
      'https://api.chariow.com/v1/checkout',
      headers={
          'Authorization': 'Bearer sk_live_your_api_key',
          'Content-Type': 'application/json'
      },
      json={
          'product_id': 'prd_abc123',
          'email': 'customer@example.com',
          'first_name': 'John',
          'last_name': 'Doe',
          'phone': {
              'number': '1234567890',
              'country_code': 'US'
          },
          'discount_code': 'SAVE20'
      }
  )
  ```
</CodeGroup>

### Paramètres de la requête

| Paramètre            | Type   | Requis | Description                                                                                                                                     |
| -------------------- | ------ | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `product_id`         | string | Oui    | ID public ou slug du produit (par ex., `prd_abc123xyz` ou `premium-course`)                                                                     |
| `email`              | string | Oui    | Adresse e-mail du client (max 255 caractères)                                                                                                   |
| `first_name`         | string | Oui    | Prénom du client (max 50 caractères)                                                                                                            |
| `last_name`          | string | Oui    | Nom de famille du client (max 50 caractères)                                                                                                    |
| `phone.number`       | string | Oui    | Numéro de téléphone (numérique uniquement)                                                                                                      |
| `phone.country_code` | string | Oui    | Code pays ISO (par ex., "US", "FR", "GB")                                                                                                       |
| `discount_code`      | string | Non    | Code de réduction à appliquer (max 100 caractères)                                                                                              |
| `campaign_id`        | string | Non    | ID public de campagne ou code de suivi                                                                                                          |
| `custom_fields`      | object | Non    | Valeurs de champs personnalisés (paires clé-valeur)                                                                                             |
| `payment_currency`   | string | Non    | Code de devise (ISO 4217, par ex., "USD", "EUR")                                                                                                |
| `redirect_url`       | string | Non    | URL de redirection personnalisée après finalisation du paiement (max 2048 caractères)                                                           |
| `custom_metadata`    | object | Non    | Métadonnées personnalisées clé-valeur à stocker avec la vente (max 10 clés, 255 caractères par valeur). Inclus dans les payloads webhook Pulse. |
| `customer_ip`        | string | Non    | L'adresse IP de l'acheteur, IPv4 ou IPv6 (par ex. « 203.0.113.42 »). Voir [Adresse IP de l'acheteur](#adresse-ip-de-lacheteur).                 |

### Champs d'adresse de livraison

Lorsque le produit a l'option "Exiger une adresse de livraison" activée, vous devez inclure les champs d'adresse de livraison dans votre requête de paiement :

| Paramètre | Type   | Requis       | Description                                            |
| --------- | ------ | ------------ | ------------------------------------------------------ |
| `address` | string | Conditionnel | Adresse postale pour la livraison (max 255 caractères) |
| `city`    | string | Conditionnel | Ville pour la livraison (max 100 caractères)           |
| `state`   | string | Conditionnel | État ou région pour la livraison (max 100 caractères)  |
| `country` | string | Conditionnel | Code pays (ISO 3166-1 alpha-2, par ex., "US", "FR")    |
| `zip`     | string | Conditionnel | Code postal pour la livraison (max 20 caractères)      |

<Info>
  Ces champs sont **requis** uniquement lorsque le produit a la livraison activée. Si la livraison n'est pas requise, ces champs sont ignorés.
</Info>

#### Exemple avec adresse de livraison

```json theme={null}
{
  "product_id": "prd_abc123xyz",
  "email": "customer@example.com",
  "first_name": "Jean",
  "last_name": "Dupont",
  "phone": {
    "number": "0612345678",
    "country_code": "FR"
  },
  "address": "123 Rue Principale",
  "city": "Paris",
  "state": "Île-de-France",
  "country": "FR",
  "zip": "75001"
}
```

## États de réponse du paiement

La réponse de paiement inclut un champ `step` indiquant l'état actuel :

### En attente de paiement

Pour les produits payants, vous recevrez une URL de paiement :

```json theme={null}
{
  "data": {
    "step": "payment",
    "message": null,
    "purchase": {
      "id": "sal_xyz789",
      "status": "awaiting_payment",
      "amount": {
        "value": 79.20,
        "formatted": "$79.20",
        "short": "79",
        "currency": "USD"
      }
    },
    "payment": {
      "checkout_url": "https://payment.chariow.com/checkout?token=abc123",
      "transaction_id": "txn_def456"
    }
  }
}
```

<Info>
  Redirigez le client vers `checkout_url` pour finaliser son paiement.
</Info>

### Finalisé (produits gratuits)

Pour les produits gratuits, la vente est finalisée immédiatement :

```json theme={null}
{
  "data": {
    "step": "completed",
    "message": null,
    "purchase": {
      "id": "sal_xyz789",
      "status": "completed"
    },
    "payment": {
      "checkout_url": null,
      "transaction_id": null
    }
  }
}
```

### Déjà acheté

Si le client possède déjà le produit :

```json theme={null}
{
  "data": {
    "step": "already_purchased",
    "message": "You have already purchased this product",
    "purchase": null,
    "payment": null
  }
}
```

## URL de redirection personnalisées

Vous pouvez spécifier une URL de redirection personnalisée pour envoyer les clients vers votre propre page de remerciement après finalisation du paiement :

```bash theme={null}
curl -X POST "https://api.chariow.com/v1/checkout" \
  -H "Authorization: Bearer sk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "product_id": "prd_abc123xyz",
    "email": "customer@example.com",
    "first_name": "John",
    "last_name": "Doe",
    "phone": {
      "number": "1234567890",
      "country_code": "US"
    },
    "redirect_url": "https://yoursite.com/thank-you?sale={sale_id}"
  }'
```

<Info>
  L'URL de redirection doit être une URL active valide (max 2048 caractères). Si non fournie, les clients seront redirigés vers la page post-achat Chariow par défaut.
</Info>

## Support multi-devises

Spécifiez la devise de paiement pour facturer les clients dans une devise différente de celle par défaut de votre boutique :

```json theme={null}
{
  "product_id": "prd_abc123xyz",
  "email": "customer@example.com",
  "first_name": "John",
  "last_name": "Doe",
  "phone": {
    "number": "1234567890",
    "country_code": "US"
  },
  "payment_currency": "EUR"
}
```

La réponse inclura les informations de taux de change lorsque la conversion de devise est appliquée.

## Application de codes de réduction

Transmettez un code de réduction pour appliquer des économies :

```json theme={null}
{
  "product_id": "prd_abc123xyz",
  "email": "customer@example.com",
  "first_name": "John",
  "last_name": "Doe",
  "phone": {
    "number": "1234567890",
    "country_code": "US"
  },
  "discount_code": "SAVE20"
}
```

La réponse affichera le montant réduit :

```json theme={null}
{
  "data": {
    "purchase": {
      "original_amount": {
        "value": 99,
        "formatted": "$99.00",
        "short": "99",
        "currency": "USD"
      },
      "amount": {
        "value": 79.20,
        "formatted": "$79.20",
        "short": "79",
        "currency": "USD"
      },
      "discount_amount": {
        "value": 19.80,
        "formatted": "$19.80",
        "short": "20",
        "currency": "USD"
      },
      "discount": {
        "id": "dis_xyz789",
        "code": "SAVE20",
        "type": "percentage",
        "value": 20
      }
    }
  }
}
```

## Champs personnalisés

Si votre produit a des champs personnalisés configurés, vous pouvez les collecter et les valider lors du paiement :

```json theme={null}
{
  "product_id": "prd_abc123xyz",
  "email": "customer@example.com",
  "first_name": "John",
  "last_name": "Doe",
  "phone": {
    "number": "1234567890",
    "country_code": "US"
  },
  "custom_fields": {
    "company_name": "Acme Corp",
    "job_title": "Developer",
    "team_size": "10-50"
  }
}
```

<Info>
  Les champs personnalisés doivent correspondre aux définitions de champs personnalisés configurées du produit. Les champs personnalisés invalides ou requis manquants entraîneront des erreurs de validation.
</Info>

## Suivi de campagne

Suivez la source des ventes en incluant un ID de campagne :

```json theme={null}
{
  "product_id": "prd_abc123xyz",
  "email": "customer@example.com",
  "first_name": "John",
  "last_name": "Doe",
  "phone": {
    "number": "1234567890",
    "country_code": "US"
  },
  "campaign_id": "camp_summer2024"
}
```

Cela vous aide à :

* Suivre quelles campagnes marketing génèrent le plus de ventes
* Attribuer les revenus à des canaux spécifiques
* Analyser les performances des campagnes dans votre tableau de bord Chariow

## Métadonnées personnalisées

Stockez des données personnalisées avec la vente pour vos propres besoins de suivi et d'intégration :

```json theme={null}
{
  "product_id": "prd_abc123xyz",
  "email": "customer@example.com",
  "first_name": "Jean",
  "last_name": "Dupont",
  "phone": {
    "number": "0612345678",
    "country_code": "FR"
  },
  "custom_metadata": {
    "order_ref": "ORD-123",
    "source": "landing_page",
    "utm_campaign": "summer_sale"
  }
}
```

### Notes importantes

* Maximum 10 clés autorisées par vente
* Chaque valeur est limitée à 255 caractères
* Les clés doivent être des chaînes avec des caractères alphanumériques et des underscores
* Les métadonnées personnalisées sont incluses dans les payloads webhook Pulse

<Tip>
  Utilisez les métadonnées personnalisées pour lier les ventes Chariow à votre CRM, plateforme d'analyse ou systèmes internes. Les métadonnées sont retournées dans tous les webhooks liés aux ventes.
</Tip>

## Adresse IP de l'acheteur

Le endpoint de paiement est appelé depuis votre serveur : l'adresse IP que nous observons est donc celle de votre infrastructure, pas celle de l'acheteur. Transmettez l'IP de l'acheteur dans `customer_ip` pour corriger cela :

```json theme={null}
{
  "product_id": "prd_abc123xyz",
  "email": "customer@example.com",
  "first_name": "Jean",
  "last_name": "Dupont",
  "phone": {
    "number": "0612345678",
    "country_code": "FR"
  },
  "customer_ip": "203.0.113.42"
}
```

Récupérez l'IP de l'acheteur depuis la requête qui arrive sur votre propre serveur, généralement la première valeur de l'en-tête `X-Forwarded-For`, ou `CF-Connecting-IP` si vous êtes derrière Cloudflare.

### Ce que cela améliore

* **Moyens de paiement** — le pays de l'acheteur est déterminé à partir de cette IP, et ce pays conditionne les moyens de paiement affichés sur la page de paiement
* **Analyses** — les ventes sont attribuées au pays de l'acheteur plutôt qu'à la région d'hébergement de votre serveur
* **Contrôle des fraudes** — la vente conserve la véritable IP de l'acheteur

### Notes importantes

* Le champ est facultatif. Si vous l'omettez, nous retombons sur l'IP appelante, exactement comme avant
* Les formats IPv4 et IPv6 sont acceptés ; une valeur invalide renvoie une erreur `422`
* Le champ n'est pris en compte que sur les paiements via l'API, il ne peut donc pas être falsifié depuis un navigateur

## Gestion des erreurs

Erreurs de paiement courantes et comment les gérer :

| Statut HTTP | Erreur                             | Cause                                                                      | Solution                                                                          |
| ----------- | ---------------------------------- | -------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| 401         | Non autorisé                       | Clé API invalide ou manquante                                              | Vérifiez que votre clé API est correcte et incluse dans l'en-tête `Authorization` |
| 404         | Produit non trouvé                 | ID de produit invalide ou produit non publié                               | Vérifiez que l'ID/slug du produit existe et est publié                            |
| 422         | Échec de validation                | Champs requis manquants ou invalides                                       | Vérifiez que tous les champs requis sont fournis avec les formats corrects        |
| 422         | Prix libre non pris en charge      | Le produit utilise la tarification à prix libre                            | Redirigez les clients vers votre boutique Chariow ou utilisez le widget Snap      |
| 422         | Type de produit non pris en charge | Le produit est de type Service ou Coaching                                 | Redirigez les clients vers votre boutique Chariow ou utilisez le widget Snap      |
| 422         | Code de réduction invalide         | Code de réduction expiré, invalide ou déjà utilisé                         | Vérifiez que le code de réduction est actif et applicable                         |
| 422         | Adresse de livraison manquante     | Le produit requiert une livraison mais les champs d'adresse sont manquants | Incluez les champs `address`, `city`, `state`, `country` et `zip`                 |

### Exemple de réponse d'erreur

```json theme={null}
{
  "message": "The email field must be a valid email address.",
  "data": [],
  "errors": {
    "email": [
      "The email field must be a valid email address."
    ],
    "phone.number": [
      "The phone.number field is required."
    ]
  }
}
```

<Tip>
  Vérifiez toujours l'objet `errors` pour les messages de validation spécifiques aux champs afin d'aider les utilisateurs à corriger leurs saisies.
</Tip>

## Bonnes pratiques

### Gérer tous les états de réponse

Vérifiez toujours le champ `step` et gérez tous les états possibles :

```javascript theme={null}
const response = await fetch('https://api.chariow.com/v1/checkout', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sk_live_your_api_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(checkoutData)
});

const result = await response.json();

switch (result.data.step) {
  case 'payment':
    // Rediriger vers l'URL de paiement
    window.location.href = result.data.payment.checkout_url;
    break;

  case 'completed':
    // Afficher le message de succès pour les produits gratuits
    showSuccessMessage(result.data.purchase);
    break;

  case 'already_purchased':
    // Informer le client qu'il possède déjà ce produit
    showAlreadyPurchasedMessage(result.data.message);
    break;
}
```

### Utiliser les Pulses pour les mises à jour de vente

Ne vous fiez pas uniquement aux URL de redirection pour suivre la finalisation des ventes. Configurez les Pulses (webhooks) pour recevoir des notifications fiables :

* Vente finalisée
* Paiement reçu
* Remboursement traité

Consultez le [Guide des Pulses](/fr/guides/pulses) pour les instructions de configuration.

### Valider avant le paiement

Réduisez les paiements échoués en validant les données avant d'appeler l'API :

* Validation du format e-mail
* Validation du format du numéro de téléphone
* Vérifications des champs requis
* Validation des champs personnalisés

### Gérer les erreurs réseau

Implémentez une gestion appropriée des erreurs pour les problèmes réseau :

```javascript theme={null}
try {
  const response = await fetch('https://api.chariow.com/v1/checkout', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer sk_live_your_api_key',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(checkoutData)
  });

  if (!response.ok) {
    const error = await response.json();
    handleCheckoutError(error);
    return;
  }

  const data = await response.json();
  handleCheckoutSuccess(data);

} catch (error) {
  // Gérer les erreurs réseau
  console.error('Checkout failed:', error);
  showErrorMessage('Impossible de traiter le paiement. Veuillez réessayer.');
}
```

### Stocker les ID de vente

Stockez toujours l'ID de vente retourné (`purchase.id`) pour :

* Les demandes du service client
* Le traitement des remboursements
* La gestion des accès
* Le suivi analytique

### Tester avec différents scénarios

Testez votre intégration avec :

* Des produits gratuits (finalisation immédiate)
* Des produits payants (flux de paiement)
* Des produits avec codes de réduction
* Des produits avec champs personnalisés
* Des ID de produit invalides
* Des codes de réduction invalides

## Prochaines étapes

<CardGroup cols={2}>
  <Card title="Guide des ventes" icon="receipt" href="/fr/guides/sales">
    Apprenez à récupérer et gérer les ventes
  </Card>

  <Card title="Pulses" icon="webhook" href="/fr/guides/pulses">
    Configurez les notifications pour les ventes finalisées
  </Card>

  <Card title="API Checkout" icon="code" href="/api-reference/checkout/init-checkout">
    Consultez la référence complète de l'API Checkout
  </Card>
</CardGroup>
