---
title: "Flutter - Обработка событий флоу и пейвола"
description: "Узнайте, как обрабатывать события, связанные с подпиской, во Flutter с помощью Adapty для эффективного отслеживания взаимодействий пользователей."
---

:::important
Это руководство охватывает обработку событий покупок, восстановлений, выбора продукта и рендеринга. Закрытие экрана и открытие ссылок обрабатываются реализацией `flowViewDidPerformAction` по умолчанию — см. наш [гайд по обработке действий кнопок](flutter-handle-paywall-actions), чтобы переопределить их или обработать пользовательские действия кнопок.
:::
Флоу и пейволы, настроенные с помощью билдера, не требуют дополнительного кода для совершения и восстановления покупок. Однако они генерируют события, на которые ваше приложение может реагировать. К таким событиям относятся нажатия кнопок (кнопки закрытия, URL, выбор продуктов и т. д.), а также уведомления о действиях, связанных с покупками, выполненных во флоу или пейволе. Ниже описано, как обрабатывать эти события.

Чтобы управлять процессами, происходящими на экране флоу или пейвола в вашем мобильном приложении, или отслеживать их, реализуйте методы `AdaptyUIFlowsEventsObserver` и установите наблюдатель перед отображением любого экрана:
```dart showLineNumbers title="Flutter"
AdaptyUI().setFlowsEventsObserver(this);
```

Три метода наблюдателя **обязательны** — без них класс не скомпилируется: `flowViewDidFinishPurchase`, `flowViewDidFinishRestore` и `flowViewDidReceiveError`. Остальные методы опциональны. Чтобы отвязать ранее установленный наблюдатель, передайте `null` в `setFlowsEventsObserver`.

:::tip

Хотите увидеть реальный пример интеграции Adapty SDK в мобильное приложение? Посмотрите наши [примеры приложений](sample-apps) — они демонстрируют полную настройку: отображение пейволов, совершение покупок и другие базовые функции.

:::

В примерах событий ниже показаны свойства, доступные для каждого объекта, с поясняющими значениями в комментариях.
### События, генерируемые пользователем \{#user-generated-events\}

#### Отображение вью \{#view-appeared\}

Этот метод вызывается, когда флоу или вью пейвола появляется на экране.

:::note
На iOS также вызывается, когда пользователь нажимает [кнопку веб-пейвола](web-paywall#step-2a-add-a-web-purchase-button) внутри пейвола и веб-пейвол открывается во встроенном браузере.
:::

```dart showLineNumbers title="Flutter"
void flowViewDidAppear(AdaptyUIFlowView view) {
}
```

#### Скрытие вью \{#view-disappeared\}

Этот метод вызывается, когда флоу или вью пейвола убирается с экрана.
:::note
На iOS также вызывается, когда [веб-пейвол](web-paywall#step-2a-add-a-web-purchase-button), открытый из пейвола во встроенном браузере, исчезает с экрана.
:::

```dart showLineNumbers title="Flutter"
void flowViewDidDisappear(AdaptyUIFlowView view) {
}
```

#### Выбор продукта \{#product-selection\}

Если продукт выбран для покупки (пользователем или системой), будет вызван следующий метод:

```dart showLineNumbers title="Flutter"
void flowViewDidSelectProduct(AdaptyUIFlowView view, String productId) {
}
```

<Details>
<summary>Пример события (нажмите, чтобы развернуть)</summary>
```dart
void flowViewDidSelectProduct(AdaptyUIFlowView view, String productId) {
  // productId is a String:
  productId; // 'premium_monthly'
}
```
</Details>

#### Начало покупки \{#started-purchase\}

Если пользователь инициирует процесс покупки, будет вызван этот метод:

```dart showLineNumbers title="Flutter"
void flowViewDidStartPurchase(AdaptyUIFlowView view, AdaptyPaywallProduct product) {
}
```

<Details>
<summary>Пример события (нажмите, чтобы развернуть)</summary>
```dart
void flowViewDidStartPurchase(AdaptyUIFlowView view, AdaptyPaywallProduct product) {
  // product — AdaptyPaywallProduct:
  product.vendorProductId;        // 'premium_monthly'
  product.localizedTitle;         // 'Premium Monthly'
  product.localizedDescription;   // 'Premium subscription for 1 month'
  product.price.amount;           // 9.99            (double)
  product.price.currencyCode;     // 'USD'
  product.price.localizedString;  // '$9.99'
}
```
</Details>

#### Завершённая покупка \{#finished-purchase\}
Этот метод **обязателен**. Он вызывается при успешной покупке, отмене покупки пользователем или если покупка находится в состоянии ожидания:
```dart showLineNumbers title="Flutter"
void flowViewDidFinishPurchase(AdaptyUIFlowView view, 
                               AdaptyPaywallProduct product, 
                               AdaptyPurchaseResult purchaseResult) {
    switch (purchaseResult) {
      case AdaptyPurchaseResultSuccess(profile: final profile):
        // successful purchase
        break;
      case AdaptyPurchaseResultPending():
        // purchase is pending
        break;
      case AdaptyPurchaseResultUserCancelled():
        // user cancelled the purchase
        break;
      default:
        break;
    }
}
```

<Details>
<summary>Примеры событий (нажмите, чтобы развернуть)</summary>
```dart
void flowViewDidFinishPurchase(AdaptyUIFlowView view,
                               AdaptyPaywallProduct product,
                               AdaptyPurchaseResult purchaseResult) {
  // product — AdaptyPaywallProduct:
  product.vendorProductId; // 'premium_monthly'

  switch (purchaseResult) {
    case AdaptyPurchaseResultSuccess(profile: final profile):
      // profile — AdaptyProfile:
      profile.accessLevels['premium']?.isActive;  // true
      profile.accessLevels['premium']?.expiresAt; // DateTime(2027, 2, 15, 10, 30)
      break;
    case AdaptyPurchaseResultPending():
      // no additional data
      break;
    case AdaptyPurchaseResultUserCancelled():
      // no additional data
      break;
  }
}
```
</Details>
:::info
В отличие от v3, у этого метода нет поведения по умолчанию — экран больше не закрывается автоматически после успешной покупки. Решите самостоятельно, что происходит дальше: продолжить флоу или вызвать `view.dismiss()`. Подробнее об управлении закрытием экрана — в разделе [Реагирование на действия кнопок](flutter-handle-paywall-actions).
:::

#### Завершение навигации в веб-платёжке \{#finished-web-payment-navigation\}

Этот метод вызывается после попытки открыть [веб-пейвол](web-paywall) для конкретного продукта. Это касается как успешных, так и неудачных попыток навигации:
```dart showLineNumbers title="Flutter"
void flowViewDidFinishWebPaymentNavigation(AdaptyUIFlowView view, 
                                           AdaptyPaywallProduct? product, 
                                           AdaptyError? error) {
}
```

**Параметры:**
| Параметр    | Описание                                                                                                                        |
|:------------|:--------------------------------------------------------------------------------------------------------------------------------|
| **product** | Объект `AdaptyPaywallProduct`, для которого был открыт веб-пейвол. Может быть `null`.                                           |
| **error**   | Объект `AdaptyError`, если навигация по веб-пейволу завершилась ошибкой; `null`, если навигация прошла успешно. |

#### Неудачная покупка \{#failed-purchase\}
Этот метод вызывается при неудачной попытке покупки (например, из-за проблем с оплатой или сетевых ошибок). Он **не** срабатывает при отмене пользователем или ожидающих транзакциях — они обрабатываются через `flowViewDidFinishPurchase`:

```dart showLineNumbers title="Flutter"
void flowViewDidFailPurchase(AdaptyUIFlowView view, 
                             AdaptyPaywallProduct product, 
                             AdaptyError error) {
}
```

#### Восстановление начато \{#started-restore\}

Если пользователь инициирует процесс восстановления покупок, этот метод будет вызван:
```dart showLineNumbers title="Flutter"
void flowViewDidStartRestore(AdaptyUIFlowView view) {
}
```

#### Успешное восстановление \{#successful-restore\}

Этот метод **обязательный**. Если восстановление покупки прошло успешно, он будет вызван:

```dart showLineNumbers title="Flutter"
void flowViewDidFinishRestore(AdaptyUIFlowView view, AdaptyProfile profile) {
}
```

<Details>
<summary>Пример события (нажмите, чтобы развернуть)</summary>
```dart
void flowViewDidFinishRestore(AdaptyUIFlowView view, AdaptyProfile profile) {
  // profile — AdaptyProfile:
  profile.accessLevels['premium']?.isActive;            // true
  profile.accessLevels['premium']?.expiresAt;           // DateTime(2027, 2, 15, 10, 30)
  profile.subscriptions['premium_monthly']?.isActive;   // true
  profile.subscriptions['premium_monthly']?.expiresAt;  // DateTime(2027, 2, 15, 10, 30)
}
```
</Details>
Мы рекомендуем закрывать экран, если у пользователя есть необходимый `accessLevel`. Обратитесь к разделу [Статус подписки](flutter-listen-subscription-changes), чтобы узнать, как его проверить, и к разделу [Обработка действий кнопок](flutter-handle-paywall-actions), чтобы узнать, как закрыть экран.

#### Неудачное восстановление \{#failed-restore\}

Если восстановление покупки завершается с ошибкой, будет вызван этот метод:

```dart showLineNumbers title="Flutter"
void flowViewDidFailRestore(AdaptyUIFlowView view, AdaptyError error) {
}
```
### Загрузка данных и отображение \{#data-fetching-and-rendering\}

#### Ошибки загрузки продуктов \{#product-loading-errors\}

Если вы не передаёте массив продуктов при инициализации, AdaptyUI самостоятельно запросит необходимые объекты с сервера. Если эта операция завершится ошибкой, AdaptyUI сообщит об этом, вызвав следующий метод:

```dart showLineNumbers title="Flutter"
void flowViewDidFailLoadingProducts(AdaptyUIFlowView view, AdaptyError error) {
}
```

#### Ошибки отображения \{#view-errors\}
Этот метод **обязателен**. Он заменяет метод `paywallViewDidFailRendering` из v3: ошибки, возникающие при рендеринге интерфейса, а также другие ошибки представления, передаются через него. После реализации метода решение о закрытии остаётся за вами — мы рекомендуем закрывать представление при таких ошибках; именно так ведёт себя встроенная логика SDK по умолчанию, когда наблюдатель не задан:

```dart showLineNumbers title="Flutter"
void flowViewDidReceiveError(AdaptyUIFlowView view, AdaptyError error) {
  // log the error and dismiss the broken view
  view.dismiss();
}
```
В нормальной ситуации ошибки рендеринга возникать не должны, поэтому если вы с ними столкнётесь — пожалуйста, сообщите нам.
### Аналитические события \{#analytics-events\}

Опциональный метод `flowViewDidReceiveAnalyticEvent` предназначен для получения пользовательских аналитических событий из флоу. Флоу пока не отправляет такие события в ваш код, поэтому реализовывать этот метод не нужно.
### Обработка покупок в режиме наблюдателя \{#handle-purchases-in-observer-mode\}

Если вы активировали SDK в [режиме наблюдателя](implement-observer-mode-flutter) и отображаете флоу или пейвол, отрисованный Adapty, SDK не совершает покупки самостоятельно. Когда пользователь нажимает кнопку покупки или восстановления, SDK вызывает ваш `AdaptyUIObserverModeResolver`. Подробнее о настройке читайте в разделе [Отображение флоу в режиме наблюдателя](flutter-present-flows-in-observer-mode).
### Обработка системных запросов \{#handle-system-requests\}

`AdaptyUISystemRequestsHandler` (регистрируется через `AdaptyUI().setSystemRequestsHandler(...)`) предназначен для системных запросов из флоу: запросы разрешений ОС (например, push-уведомления или доступ к камере) и запросы на оценку в App Store. Флоу пока не инициируют такие запросы, поэтому регистрировать обработчик не нужно.
Если вы регистрируете обработчик, обратите внимание: `handlePermission` — это обязательный метод класса; запросите разрешение своим кодом, затем верните `AdaptyUIPermissionResult.granted()` или `AdaptyUIPermissionResult.denied()`; `handleAppReviewRequest` — необязательный.

---

> [!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
Этот гайд охватывает обработку событий покупок, восстановления, выбора продуктов и отображения пейвола. Также необходимо реализовать обработку кнопок (закрытие пейвола, открытие ссылок и т. д.). Подробнее см. в нашем [гайде по обработке действий кнопок](flutter-handle-paywall-actions).
:::
Пейволы, созданные в [Paywall Builder](adapty-paywall-builder), не требуют дополнительного кода для совершения и восстановления покупок. Однако они генерируют события, на которые ваше приложение может реагировать. Среди них — нажатия кнопок (кнопки закрытия, URL, выбор продукта и т. д.), а также уведомления о действиях, связанных с покупками, выполненных на пейволе. Ниже описано, как обрабатывать эти события.

:::warning

Это руководство предназначено **только для пейволов, созданных в новом Paywall Builder**, для работы с которыми требуется Adapty SDK v3.0 или более поздней версии.

:::
Чтобы контролировать или отслеживать процессы, происходящие на экране пейвола в вашем мобильном приложении, реализуйте методы `AdaptyUIPaywallsEventsObserver` и установите наблюдатель до отображения любого экрана:

```dart showLineNumbers title="Flutter"
AdaptyUI().setPaywallsEventsObserver(this);
```

:::tip

Хотите увидеть реальный пример интеграции Adapty SDK в мобильное приложение? Посмотрите наши [примеры приложений](sample-apps) — они демонстрируют полную настройку: отображение пейволов, совершение покупок и другие базовые функции.

:::

В примерах событий ниже показаны свойства, доступные для каждого объекта, с иллюстративными значениями в комментариях.
### События, генерируемые пользователем \{#user-generated-events\}

#### Пейвол появился \{#paywall-appeared\}

Этот метод вызывается, когда представление пейвола отображается на экране.

:::note
На iOS также вызывается, когда пользователь нажимает на [кнопку веб-пейвола](web-paywall#step-2a-add-a-web-purchase-button) внутри пейвола, и веб-пейвол открывается во встроенном браузере.
:::

```dart showLineNumbers title="Flutter"
void paywallViewDidAppear(AdaptyUIPaywallView view) {
}
```

#### Пейвол исчез \{#paywall-disappeared\}

Этот метод вызывается, когда представление пейвола убирается с экрана.
:::note
На iOS также вызывается, когда [веб-пейвол](web-paywall#step-2a-add-a-web-purchase-button), открытый из пейвола во встроенном браузере, исчезает с экрана.
:::

```dart showLineNumbers title="Flutter"
void paywallViewDidDisappear(AdaptyUIPaywallView view) {
}
```

#### Выбор продукта \{#product-selection\}

Если продукт выбран для покупки (пользователем или системой), этот метод будет вызван:

```dart showLineNumbers title="Flutter"
void paywallViewDidSelectProduct(AdaptyUIPaywallView view, String productId) {
}
```

<Details>
<summary>Пример события (нажмите, чтобы развернуть)</summary>
```dart
void paywallViewDidSelectProduct(AdaptyUIPaywallView view, String productId) {
  // productId is a String:
  productId; // 'premium_monthly'
}
```
</Details>

#### Начало покупки \{#started-purchase\}

Если пользователь инициирует процесс покупки, будет вызван этот метод:

```dart showLineNumbers title="Flutter"
void paywallViewDidStartPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product) {
}
```

<Details>
<summary>Пример события (нажмите, чтобы развернуть)</summary>
```dart
void paywallViewDidStartPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product) {
  // product — AdaptyPaywallProduct:
  product.vendorProductId;        // 'premium_monthly'
  product.localizedTitle;         // 'Premium Monthly'
  product.localizedDescription;   // 'Premium subscription for 1 month'
  product.price.amount;           // 9.99            (double)
  product.price.currencyCode;     // 'USD'
  product.price.localizedString;  // '$9.99'
}
```
</Details>

#### Завершённая покупка \{#finished-purchase\}
Этот метод вызывается, когда покупка завершается успешно, пользователь отменяет покупку или покупка оказывается в ожидании:
```dart showLineNumbers title="Flutter"
void paywallViewDidFinishPurchase(AdaptyUIPaywallView view, 
                                  AdaptyPaywallProduct product, 
                                  AdaptyPurchaseResult purchaseResult) {
    switch (purchaseResult) {
      case AdaptyPurchaseResultSuccess(profile: final profile):
        // successful purchase
        break;
      case AdaptyPurchaseResultPending():
        // purchase is pending
        break;
      case AdaptyPurchaseResultUserCancelled():
        // user cancelled the purchase
        break;
      default:
        break;
    }
}
```

<Details>
<summary>Примеры событий (нажмите, чтобы развернуть)</summary>
```dart
void paywallViewDidFinishPurchase(AdaptyUIPaywallView view,
                                  AdaptyPaywallProduct product,
                                  AdaptyPurchaseResult purchaseResult) {
  // product — AdaptyPaywallProduct:
  product.vendorProductId; // 'premium_monthly'

  switch (purchaseResult) {
    case AdaptyPurchaseResultSuccess(profile: final profile):
      // profile — AdaptyProfile:
      profile.accessLevels['premium']?.isActive;  // true
      profile.accessLevels['premium']?.expiresAt; // DateTime(2027, 2, 15, 10, 30)
      break;
    case AdaptyPurchaseResultPending():
      // no additional data
      break;
    case AdaptyPurchaseResultUserCancelled():
      // no additional data
      break;
  }
}
```
</Details>
Мы рекомендуем закрывать экран в этом случае. Подробнее о закрытии экрана пейвола см. в разделе [Реакция на действия кнопок](flutter-handle-paywall-actions).

#### Завершение навигации веб-платежа \{#finished-web-payment-navigation\}

Этот метод вызывается после попытки открыть [веб-пейвол](web-paywall) для конкретного продукта. Это включает как успешные, так и неудачные попытки навигации:
```dart showLineNumbers title="Flutter"
void paywallViewDidFinishWebPaymentNavigation(AdaptyUIPaywallView view, 
                                               AdaptyPaywallProduct? product, 
                                               AdaptyError? error) {
}
```

**Параметры:**
| Параметр    | Описание                                                                                                         |
|:------------|:-----------------------------------------------------------------------------------------------------------------|
| **product** | `AdaptyPaywallProduct` — продукт, для которого открыт веб-пейвол. Может быть `null`.                            |
| **error**   | Объект `AdaptyError`, если навигация по веб-пейволу завершилась с ошибкой; `null`, если навигация прошла успешно. |

<Details>
<summary>Примеры событий (нажмите, чтобы развернуть)</summary>
```dart
void paywallViewDidFinishWebPaymentNavigation(AdaptyUIPaywallView view,
                                               AdaptyPaywallProduct? product,
                                               AdaptyError? error) {
  // product — AdaptyPaywallProduct?:
  product?.vendorProductId; // 'premium_monthly'

  if (error == null) {
    // navigation succeeded
  } else {
    // error — AdaptyError:
    error.code;    // AdaptyErrorCode.networkFailed (2005)
    error.message; // 'Network request failed'
    error.detail;  // platform-specific underlying error, or null
  }
}
```
</Details>
#### Неудачная покупка \{#failed-purchase\}

Этот метод вызывается, когда покупка завершается ошибкой (например, из-за проблем с оплатой или сетевых ошибок). Он **не** срабатывает при отмене пользователем или незавершённых транзакциях — они обрабатываются через `paywallViewDidFinishPurchase`:

```dart showLineNumbers title="Flutter"
void paywallViewDidFailPurchase(AdaptyUIPaywallView view, 
                                AdaptyPaywallProduct product, 
                                AdaptyError error) {
}
```

<Details>
<summary>Пример события (нажмите, чтобы развернуть)</summary>
```dart
void paywallViewDidFailPurchase(AdaptyUIPaywallView view,
                                AdaptyPaywallProduct product,
                                AdaptyError error) {
  // product — AdaptyPaywallProduct:
  product.vendorProductId; // 'premium_monthly'

  // error — AdaptyError:
  error.code;    // AdaptyErrorCode.productPurchaseFailed (1006)
  error.message; // 'Product purchase failed.'
  error.detail;  // platform-specific underlying error, or null
}
```
</Details>

#### Восстановление начато \{#started-restore\}

Когда пользователь инициирует процесс восстановления покупок, вызывается этот метод:
```dart showLineNumbers title="Flutter"
void paywallViewDidStartRestore(AdaptyUIPaywallView view) {
}
```

#### Успешное восстановление \{#successful-restore\}

Если восстановление покупки прошло успешно, будет вызван этот метод:

```dart showLineNumbers title="Flutter"
void paywallViewDidFinishRestore(AdaptyUIPaywallView view, AdaptyProfile profile) {
}
```

<Details>
<summary>Пример события (нажмите, чтобы развернуть)</summary>
```dart
void paywallViewDidFinishRestore(AdaptyUIPaywallView view, AdaptyProfile profile) {
  // profile — AdaptyProfile:
  profile.accessLevels['premium']?.isActive;            // true
  profile.accessLevels['premium']?.expiresAt;           // DateTime(2027, 2, 15, 10, 30)
  profile.subscriptions['premium_monthly']?.isActive;   // true
  profile.subscriptions['premium_monthly']?.expiresAt;  // DateTime(2027, 2, 15, 10, 30)
}
```
</Details>
Мы рекомендуем закрывать экран, если у пользователя есть нужный `accessLevel`. Обратитесь к разделу [Статус подписки](flutter-listen-subscription-changes), чтобы узнать, как его проверить, и к разделу [Реагирование на действия кнопок](flutter-handle-paywall-actions), чтобы узнать, как закрыть экран пейвола.

#### Ошибка восстановления \{#failed-restore\}

Если восстановление покупки завершится с ошибкой, будет вызван следующий метод:

```dart showLineNumbers title="Flutter"
void paywallViewDidFailRestore(AdaptyUIPaywallView view, AdaptyError error) {
}
```

<Details>
<summary>Пример события (нажмите, чтобы развернуть)</summary>
```dart
void paywallViewDidFailRestore(AdaptyUIPaywallView view, AdaptyError error) {
  // error — AdaptyError:
  error.code;    // AdaptyErrorCode.receiveRestoredTransactionsFailed (1011)
  error.message; // 'Error occurred in the process of restoring purchases.'
  error.detail;  // platform-specific underlying error, or null
}
```
</Details>
### Получение данных и рендеринг \{#data-fetching-and-rendering\}

#### Ошибки загрузки продуктов \{#product-loading-errors\}

Если вы не передаёте массив продуктов при инициализации, AdaptyUI самостоятельно получит необходимые объекты с сервера. Если эта операция завершится ошибкой, AdaptyUI сообщит о ней, вызвав следующий метод:

```dart showLineNumbers title="Flutter"
void paywallViewDidFailLoadingProducts(AdaptyUIPaywallView view, AdaptyError error) {
}
```

<Details>
<summary>Пример события (нажмите, чтобы развернуть)</summary>
```dart
void paywallViewDidFailLoadingProducts(AdaptyUIPaywallView view, AdaptyError error) {
  // error — AdaptyError:
  error.code;    // AdaptyErrorCode.productRequestFailed (1002)
  error.message; // 'Unable to fetch available In-App Purchase products at the moment.'
  error.detail;  // platform-specific underlying error, or null
}
```
</Details>

#### Ошибки рендеринга \{#rendering-errors\}
Если во время отображения интерфейса возникает ошибка, она сообщается путём вызова этого метода. По умолчанию (начиная с v3.15.2) пейвол автоматически закрывается при ошибке рендеринга, но при необходимости это поведение можно переопределить.

```dart showLineNumbers title="Flutter"
void paywallViewDidFailRendering(AdaptyUIPaywallView view, AdaptyError error) {
  // Default behavior: view.dismiss()
  // Override with custom logic if needed, for example:
  // - Log the error
  // - Show an error message to the user
}
```

<Details>
<summary>Пример события (нажмите, чтобы развернуть)</summary>
```dart
void paywallViewDidFailRendering(AdaptyUIPaywallView view, AdaptyError error) {
  // error — AdaptyError:
  error.code;    // AdaptyErrorCode.jsException (4105)
  error.message; // 'An exception was thrown from JS during AdaptyUI flow execution.'
  error.detail;  // platform-specific underlying error, or null

  // Default behavior: view.dismiss()
}
```
</Details>

В нормальной ситуации такие ошибки возникать не должны, поэтому если вы столкнулись с одной из них, пожалуйста, сообщите нам.

---