---
title: "Gérer les événements de flow et de paywall - Unity"
description: "Gérez les événements de flow et de paywall dans votre application Unity."
---

:::important
Ce guide couvre la gestion des événements pour les achats, les restaurations, la sélection de produits et le rendu des flows. Vous devez également implémenter la gestion des boutons (fermeture du flow, ouverture de liens, etc.). Consultez notre [guide sur la gestion des actions de flow](unity-handle-paywall-actions) pour plus de détails.
:::

Les flows et paywalls configurés avec le [Flow Builder](adapty-flow-builder) ou le [Paywall Builder](adapty-paywall-builder) n'ont pas besoin de code supplémentaire pour effectuer et restaurer des achats. Cependant, ils génèrent certains événements auxquels votre application peut réagir. Ces événements comprennent les pressions sur des boutons (boutons de fermeture, URLs, sélections de produits, etc.) ainsi que des notifications sur les actions liées aux achats. Découvrez ci-dessous comment réagir à ces événements.

:::tip

Vous souhaitez voir un exemple concret d'intégration du SDK Adapty dans une application mobile ? Consultez nos [exemples d'applications](sample-apps), qui illustrent la configuration complète, notamment l'affichage des paywalls, les achats et d'autres fonctionnalités de base.

:::

## Gestion des événements \{#handling-events\}

Pour contrôler ou surveiller les processus qui se déroulent sur l'écran du flow dans votre application mobile, implémentez l'interface `IAdaptyFlowsEventsListener` et enregistrez-la avec `Adapty.SetFlowsEventsListener()` :

```csharp showLineNumbers title="Unity"
using UnityEngine;
using AdaptySDK;

public class FlowEventsHandler : MonoBehaviour, IAdaptyFlowsEventsListener
{
    void Start()
    {
        Adapty.SetFlowsEventsListener(this);
    }

    // Implement all interface methods below
}
```

:::note
Ces méthodes sont l'endroit où vous ajoutez votre logique personnalisée pour répondre aux événements du flow. Le SDK n'applique aucun comportement par défaut : un achat réussi ou une erreur ne ferme pas la vue automatiquement — appelez `view.Dismiss(...)` vous-même au moment opportun.
:::

### Événements générés par l'utilisateur \{#user-generated-events\}

#### Flow apparu \{#flow-appeared\}

Invoqué lorsque la vue du flow s'affiche à l'écran.

:::note
Sur iOS, également invoqué lorsqu'un utilisateur appuie sur le [bouton de paywall web](web-paywall#step-2a-add-a-web-purchase-button) dans un flow, et qu'un paywall web s'ouvre dans un navigateur intégré.
:::

```csharp showLineNumbers title="Unity"
public void FlowViewDidAppear(AdaptyUIFlowView view) { }
```

#### Flow disparu \{#flow-disappeared\}

Invoqué lorsque la vue du flow est fermée depuis l'écran.

:::note
Sur iOS, également invoqué lorsqu'un [paywall web](web-paywall#step-2a-add-a-web-purchase-button) ouvert depuis un flow dans un navigateur intégré disparaît de l'écran.
:::

```csharp showLineNumbers title="Unity"
public void FlowViewDidDisappear(AdaptyUIFlowView view) { }
```

#### Sélection de produit \{#product-selection\}

Invoqué lorsqu'un produit est sélectionné pour achat (par l'utilisateur ou par le système).

```csharp showLineNumbers title="Unity"
public void FlowViewDidSelectProduct(
    AdaptyUIFlowView view,
    string productId
) { }
```

<Details>
<summary>Exemple d'événement (cliquer pour développer)</summary>

```javascript
{
  "productId": "premium_monthly"
}
```
</Details>

#### Achat démarré \{#started-purchase\}

Invoqué lorsqu'un utilisateur lance le processus d'achat.

```csharp showLineNumbers title="Unity"
public void FlowViewDidStartPurchase(
    AdaptyUIFlowView view,
    AdaptyPaywallProduct product
) { }
```

:::note
En [mode Observer](unity-present-flows-in-observer-mode), les achats démarrés depuis un flow sont transmis à votre `IAdaptyUIObserverModeResolver` à la place.
:::

<Details>
<summary>Exemple d'événement (Cliquer pour développer)</summary>

```javascript
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}
```
</Details>

#### Achat réussi, annulé ou en attente \{#successful-canceled-or-pending-purchase\}

Si l'achat réussit, que l'utilisateur annule son achat, ou que l'achat est en attente, cette méthode sera invoquée. Les annulations de l'utilisateur et les paiements en attente (par exemple, approbation parentale requise) déclenchent cette méthode, et non `FlowViewDidFailPurchase`.

Le flow reste ouvert après l'achat jusqu'à ce que vous le fermiez vous-même, alors appelez `view.Dismiss(...)` dès que l'utilisateur obtient l'accès :

```csharp showLineNumbers title="Unity"
public void FlowViewDidFinishPurchase(
    AdaptyUIFlowView view,
    AdaptyPaywallProduct product,
    AdaptyPurchaseResult purchasedResult
) {
    switch (purchasedResult.Type) {
        case AdaptyPurchaseResultType.Success:
            // Check if user has access to premium features
            if (purchasedResult.Profile != null
                && purchasedResult.Profile.AccessLevels.TryGetValue("premium", out var premium)
                && premium.IsActive) {
                view.Dismiss(null);
            }
            break;
        case AdaptyPurchaseResultType.Pending:
            // Handle pending purchase (e.g., user will pay offline with cash)
            break;
        case AdaptyPurchaseResultType.UserCancelled:
            // Handle user cancellation
            break;
        default:
            break;
    }
}
```

<Details>
<summary>Exemples d'événements (cliquez pour développer)</summary>

```javascript
// Successful purchase
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  },
  "purchaseResult": {
    "type": "Success",
    "profile": {
      "accessLevels": {
        "premium": {
          "id": "premium",
          "isActive": true,
          "expiresAt": "2024-02-15T10:30:00Z"
        }
      }
    }
  }
}

// Cancelled purchase
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  },
  "purchaseResult": {
    "type": "UserCancelled"
  }
}

// Pending purchase
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  },
  "purchaseResult": {
    "type": "Pending"
  }
}
```
</Details>

Nous recommandons de fermer l'écran du flow en cas d'achat réussi.

#### Échec d'achat \{#failed-purchase\}

Si un achat échoue en raison d'une erreur, cette méthode sera appelée. Cela inclut les erreurs StoreKit/Google Play Billing (restrictions de paiement, produits invalides, échecs réseau), les échecs de vérification de transaction et les erreurs système. Notez que les annulations par l'utilisateur déclenchent `FlowViewDidFinishPurchase` avec un résultat annulé, et les paiements en attente ne déclenchent pas cette méthode.

```csharp showLineNumbers title="Unity"
public void FlowViewDidFailPurchase(
    AdaptyUIFlowView view,
    AdaptyPaywallProduct product,
    AdaptyError error
) { }
```

<Details>
<summary>Exemple d'événement (Cliquez pour développer)</summary>

```javascript
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  },
  "error": {
    "code": "purchase_failed",
    "message": "Purchase failed due to insufficient funds",
    "details": {
      "underlyingError": "Insufficient funds in account"
    }
  }
}
```
</Details>

#### Restauration démarrée \{#started-restore\}

Déclenché lorsqu'un utilisateur lance le processus de restauration :

```csharp showLineNumbers title="Unity"
public void FlowViewDidStartRestore(AdaptyUIFlowView view) { }
```

#### Restauration réussie \{#successful-restore\}

Appelé lorsque la restauration des achats réussit. Le flow reste ouvert après la restauration jusqu'à ce que vous le fermiez :

```csharp showLineNumbers title="Unity"
public void FlowViewDidFinishRestore(
    AdaptyUIFlowView view,
    AdaptyProfile profile
) {
    // Check if user has access to premium features
    if (profile.AccessLevels.TryGetValue("premium", out var premium) && premium.IsActive) {
        view.Dismiss(null);
    }
}
```

<Details>
<summary>Exemple d'événement (cliquer pour développer)</summary>

```javascript
{
  "profile": {
    "accessLevels": {
      "premium": {
        "id": "premium",
        "isActive": true,
        "expiresAt": "2024-02-15T10:30:00Z"
      }
    },
    "subscriptions": [
      {
        "vendorProductId": "premium_monthly",
        "isActive": true,
        "expiresAt": "2024-02-15T10:30:00Z"
      }
    ]
  }
}
```
</Details>

Nous recommandons de fermer l'écran si l'utilisateur possède le `accessLevel` requis. Consultez la rubrique [Statut de l'abonnement](unity-listen-subscription-changes) pour savoir comment le vérifier.

#### Échec de la restauration \{#failed-restore\}

Invoqué lorsque la restauration des achats échoue :

```csharp showLineNumbers title="Unity"
public void FlowViewDidFailRestore(
    AdaptyUIFlowView view,
    AdaptyError error
) { }
```

<Details>
<summary>Exemple d'événement (Cliquez pour développer)</summary>

```javascript
{
  "error": {
    "code": "restore_failed",
    "message": "Purchase restoration failed",
    "details": {
      "underlyingError": "No previous purchases found"
    }
  }
}
```
</Details>

#### Navigation de paiement web terminée \{#finished-web-payment-navigation\}

Après une tentative d'ouverture d'un [paywall web](web-paywall) pour un achat (qu'elle ait réussi ou échoué), cette méthode sera invoquée :

```csharp showLineNumbers title="Unity"
public void FlowViewDidFinishWebPaymentNavigation(
    AdaptyUIFlowView view,
    AdaptyPaywallProduct product,
    AdaptyError error
) { }
```

**Paramètres :**
- `product` : Le produit pour lequel le paywall web a été ouvert (ou tenté), ou `null`
- `error` : `null` si le paywall web s'est ouvert avec succès, ou un `AdaptyError` en cas d'échec

<Details>
<summary>Exemples d'événements (Cliquez pour développer)</summary>

```javascript
// Successful navigation
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  },
  "error": null
}

// Failed navigation
{
  "product": null,
  "error": {
    "code": "wrong_param",
    "message": "Current method is not available for this product",
    "details": {
      "underlyingError": "Product not configured for web purchases"
    }
  }
}
```
</Details>

### Récupération et rendu des données \{#data-fetching-and-rendering\}

#### Erreurs de chargement des produits \{#product-loading-errors\}

Déclenché quand le chargement des produits échoue et fournit une `AdaptyError`. Si vous n'avez pas passé le tableau de produits lors de l'initialisation, AdaptyUI récupérera lui-même les objets nécessaires auprès du serveur. Cette opération peut échouer, et AdaptyUI signalera l'erreur en appelant cette méthode :

```csharp showLineNumbers title="Unity"
public void FlowViewDidFailLoadingProducts(
    AdaptyUIFlowView view,
    AdaptyError error
) { }
```

<Details>
<summary>Exemple d'événement (Cliquer pour agrandir)</summary>

```javascript
{
  "error": {
    "code": "products_loading_failed",
    "message": "Failed to load products from the server",
    "details": {
      "underlyingError": "Network timeout"
    }
  }
}
```
</Details>

#### Erreurs de rendu et d'exécution \{#rendering-and-runtime-errors\}

Si une erreur survient lors du rendu de l'interface, ou qu'une autre erreur d'exécution non liée à un achat se produit, elle sera signalée par cette méthode. La vue n'est pas fermée automatiquement — appelez `view.Dismiss(...)` vous-même si nécessaire :

```csharp showLineNumbers title="Unity"
public void FlowViewDidReceiveError(
    AdaptyUIFlowView view,
    AdaptyError error
) { }
```

<Details>
<summary>Exemple d'événement (Cliquez pour développer)</summary>

```javascript
{
  "error": {
    "code": "rendering_failed",
    "message": "Failed to render flow interface",
    "details": {
      "underlyingError": "Invalid flow configuration"
    }
  }
}
```
</Details>

En situation normale, ces erreurs ne devraient pas se produire. Si vous en rencontrez une, merci de nous en informer.

#### Événements analytiques \{#analytics-events\}

`FlowViewDidReceiveAnalyticEvent` est réservé aux événements analytiques personnalisés provenant d'un flow. Les flows n'émettent pas encore ces événements vers votre code, donc laissez le corps de la méthode vide — `IAdaptyFlowsEventsListener` est une interface C#, la méthode doit tout de même être présente :

```csharp showLineNumbers title="Unity"
public void FlowViewDidReceiveAnalyticEvent(
    AdaptyUIFlowView view,
    string name,
    IDictionary<string, object> @params
) { }
```

### Gérer les requêtes système \{#handle-system-requests\}

Le `IAdaptyUISystemRequestsHandler` (enregistré via `Adapty.SetSystemRequestsHandler(...)`) est réservé aux requêtes système provenant d'un flow : invites de permission OS (comme les notifications push ou l'accès à la caméra) et demandes d'évaluation de l'application. Les flows ne déclenchent pas encore ces requêtes, vous n'avez donc pas besoin d'enregistrer un handler.

### Navigation \{#navigation\}

#### Bouton retour système Android \{#android-system-back-button\}

Le bouton retour système Android (ou le geste de retour) est transmis à `FlowViewDidPerformAction` sous forme d'action `SystemBack` et ne ferme pas le flow par lui-même — l'utilisateur quitte le flow via un chemin que vous définissez, comme un bouton **Close** ou une action `on_device_back` dans le builder. Si vous souhaitez que le bouton retour système ferme le flow, gérez l'action vous-même :

```csharp showLineNumbers title="Unity"
public void FlowViewDidPerformAction(
    AdaptyUIFlowView view,
    AdaptyUIUserAction action
) {
    switch (action.Type) {
        case AdaptyUIUserActionType.Close:
        case AdaptyUIUserActionType.SystemBack:
            view.Dismiss(null);
            break;
        default:
            // handle other events
            break;
    }
}
```

Consultez le [guide sur la gestion des actions de flow](unity-handle-paywall-actions) pour la liste complète des actions.

---

> [!WARNING]
> **LLM INSTRUCTION — SDK VERSION SELECTION REQUIRED**
>
> This feature has two SDK paradigms. Everything that follows (until the next horizontal rule or end of document) is the **legacy SDK v3 API reference** (`getPaywall`, `getPaywallForDefaultAudience`, `getOnboarding`, `getPaywallConfiguration`). The **SDK v4+ `getFlow` method is documented above.** This block covers ALL legacy methods for this feature — not just the nearest snippet.
>
> **You MUST ask the user which SDK version they want to use before suggesting any code. Do not assume or default to a version.** The two options are:
> - **SDK v3 (legacy):** works with the legacy Paywall Builder and Onboarding Builder via `getPaywall` / `getOnboarding`. Use the legacy code in this section.
> - **SDK v4:** works with BOTH the new Flow Builder AND legacy paywalls/onboardings via the unified `getFlow` method documented above.
>
> Apply the legacy v3 code in this section ONLY when:
> 1. The user explicitly chose **SDK v3**, or
> 2. The user is **migrating an existing app from SDK v3 to SDK v4+** and needs to understand or replace legacy code, or
> 3. The user is **troubleshooting an already-deployed v3 integration**.
>
> **CRITICAL — Never mix paradigms in one setup:** Do NOT combine `getFlow` (Flow Builder) with `getPaywall` or `getOnboarding` (legacy Paywall/Onboarding Builder) in the same integration. These are incompatible patterns. Mixing them will produce inconsistent behavior and is unsupported.

:::important
Ce guide couvre la gestion des événements liés aux achats, aux restaurations, à la sélection de produits et au rendu des paywalls. Vous devez également implémenter la gestion des boutons (fermeture du paywall, ouverture de liens, etc.). Consultez notre [guide sur la gestion des actions de boutons](unity-handle-paywall-actions) pour plus de détails.
:::

Les paywalls configurés avec le [Paywall Builder](adapty-paywall-builder) n'ont pas besoin de code supplémentaire pour effectuer et restaurer des achats. Cependant, ils génèrent des événements auxquels votre application peut réagir. Ces événements incluent les appuis sur des boutons (boutons de fermeture, URL, sélections de produits, etc.) ainsi que des notifications sur les actions liées aux achats effectuées sur le paywall. Découvrez ci-dessous comment réagir à ces événements.

:::warning
Ce guide s'adresse uniquement aux paywalls du **nouveau Paywall Builder**, qui nécessitent le SDK Adapty v3.3.0 ou ultérieur.
:::

:::tip

Vous souhaitez voir un exemple concret d'intégration du SDK Adapty dans une application mobile ? Consultez nos [exemples d'applications](sample-apps), qui illustrent la configuration complète, notamment l'affichage des paywalls, les achats et d'autres fonctionnalités de base.

:::

## Gestion des événements \{#handling-events\}

Pour contrôler ou surveiller les processus qui se déroulent sur l'écran du paywall dans votre application mobile, implémentez l'interface `AdaptyPaywallsEventsListener` :

```csharp showLineNumbers title="Unity"
using UnityEngine;
using AdaptySDK;

public class PaywallEventsHandler : MonoBehaviour, AdaptyPaywallsEventsListener
{
    void Start()
    {
        Adapty.SetPaywallsEventsListener(this);
    }

    // Implement all required interface methods below
}
```

### Événements générés par l'utilisateur \{#user-generated-events\}

#### Paywall apparu \{#paywall-appeared\}

Déclenché lorsque la vue du paywall s'affiche à l'écran.

:::note
Sur iOS, également déclenché lorsqu'un utilisateur appuie sur le [bouton de paywall web](web-paywall#step-2a-add-a-web-purchase-button) à l'intérieur d'un paywall, et qu'un paywall web s'ouvre dans un navigateur intégré à l'application.
:::

```csharp showLineNumbers title="Unity"
public void PaywallViewDidAppear(AdaptyUIPaywallView view) { }
```

#### Paywall disparu \{#paywall-disappeared\}

Déclenché lorsque la vue du paywall est fermée et disparaît de l'écran.

:::note
Sur iOS, également invoqué lorsqu'un [web paywall](web-paywall#step-2a-add-a-web-purchase-button) ouvert depuis un paywall dans un navigateur intégré disparaît de l'écran.
:::

```csharp showLineNumbers title="Unity"
public void PaywallViewDidDisappear(AdaptyUIPaywallView view) { }
```

#### Sélection de produit \{#product-selection\}

Invoqué lorsqu'un produit est sélectionné pour achat (par l'utilisateur ou par le système).

```csharp showLineNumbers title="Unity"
public void PaywallViewDidSelectProduct(
    AdaptyUIPaywallView view, 
    string productId
) { }
```

<Details>
<summary>Exemple d'événement (Cliquer pour développer)</summary>

```javascript
{
  "productId": "premium_monthly"
}
```
</Details>

#### Achat démarré \{#started-purchase\}

Invoqué lorsqu'un utilisateur lance le processus d'achat.

```csharp showLineNumbers title="Unity"
public void PaywallViewDidStartPurchase(
    AdaptyUIPaywallView view, 
    AdaptyPaywallProduct product
) { }
```

<Details>
<summary>Exemple d'événement (Cliquez pour développer)</summary>

```javascript
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}
```
</Details>

#### Achat réussi, annulé ou en attente \{#successful-canceled-or-pending-purchase\}

Si l'achat réussit, si l'utilisateur l'annule, ou si l'achat est en attente, cette méthode sera invoquée. Les annulations par l'utilisateur et les paiements en attente (par exemple, approbation parentale requise) déclenchent cette méthode, et non `PaywallViewDidFailPurchase`.

```csharp showLineNumbers title="Unity"
public void PaywallViewDidFinishPurchase(
    AdaptyUIPaywallView view, 
    AdaptyPaywallProduct product, 
    AdaptyPurchaseResult purchasedResult
) { }
```

<Details>
<summary>Exemples d'événements (cliquez pour développer)</summary>

```javascript
// Successful purchase
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  },
  "purchaseResult": {
    "type": "Success",
    "profile": {
      "accessLevels": {
        "premium": {
          "id": "premium",
          "isActive": true,
          "expiresAt": "2024-02-15T10:30:00Z"
        }
      }
    }
  }
}

// Cancelled purchase
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  },
  "purchaseResult": {
    "type": "UserCancelled"
  }
}

// Pending purchase
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  },
  "purchaseResult": {
    "type": "Pending"
  }
}
```
</Details>

Nous vous recommandons de fermer l'écran dans ce cas.

#### Échec d'achat \{#failed-purchase\}

Si un achat échoue en raison d'une erreur, cette méthode sera invoquée. Cela inclut les erreurs StoreKit/Google Play Billing (restrictions de paiement, produits invalides, échecs réseau), les échecs de vérification des transactions et les erreurs système. Notez que les annulations de l'utilisateur déclenchent `PaywallViewDidFinishPurchase` avec un résultat annulé, et les paiements en attente ne déclenchent pas cette méthode.

```csharp showLineNumbers title="Unity"
public void PaywallViewDidFailPurchase(
    AdaptyUIPaywallView view, 
    AdaptyPaywallProduct product, 
    AdaptyError error
) { }
```

<Details>
<summary>Exemple d'événement (Cliquez pour développer)</summary>

```javascript
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  },
  "error": {
    "code": "purchase_failed",
    "message": "Purchase failed due to insufficient funds",
    "details": {
      "underlyingError": "Insufficient funds in account"
    }
  }
}
```
</Details>

#### Restauration démarrée \{#started-restore\}

Déclenché lorsqu'un utilisateur lance le processus de restauration :

```csharp showLineNumbers title="Unity"
public void PaywallViewDidStartRestore(AdaptyUIPaywallView view) { }
```

#### Restauration réussie \{#successful-restore\}

Invoqué lorsque la restauration des achats réussit :

```csharp showLineNumbers title="Unity"
public void PaywallViewDidFinishRestore(
    AdaptyUIPaywallView view, 
    AdaptyProfile profile
) { }
```

<Details>
<summary>Exemple d'événement (Cliquez pour développer)</summary>

```javascript
{
  "profile": {
    "accessLevels": {
      "premium": {
        "id": "premium",
        "isActive": true,
        "expiresAt": "2024-02-15T10:30:00Z"
      }
    },
    "subscriptions": [
      {
        "vendorProductId": "premium_monthly",
        "isActive": true,
        "expiresAt": "2024-02-15T10:30:00Z"
      }
    ]
  }
}
```
</Details>

Nous vous recommandons de fermer l'écran si l'utilisateur possède le `accessLevel` requis. Consultez la rubrique [Statut de l'abonnement](unity-listen-subscription-changes) pour savoir comment le vérifier.

#### Échec de la restauration \{#failed-restore\}

Déclenché en cas d'échec de la restauration des achats :

```csharp showLineNumbers title="Unity"
public void PaywallViewDidFailRestore(
    AdaptyUIPaywallView view, 
    AdaptyError error
) { }
```

<Details>
<summary>Exemple d'événement (cliquer pour développer)</summary>

```javascript
{
  "error": {
    "code": "restore_failed",
    "message": "Purchase restoration failed",
    "details": {
      "underlyingError": "No previous purchases found"
    }
  }
}
```
</Details>

#### Navigation web de paiement terminée \{#finished-web-payment-navigation\}

Après avoir tenté d'ouvrir un [paywall web](web-paywall) pour un achat (qu'il ait réussi ou échoué), cette méthode sera invoquée :

```csharp showLineNumbers title="Unity"
public void PaywallViewDidFinishWebPaymentNavigation(
    AdaptyUIPaywallView view, 
    AdaptyPaywallProduct product, 
    AdaptyError error
) { }
```

**Paramètres :**
- `product` : Le produit pour lequel le paywall web a été ouvert (ou tenté)
- `error` : `null` si le paywall web s'est ouvert avec succès, ou une `AdaptyError` en cas d'échec

<Details>
<summary>Exemples d'événements (Cliquez pour développer)</summary>

```javascript
// Successful navigation
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  },
  "error": null
}

// Failed navigation
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  },
  "error": {
    "code": "wrong_param",
    "message": "Current method is not available for this product",
    "details": {
      "underlyingError": "Product not configured for web purchases"
    }
  }
}
```
</Details>

### Récupération et rendu des données \{#data-fetching-and-rendering\}

#### Erreurs de chargement des produits \{#product-loading-errors\}

Déclenché quand le chargement des produits échoue et fournit une `AdaptyError`. Si vous n'avez pas transmis le tableau de produits lors de l'initialisation, AdaptyUI récupèrera lui-même les objets nécessaires depuis le serveur. Cette opération peut échouer, et AdaptyUI signalera l'erreur en invoquant cette méthode :

```csharp showLineNumbers title="Unity"
public void PaywallViewDidFailLoadingProducts(
    AdaptyUIPaywallView view, 
    AdaptyError error
) { }
```

<Details>
<summary>Exemple d'événement (Cliquez pour développer)</summary>

```javascript
{
  "error": {
    "code": "products_loading_failed",
    "message": "Failed to load products from the server",
    "details": {
      "underlyingError": "Network timeout"
    }
  }
}
```
</Details>

#### Erreurs de rendu \{#rendering-errors\}

Invoqué lorsqu'une erreur survient pendant le rendu de l'interface et fournit `AdaptyError` :

```csharp showLineNumbers title="Unity"
public void PaywallViewDidFailRendering(
    AdaptyUIPaywallView view, 
    AdaptyError error
) { }
```

<Details>
<summary>Exemple d'événement (Cliquez pour développer)</summary>

```javascript
{
  "error": {
    "code": "rendering_failed",
    "message": "Failed to render paywall interface",
    "details": {
      "underlyingError": "Invalid paywall configuration"
    }
  }
}
```
</Details>

Dans une situation normale, de telles erreurs ne devraient pas se produire, donc si vous en rencontrez une, veuillez nous en informer.

---