Миграция Adapty React Native SDK на v3.3
Adapty SDK 3.3.1 — это крупный релиз, который принёс ряд улучшений, требующих от вас выполнения нескольких шагов миграции.
- Обновите Adapty SDK до версии 3.3.x.
- Обновите модели.
- Удалите метод
getProductsIntroductoryOfferEligibility. - Обновите совершение покупки.
- Обновите отображение пейвола, созданного в Paywall Builder.
- Пересмотрите реализацию таймера, заданного разработчиком.
- Обновите обработку событий покупки в Paywall Builder.
- Обновите обработку событий пользовательских действий в Paywall Builder.
- Измените колбэк
onProductSelected. - Удалите параметры сторонних интеграций из метода
updateProfile. - Обновите настройки интеграций для Adjust, AirBridge, Amplitude, AppMetrica, Appsflyer, Branch, Facebook Ads, Firebase и Google Analytics, Mixpanel, OneSignal и Pushwoosh.
- Обновите реализацию режима Observer mode.
Обновление Adapty React Native SDK до версии 3.3.x
До версии 3.3.1 SDK react-native-adapty являлся основным и обязательным SDK для работы Adapty в вашем приложении. SDK @adapty/react-native-ui был необязательным и требовался только при использовании Adapty Paywall Builder.
Начиная с версии 3.3.1, SDK @adapty/react-native-ui считается устаревшим, а его функциональность перенесена в SDK react-native-adapty. Чтобы обновиться до версии 3.3.1, выполните следующие шаги:
- Обновите пакет
react-native-adaptyдо версии 3.3.1. - Удалите пакет
@adapty/react-native-uiиз зависимостей проекта. - Синхронизируйте зависимости проекта, чтобы применить изменения.
Изменения в моделях
Новые модели
-
export interface AdaptySubscriptionOffer { readonly identifier: AdaptySubscriptionOfferId; phases: AdaptyDiscountPhase[]; android?: { offerTags?: string[]; }; } -
export type AdaptySubscriptionOfferId = | { id?: string; type: 'introductory'; } | { id: string; type: 'promotional' | 'win_back'; };
Изменённые модели
-
-
Переименовано свойство
subscriptionDetailsвsubscription.
- subscriptionDetails?: AdaptySubscriptionDetails; + subscription?: AdaptySubscriptionDetails; -
-
promotionalOfferудалён. Теперь promotional offer передаётся в свойствеofferтолько если он доступен. В этом случаеoffer?.identifier?.typeбудет равен'promotional'.-
introductoryOfferEligibilityудалён (офферы возвращаются только если пользователь имеет право на них). -
offerIdудалён. ID оффера теперь хранится вAdaptySubscriptionOffer.identifier. -
offerTagsперемещён вAdaptySubscriptionOffer.android.
-
- introductoryOffers?: AdaptyDiscountPhase[];
+ offer?: AdaptySubscriptionOffer;
ios?: {
- promotionalOffer?: AdaptyDiscountPhase;
subscriptionGroupIdentifier?: string;
};
android?: {
- offerId?: string;
basePlanId: string;
- introductoryOfferEligibility: OfferEligibility;
- offerTags?: string[];
renewalType?: 'prepaid' | 'autorenewable';
};
}
-
Поле
identifierудалено из моделиAdaptyDiscountPhase. Идентификатор оффера теперь хранится вAdaptySubscriptionOffer.identifier.- ios?: { - readonly identifier?: string; - };
Удалённые модели
AttributionSource:- Вместо него теперь используется строка там, где ранее применялся
AttributionSource.
- Вместо него теперь используется строка там, где ранее применялся
OfferEligibility:- Эта модель удалена, так как больше не нужна. Теперь оффер возвращается только если пользователь имеет право на его получение.
Удаление метода getProductsIntroductoryOfferEligibility
До Adapty SDK 3.3.1 объекты продуктов всегда включали офферы, даже если пользователь не имел права на их получение. Это требовало ручной проверки права на получение оффера перед его использованием.
Начиная с версии 3.3.1, объект продукта включает офферы только если пользователь имеет на них право. Это упрощает процесс: если оффер присутствует, можно считать, что пользователь имеет право на его получение.
Обновление процесса покупки
В более ранних версиях отменённые и ожидающие покупки считались ошибками и возвращали коды 2: 'paymentCancelled' и 25: 'pendingPurchase' соответственно.
Начиная с версии 3.3.1, отменённые и ожидающие покупки считаются успешными результатами и должны обрабатываться соответствующим образом:
try {
const purchaseResult = await adapty.makePurchase(product);
switch (purchaseResult.type) {
case 'success':
const isSubscribed = purchaseResult.profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive;
if (isSubscribed) {
// Grant access to the paid features
}
break;
case 'user_cancelled':
// Handle the case where the user canceled the purchase
break;
case 'pending':
// Handle deferred purchases (e.g., the user will pay offline with cash)
break;
}
} catch (error) {
// Handle the error
}
Обновление отображения пейволов Paywall Builder
Актуальные примеры смотрите в документации Отображение новых пейволов Paywall Builder в React Native.
- import { createPaywallView } from '@adapty/react-native-ui';
+ import { createPaywallView } from 'react-native-adapty/dist/ui';
const view = await createPaywallView(paywall);
view.registerEventHandlers(); // handle close press, etc
try {
await view.present();
} catch (error) {
// handle the error
}
Обновление реализации таймеров, определяемых разработчиком
Переименуйте параметр timerInfo в customTimers:
- let timerInfo = { 'CUSTOM_TIMER_NY': new Date(2025, 0, 1) }
+ let customTimers = { 'CUSTOM_TIMER_NY': new Date(2025, 0, 1) }
//and then you can pass it to createPaywallView as follows:
- view = await createPaywallView(paywall, { timerInfo })
+ view = await createPaywallView(paywall, { customTimers })
Изменение событий покупки в Paywall Builder
Раньше:
- Отменённые покупки вызывали коллбэк
onPurchaseCancelled. - Ожидающие покупки возвращали код ошибки
25: 'pendingPurchase'.
Теперь:
- Оба случая обрабатываются коллбэком
onPurchaseCompleted.
Шаги для миграции:
- Удалите коллбэк
onPurchaseCancelled. - Удалите обработку кода ошибки
25: 'pendingPurchase'. - Обновите коллбэк
onPurchaseCompleted:
const view = await createPaywallView(paywall);
const unsubscribe = view.registerEventHandlers({
// ... other optional callbacks
onPurchaseCompleted(purchaseResult, product) {
switch (purchaseResult.type) {
case 'success':
const isSubscribed = purchaseResult.profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive;
if (isSubscribed) {
// Grant access to the paid features
}
break;
case 'user_cancelled':
// Handle the case where the user canceled the purchase
break;
case 'pending':
// Handle deferred purchases (e.g., the user will pay offline with cash)
break;
}
return purchaseResult.type !== 'user_cancelled';
},
});
Обновление событий кастомных действий в Paywall Builder
Удалённые коллбэки:
onActiononCustomEvent
Добавленный коллбэк:
- Новый коллбэк
onCustomAction(actionId). Используйте его для кастомных действий.
Изменение коллбэка onProductSelected
Ранее onProductSelected принимал объект product. Теперь требуется productId в виде строки.
Удаление параметров сторонних интеграций из метода updateProfile
Идентификаторы сторонних интеграций теперь задаются с помощью метода setIntegrationIdentifier. Метод updateProfile больше не принимает их.
Обновление конфигурации SDK сторонних интеграций
Чтобы интеграции корректно работали с Adapty React Native SDK 3.3.1 и выше, обновите конфигурации SDK для следующих интеграций согласно разделам ниже.
Кроме того, если вы использовали AttributionSource для получения идентификатора атрибуции, измените код так, чтобы передавать нужный идентификатор в виде строки.
Adjust
Обновите код вашего мобильного приложения, как показано ниже. Полный пример кода смотрите в разделе Настройка SDK для интеграции с Adjust.
import { Adjust, AdjustConfig } from "react-native-adjust";
import { adapty } from "react-native-adapty";
var adjustConfig = new AdjustConfig(appToken, environment);
// Before submiting Adjust config...
adjustConfig.setAttributionCallbackListener(attribution => {
// Make sure Adapty SDK is activated at this point
// You may want to lock this thread awaiting of `activate`
adapty.updateAttribution(attribution, "adjust");
});
// ...
Adjust.create(adjustConfig);
+ Adjust.getAdid((adid) => {
+ if (adid)
+ adapty.setIntegrationIdentifier("adjust_device_id", adid);
+ });
AirBridge
Обновите код мобильного приложения, как показано ниже. Полный пример кода смотрите в разделе Конфигурация SDK для интеграции AirBridge.
import Airbridge from 'airbridge-react-native-sdk';
import { adapty } from 'react-native-adapty';
try {
const deviceId = await Airbridge.state.deviceUUID();
- await adapty.updateProfile({
- airbridgeDeviceId: deviceId,
- });
+ await adapty.setIntegrationIdentifier("airbridge_device_id", deviceId);
} catch (error) {
// handle `AdaptyError`
}
Amplitude
Обновите код мобильного приложения, как показано ниже. Полный пример кода смотрите в разделе Конфигурация SDK для интеграции Amplitude.
import { adapty } from 'react-native-adapty';
try {
- await adapty.updateProfile({
- amplitudeDeviceId: deviceId,
- amplitudeUserId: userId,
- });
+ await adapty.setIntegrationIdentifier("amplitude_device_id", deviceId);
+ await adapty.setIntegrationIdentifier("amplitude_user_id", userId);
} catch (error) {
// handle `AdaptyError`
}
AppMetrica
Обновите код своего мобильного приложения, как показано ниже. Полный пример кода можно найти в разделе Настройка SDK для интеграции с AppMetrica.
import { adapty } from 'react-native-adapty';
import AppMetrica, { DEVICE_ID_KEY, StartupParams, StartupParamsReason } from '@appmetrica/react-native-analytics';
// ...
const startupParamsCallback = async (
params?: StartupParams,
reason?: StartupParamsReason
) => {
const deviceId = params?.deviceId
if (deviceId) {
try {
- await adapty.updateProfile({
- appmetricaProfileId: 'YOUR_ADAPTY_CUSTOMER_USER_ID',
- appmetricaDeviceId: deviceId,
- });
+ await adapty.setIntegrationIdentifier("appmetrica_profile_id", 'YOUR_ADAPTY_CUSTOMER_USER_ID');
+ await adapty.setIntegrationIdentifier("appmetrica_device_id", deviceId);
} catch (error) {
// handle `AdaptyError`
}
}
}
AppMetrica.requestStartupParams(startupParamsCallback, [DEVICE_ID_KEY])
AppsFlyer
Обновите код мобильного приложения, как показано ниже. Полный пример кода смотрите в разделе Настройка SDK для интеграции с AppsFlyer.
import { adapty, AttributionSource } from 'react-native-adapty';
import appsFlyer from 'react-native-appsflyer';
appsFlyer.onInstallConversionData(installData => {
try {
- const networkUserId = appsFlyer.getAppsFlyerUID();
- adapty.updateAttribution(installData, AttributionSource.AppsFlyer, networkUserId);
+ const uid = appsFlyer.getAppsFlyerUID();
+ adapty.setIntegrationIdentifier("appsflyer_id", uid);
+ adapty.updateAttribution(installData, "appsflyer");
} catch (error) {
// handle the error
}
});
// ...
appsFlyer.initSdk(/*...*/);
Branch
Обновите код мобильного приложения, как показано ниже. Полный пример кода смотрите в разделе Конфигурация SDK для интеграции Branch.
import { adapty, AttributionSource } from 'react-native-adapty';
import branch from 'react-native-branch';
branch.subscribe({
enComplete: ({
params,
}) => {
- adapty.updateAttribution(params, AttributionSource.Branch);
+ adapty.updateAttribution(params, "branch");
},
});
Facebook Ads
Обновите код вашего мобильного приложения, как показано ниже. Полный пример кода можно найти в разделе Настройка SDK для интеграции с Facebook Ads.
import { adapty } from 'react-native-adapty';
import { AppEventsLogger } from 'react-native-fbsdk-next';
try {
const anonymousId = await AppEventsLogger.getAnonymousID();
- await adapty.updateProfile({
- facebookAnonymousId: anonymousId,
- });
+ await adapty.setIntegrationIdentifier("facebook_anonymous_id", anonymousId);
} catch (error) {
// handle `AdaptyError`
}
Firebase и Google Analytics
Обновите код мобильного приложения, как показано ниже. Полный пример кода можно найти в разделе настройка SDK для интеграции с Firebase и Google Analytics.
import analytics from '@react-native-firebase/analytics';
import { adapty } from 'react-native-adapty';
try {
const appInstanceId = await analytics().getAppInstanceId();
- await adapty.updateProfile({
- firebaseAppInstanceId: appInstanceId,
- });
+ await adapty.setIntegrationIdentifier("firebase_app_instance_id", appInstanceId);
} catch (error) {
// handle `AdaptyError`
}
Mixpanel
Обновите код мобильного приложения, как показано ниже. Полный пример кода смотрите в разделе Конфигурация SDK для интеграции Mixpanel.
import { adapty } from 'react-native-adapty';
import { Mixpanel } from 'mixpanel-react-native';
// ...
try {
- await adapty.updateProfile({
- mixpanelUserId: mixpanelUserId,
- });
+ await adapty.setIntegrationIdentifier("mixpanel_user_id", mixpanelUserId);
} catch (error) {
// handle `AdaptyError`
}
OneSignal
Обновите код мобильного приложения, как показано ниже. Полный пример кода можно найти в разделе Настройка SDK для интеграции с OneSignal.
Pushwoosh
Обновите код мобильного приложения, как показано ниже. Полный пример кода смотрите в разделе Конфигурация SDK для интеграции Pushwoosh.
import { adapty } from 'react-native-adapty';
import Pushwoosh from 'pushwoosh-react-native-plugin';
// ...
try {
- await adapty.updateProfile({
- pushwooshHWID: hwid,
- });
+ await adapty.setIntegrationIdentifier("pushwoosh_hwid", hwid);
} catch (error) {
// handle `AdaptyError`
}
Обновление реализации режима Observer
Обновите способ привязки пейволов к транзакциям. Раньше для назначения variationId использовался метод setVariationId. Теперь можно передавать variationId напрямую при записи транзакции с помощью нового метода reportTransaction. Итоговый пример кода смотрите в разделе Привязка пейволов к транзакциям покупок в режиме Observer.
Не забывайте фиксировать транзакцию с помощью метода reportTransaction. Если пропустить этот шаг, Adapty не распознает транзакцию, не предоставит уровни доступа, не включит её в аналитику и не отправит в интеграции. Этот шаг обязателен!
Обратите внимание, что порядок параметров метода reportTransaction отличается от порядка параметров метода setVariationId.
const variationId = paywall.variationId;
try {
- await adapty.setVariationId(variationId, transactionId);
+ await adapty.reportTransaction(transactionId, variationId);
} catch (error) {
// handle the `AdaptyError`
}