Migrer le SDK Adapty React Native vers la v3.3

Le SDK Adapty 3.3.1 est une version majeure qui apporte des améliorations pouvant nécessiter quelques étapes de migration de votre part.

  1. Mettre à niveau vers le SDK Adapty v3.3.x.
  2. Mettre à jour les modèles.
  3. Supprimer la méthode getProductsIntroductoryOfferEligibility.
  4. Mettre à jour la création d’achat.
  5. Mettre à jour la présentation des paywalls du Paywall Builder.
  6. Revoir l’implémentation des timers définis par le développeur.
  7. Mettre à jour la gestion des événements d’achat du Paywall Builder.
  8. Mettre à jour la gestion des événements d’action personnalisée du Paywall Builder.
  9. Modifier le callback onProductSelected.
  10. Supprimer les paramètres d’intégration tiers de la méthode updateProfile.
  11. Mettre à jour les configurations d’intégration pour Adjust, AirBridge, Amplitude, AppMetrica, Appsflyer, Branch, Facebook Ads, Firebase et Google Analytics, Mixpanel, OneSignal et Pushwoosh.
  12. Mettre à jour l’implémentation du mode Observer.

Mettre à niveau le SDK Adapty React Native vers la 3.3.x

Avant la version 3.3.1, le SDK react-native-adapty était le SDK principal et obligatoire pour qu’Adapty fonctionne correctement dans votre application. Le SDK @adapty/react-native-ui était optionnel et nécessaire uniquement si vous utilisiez le Paywall Builder d’Adapty.

À partir de la version 3.3.1, le SDK @adapty/react-native-ui est déprécié et ses fonctionnalités ont été intégrées dans le SDK react-native-adapty. Pour mettre à niveau vers la version 3.3.1, suivez ces étapes :

  1. Mettez à jour le package react-native-adapty vers la version 3.3.1.
  2. Supprimez le package @adapty/react-native-ui des dépendances de votre projet.
  3. Synchronisez les dépendances de votre projet pour appliquer les modifications.

Modifications des modèles

Nouveaux modèles

  1. AdaptySubscriptionOffer :

    export interface AdaptySubscriptionOffer {
      readonly identifier: AdaptySubscriptionOfferId;
    
      phases: AdaptyDiscountPhase[];
    
      android?: {
        offerTags?: string[];
      };
    }
  2. AdaptySubscriptionOfferId :

    export type AdaptySubscriptionOfferId =
      | { id?: string; type: 'introductory'; }
      | { id: string; type: 'promotional' | 'win_back'; };

Modèles modifiés

  1. AdaptyPaywallProduct :

    • La propriété subscriptionDetails a été renommée en subscription.

    -  subscriptionDetails?: AdaptySubscriptionDetails; 
    +  subscription?: AdaptySubscriptionDetails;
  2. AdaptySubscriptionDetails :

    • promotionalOffer est supprimé. L’offre promotionnelle est désormais transmise via la propriété offer uniquement si elle est disponible. Dans ce cas, offer?.identifier?.type sera 'promotional'.

    • introductoryOfferEligibility est supprimé (les offres ne sont retournées que si l’utilisateur est éligible).

    • offerId est supprimé. L’identifiant de l’offre est désormais stocké dans AdaptySubscriptionOffer.identifier.

    • offerTags est déplacé vers AdaptySubscriptionOffer.android.

    -  introductoryOffers?: AdaptyDiscountPhase[];
    +  offer?: AdaptySubscriptionOffer;
    
       ios?: {
    -    promotionalOffer?: AdaptyDiscountPhase;
         subscriptionGroupIdentifier?: string;
       };
    
       android?: {
    -    offerId?: string;
         basePlanId: string;
    -    introductoryOfferEligibility: OfferEligibility;
    -    offerTags?: string[];
         renewalType?: 'prepaid' | 'autorenewable';
       };
     }
  3. AdaptyDiscountPhase :

    • Le champ identifier est supprimé du modèle AdaptyDiscountPhase. L’identifiant de l’offre est désormais stocké dans AdaptySubscriptionOffer.identifier.

    -  ios?: {
    -    readonly identifier?: string;
    -  };

Modèles supprimés

  1. AttributionSource :
    • Une chaîne de caractères est désormais utilisée aux endroits où AttributionSource était précédemment utilisé.
  2. OfferEligibility :
    • Ce modèle a été supprimé car il n’est plus nécessaire. Désormais, une offre n’est retournée que si l’utilisateur est éligible.

Supprimer la méthode getProductsIntroductoryOfferEligibility

Avant le SDK Adapty 3.3.1, les objets produit incluaient toujours les offres, même si l’utilisateur n’était pas éligible. Vous deviez donc vérifier manuellement l’éligibilité avant d’utiliser l’offre.

À partir de la version 3.3.1, l’objet produit n’inclut les offres que si l’utilisateur est éligible. Cela simplifie le processus, car vous pouvez supposer que l’utilisateur est éligible si une offre est présente.

Mettre à jour la création d’achat

Dans les versions précédentes, les achats annulés et en attente étaient traités comme des erreurs et retournaient les codes 2: 'paymentCancelled' et 25: 'pendingPurchase' respectivement.

À partir de la version 3.3.1, les achats annulés et en attente sont désormais considérés comme des résultats réussis et doivent être gérés en conséquence :

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
}

Mettre à jour la présentation des paywalls du Paywall Builder

Pour des exemples mis à jour, consultez la documentation Présenter les nouveaux paywalls du Paywall Builder dans 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
}

Mettre à jour l’implémentation des timers définis par le développeur

Renommez le paramètre timerInfo en 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 })

Modifier les événements d’achat du Paywall Builder

Précédemment :

  • Les achats annulés déclenchaient le callback onPurchaseCancelled.
  • Les achats en attente retournaient le code d’erreur 25: 'pendingPurchase'.

Maintenant :

  • Les deux sont gérés par le callback onPurchaseCompleted.

Étapes de migration :

  1. Supprimez le callback onPurchaseCancelled.
  2. Supprimez la gestion du code d’erreur 25: 'pendingPurchase'.
  3. Mettez à jour le callback 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';
  },
});

Modifier les événements d’action personnalisée du Paywall Builder

Callbacks supprimés :

  • onAction
  • onCustomEvent

Callback ajouté :

  • Nouveau callback onCustomAction(actionId). Utilisez-le pour les actions personnalisées.

Modifier le callback onProductSelected

Précédemment, onProductSelected nécessitait l’objet product. Il requiert maintenant productId sous forme de chaîne de caractères.

Supprimer les paramètres d’intégration tiers de la méthode updateProfile

Les identifiants d’intégration tiers sont désormais définis via la méthode setIntegrationIdentifier. La méthode updateProfile ne les accepte plus.

Mettre à jour la configuration des SDK d’intégration tiers

Pour garantir le bon fonctionnement des intégrations avec le SDK Adapty React Native 3.3.1 et versions ultérieures, mettez à jour vos configurations SDK pour les intégrations suivantes comme décrit dans les sections ci-dessous.

De plus, si vous utilisiez AttributionSource pour obtenir l’identifiant d’attribution, modifiez votre code pour fournir l’identifiant requis sous forme de chaîne de caractères.

Adjust

Mettez à jour le code de votre application mobile comme indiqué ci-dessous. Pour l’exemple de code complet, consultez la configuration SDK pour l’intégration 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

Mettez à jour le code de votre application mobile comme indiqué ci-dessous. Pour l’exemple de code complet, consultez la configuration SDK pour l’intégration 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

Mettez à jour le code de votre application mobile comme indiqué ci-dessous. Pour l’exemple de code complet, consultez la configuration SDK pour l’intégration 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

Mettez à jour le code de votre application mobile comme indiqué ci-dessous. Pour l’exemple de code complet, consultez la configuration SDK pour l’intégration 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

Mettez à jour le code de votre application mobile comme indiqué ci-dessous. Pour l’exemple de code complet, consultez la configuration SDK pour l’intégration 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

Mettez à jour le code de votre application mobile comme indiqué ci-dessous. Pour l’exemple de code complet, consultez la configuration SDK pour l’intégration 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

Mettez à jour le code de votre application mobile comme indiqué ci-dessous. Pour l’exemple de code complet, consultez la configuration SDK pour l’intégration 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 et Google Analytics

Mettez à jour le code de votre application mobile comme indiqué ci-dessous. Pour l’exemple de code complet, consultez la configuration SDK pour l’intégration Firebase et 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

Mettez à jour le code de votre application mobile comme indiqué ci-dessous. Pour l’exemple de code complet, consultez la configuration SDK pour l’intégration 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

Mettez à jour le code de votre application mobile comme indiqué ci-dessous. Pour l’exemple de code complet, consultez la configuration SDK pour l’intégration OneSignal.

Pushwoosh

Mettez à jour le code de votre application mobile comme indiqué ci-dessous. Pour l’exemple de code complet, consultez la configuration SDK pour l’intégration 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`
 }

Mettre à jour l’implémentation du mode Observer

Mettez à jour la façon dont vous associez les paywalls aux transactions. Précédemment, vous utilisiez la méthode setVariationId pour assigner le variationId. Désormais, vous pouvez inclure le variationId directement lors de l’enregistrement de la transaction en utilisant la nouvelle méthode reportTransaction. Consultez l’exemple de code final dans Associer les paywalls aux transactions d’achat en mode Observer.

N’oubliez pas d’enregistrer la transaction avec la méthode reportTransaction. Si vous omettez cette étape, Adapty ne reconnaîtra pas la transaction, n’accordera pas les niveaux d’accès, ne l’inclura pas dans les analyses et ne l’enverra pas aux intégrations. Cette étape est indispensable !

Veuillez noter que l’ordre des paramètres de la méthode reportTransaction diffère de celui de la méthode setVariationId.

  const variationId = paywall.variationId;

 try {
-    await adapty.setVariationId(variationId, transactionId);
+    await adapty.reportTransaction(transactionId, variationId);
 } catch (error) {
     // handle the `AdaptyError`
 }