React Native - Отображение пейволов, созданных в новом Paywall Builder

Если вы настроили пейвол с помощью Paywall Builder, вам не нужно беспокоиться о его отрисовке в коде мобильного приложения. Такой пейвол содержит как содержимое экрана, так и способ его отображения.

Перед началом убедитесь, что:

  1. Вы создали пейвол.
  2. Вы добавили пейвол в плейсмент.
  3. Вы получили пейвол и подготовили представление.

Это руководство предназначено только для пейволов нового Paywall Builder, которые требуют SDK v3.0 или новее. Процесс отображения пейволов отличается для пейволов, созданных в разных версиях Paywall Builder, и для пейволов на основе Remote Config.

Adapty React Native SDK предоставляет два способа отображения пейволов:

  • React-компонент: встраиваемый компонент, который можно интегрировать в архитектуру и навигационную систему вашего приложения.

  • Модальное отображение

React-компонент

Подход с использованием React-компонента требует SDK 3.14.0 или новее.

Чтобы встроить пейвол в существующее дерево компонентов, используйте компонент AdaptyPaywallView непосредственно в иерархии React Native компонентов. Встраиваемый компонент позволяет интегрировать его в архитектуру и навигационную систему вашего приложения.

На Android, если пейвол не распространяется за пределы строки состояния, в его верхней части может появиться визуальный оверлей. Рекомендуем отключить его для ваших пейволов. См. Визуальный оверлей в верхней части пейвола (Android).


function MyPaywall({ paywall }) {
  const paywallParams = useMemo(() => ({
    loadTimeoutMs: 3000,
  }), []);

  const onCloseButtonPress = useCallback<EventHandlers['onCloseButtonPress']>(() => {}, []);
  const onProductSelected = useCallback<EventHandlers['onProductSelected']>((productId) => {}, []);
  const onPurchaseStarted = useCallback<EventHandlers['onPurchaseStarted']>((product) => {}, []);
  const onPurchaseCompleted = useCallback<EventHandlers['onPurchaseCompleted']>((purchaseResult, product) => {}, []);
  const onPurchaseFailed = useCallback<EventHandlers['onPurchaseFailed']>((error, product) => {}, []);
  const onRestoreStarted = useCallback<EventHandlers['onRestoreStarted']>(() => {}, []);
  const onRestoreCompleted = useCallback<EventHandlers['onRestoreCompleted']>((profile) => {}, []);
  const onRestoreFailed = useCallback<EventHandlers['onRestoreFailed']>((error) => {}, []);
  const onPaywallShown = useCallback<EventHandlers['onPaywallShown']>(() => {}, []);
  const onRenderingFailed = useCallback<EventHandlers['onRenderingFailed']>((error) => {}, []);
  const onLoadingProductsFailed = useCallback<EventHandlers['onLoadingProductsFailed']>((error) => {}, []);
  const onUrlPress = useCallback<EventHandlers['onUrlPress']>((url) => {}, []);
  const onCustomAction = useCallback<EventHandlers['onCustomAction']>((actionId) => {}, []);
  const onWebPaymentNavigationFinished = useCallback<EventHandlers['onWebPaymentNavigationFinished']>(() => {}, []);

  return (
    <AdaptyPaywallView
      paywall={paywall}
      params={paywallParams}
      style={styles.paywall}
      onCloseButtonPress={onCloseButtonPress}
      onProductSelected={onProductSelected}
      onPurchaseStarted={onPurchaseStarted}
      onPurchaseCompleted={onPurchaseCompleted}
      onPurchaseFailed={onPurchaseFailed}
      onRestoreStarted={onRestoreStarted}
      onRestoreCompleted={onRestoreCompleted}
      onRestoreFailed={onRestoreFailed}
      onPaywallShown={onPaywallShown}
      onRenderingFailed={onRenderingFailed}
      onLoadingProductsFailed={onLoadingProductsFailed}
      onCustomAction={onCustomAction}
      onUrlPress={onUrlPress}
      onWebPaymentNavigationFinished={onWebPaymentNavigationFinished}
    />
  );
}

Чтобы показать пейвол как отдельный экран, используйте метод view.present() на объекте view, созданном методом createPaywallView. Каждый view можно использовать только один раз. Если нужно показать пейвол снова, вызовите createPaywallView ещё раз, чтобы создать новый экземпляр view.

Повторное использование одного и того же view без его пересоздания запрещено. Это приведёт к ошибке AdaptyUIError.viewAlreadyPresented.

Настройка стиля отображения на iOS

Настройте способ отображения пейвола на iOS, передав параметр iosPresentationStyle в метод present(). Параметр принимает значения 'full_screen' (по умолчанию) или 'page_sheet'.

try {
  await view.present(iosPresentationStyle: 'page_sheet');
} catch (error) {
  // handle the error
}

Использование таймеров, заданных разработчиком

Чтобы использовать таймеры, заданные разработчиком, в вашем мобильном приложении, укажите timerId — например, CUSTOM_TIMER_NYTimer ID таймера, заданного разработчиком в дашборде Adapty. Это позволяет приложению динамически обновлять таймер с нужным значением, например 13d 09h 03m 34s (рассчитывается как время окончания таймера, например Новый год, минус текущее время).

В этом примере CUSTOM_TIMER_NY — это Timer ID таймера, заданного разработчиком в дашборде Adapty. timerResolver обеспечивает динамическое обновление таймера с нужным значением, например 13d 09h 03m 34s (рассчитывается как время окончания таймера, например Новый год, минус текущее время).

Отображение диалога

Используйте этот метод вместо стандартных диалоговых окон на Android в тех случаях, когда на экране отображается пейвол. На Android обычные RN-алерты появляются позади пейвола и становятся невидимыми для пользователей. Этот метод обеспечивает корректное отображение диалога поверх пейвола на всех платформах.

try {
  const action = await view.showDialog({
    title: 'Close paywall?',
    content: 'You will lose access to exclusive offers.',
    primaryActionTitle: 'Stay',
    secondaryActionTitle: 'Close',
  });
  
  if (action === 'secondary') {
    // User confirmed - close the paywall
    await view.dismiss();
  }
  // If primary - do nothing, user stays
} catch (error) {
  // handle error
}

Замена одной подписки на другую

Когда пользователь пытается приобрести новую подписку при наличии активной подписки на Android, вы можете управлять обработкой новой покупки, передав параметры обновления подписки при создании представления пейвола. Чтобы заменить текущую подписку новой, используйте productPurchaseParams в createPaywallView с параметрами oldSubVendorProductId и prorationMode.


const productPurchaseParams = paywall.productIdentifiers.map((productId) => {
  let params = {};
  if (Platform.OS === 'android') {
    params.android = {
      subscriptionUpdateParams: {
        oldSubVendorProductId: 'PRODUCT_ID_OF_THE_CURRENT_ACTIVE_SUBSCRIPTION',
        prorationMode: 'with_time_proration',
      },
    };
  }
  return { productId, params };
});

const view = await createPaywallView(paywall, { productPurchaseParams });

Устранение проблем

Визуальный оверлей в верхней части пейвола (Android)

Этот параметр поддерживается начиная с React Native SDK 3.15.5 и доступен только в bare React Native проектах.

Если вы используете управляемый воркфлоу Expo, вы не можете добавить этот Android-ресурс напрямую. Чтобы применить эту настройку, необходимо создать кастомный Expo config plugin, который добавляет соответствующий Android-ресурс, и зарегистрировать его в app.config.js. Это обязательно, поскольку Expo управляет нативным Android-проектом за вас.

Если AdaptyPaywallView не распространяется за пределы строки состояния, в верхней части пейвола всё равно может появиться визуальный оверлей. Чтобы убрать его, добавьте в приложение следующий булевый ресурс:

  1. Перейдите в android/app/src/main/res/values. Если файл bools.xml отсутствует, создайте его.

  2. Добавьте следующий ресурс:

<resources>
    <bool name="adapty_paywall_enable_safe_area_paddings">false</bool>
</resources>

Обратите внимание, что изменения применяются глобально для всех пейволов в вашем приложении.