Migrate Adapty React Native SDK to v3.3

Adapty SDK 3.3.1 là bản phát hành lớn mang lại một số cải tiến có thể yêu cầu bạn thực hiện các bước migration.

  1. Nâng cấp lên Adapty SDK v3.3.x.
  2. Cập nhật các model.
  3. Xóa phương thức getProductsIntroductoryOfferEligibility.
  4. Cập nhật cách thực hiện giao dịch mua.
  5. Cập nhật cách hiển thị paywall trong Paywall Builder.
  6. Xem lại cách triển khai timer do developer định nghĩa.
  7. Cập nhật cách xử lý sự kiện mua hàng trong Paywall Builder.
  8. Cập nhật cách xử lý sự kiện custom action trong Paywall Builder.
  9. Sửa đổi callback onProductSelected.
  10. Xóa các tham số tích hợp bên thứ ba khỏi phương thức updateProfile.
  11. Cập nhật cấu hình tích hợp cho Adjust, AirBridge, Amplitude, AppMetrica, Appsflyer, Branch, Facebook Ads, Firebase and Google Analytics, Mixpanel, OneSignal, và Pushwoosh.
  12. Cập nhật cách triển khai Observer mode.

Nâng cấp Adapty React Native SDK lên 3.3.x

Trước phiên bản 3.3.1, SDK react-native-adapty là SDK cốt lõi và bắt buộc để Adapty hoạt động đúng trong ứng dụng của bạn. SDK @adapty/react-native-ui là tùy chọn và chỉ cần thiết nếu bạn sử dụng Adapty Paywall Builder.

Kể từ phiên bản 3.3.1, SDK @adapty/react-native-ui đã bị deprecated và chức năng của nó đã được tích hợp vào SDK react-native-adapty. Để nâng cấp lên phiên bản 3.3.1, hãy thực hiện các bước sau:

  1. Cập nhật gói react-native-adapty lên phiên bản 3.3.1.
  2. Xóa gói @adapty/react-native-ui khỏi các dependency của dự án.
  3. Đồng bộ hóa các dependency của dự án để áp dụng các thay đổi.

Thay đổi trong các model

Model mới

  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'; };

Model đã thay đổi

  1. AdaptyPaywallProduct:

    • Đổi tên thuộc tính subscriptionDetails thành subscription.

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

    • promotionalOffer đã bị xóa. Bây giờ ưu đãi chỉ được trả về trong thuộc tính offer nếu có. Trong trường hợp đó, offer?.identifier?.type sẽ là 'promotional'.

    • introductoryOfferEligibility đã bị xóa (ưu đãi chỉ được trả về nếu người dùng đủ điều kiện).

    • offerId đã bị xóa. ID ưu đãi hiện được lưu trong AdaptySubscriptionOffer.identifier.

    • offerTags đã được chuyển sang 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:

    • Trường identifier đã bị xóa khỏi model AdaptyDiscountPhase. Identifier của ưu đãi hiện được lưu trong AdaptySubscriptionOffer.identifier.

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

Xóa các model

  1. AttributionSource:
    • Chuỗi string hiện được sử dụng ở những nơi trước đây dùng AttributionSource.
  2. OfferEligibility:
    • Model này đã bị xóa vì không còn cần thiết. Hiện tại, ưu đãi chỉ được trả về nếu người dùng đủ điều kiện.

Xóa phương thức getProductsIntroductoryOfferEligibility

Trước Adapty SDK 3.3.1, các object sản phẩm luôn bao gồm ưu đãi, ngay cả khi người dùng không đủ điều kiện. Điều này yêu cầu bạn phải kiểm tra điều kiện thủ công trước khi sử dụng ưu đãi.

Kể từ phiên bản 3.3.1, object sản phẩm chỉ bao gồm ưu đãi nếu người dùng đủ điều kiện. Điều này đơn giản hóa quy trình vì bạn có thể giả định người dùng đủ điều kiện nếu có ưu đãi.

Cập nhật cách thực hiện giao dịch mua

Trong các phiên bản trước, giao dịch bị hủy và đang chờ xử lý được coi là lỗi và trả về mã 2: 'paymentCancelled'25: 'pendingPurchase' tương ứng.

Kể từ phiên bản 3.3.1, giao dịch bị hủy và đang chờ xử lý hiện được coi là kết quả thành công và nên được xử lý tương ứng:

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
}

Cập nhật cách hiển thị paywall trong Paywall Builder

Để xem các ví dụ cập nhật, hãy tham khảo tài liệu Hiển thị paywall mới từ Paywall Builder trong 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
}

Cập nhật cách triển khai timer do developer định nghĩa

Đổi tên tham số timerInfo thành 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 })

Sửa đổi sự kiện mua hàng trong Paywall Builder

Trước đây:

  • Giao dịch bị hủy kích hoạt callback onPurchaseCancelled.
  • Giao dịch đang chờ xử lý trả về mã lỗi 25: 'pendingPurchase'.

Bây giờ:

  • Cả hai trường hợp đều được xử lý bởi callback onPurchaseCompleted.

Các bước migration:

  1. Xóa callback onPurchaseCancelled.
  2. Xóa phần xử lý mã lỗi 25: 'pendingPurchase'.
  3. Cập nhật 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';
  },
});

Sửa đổi sự kiện custom action trong Paywall Builder

Các callback đã bị xóa:

  • onAction
  • onCustomEvent

Callback mới được thêm vào:

  • Callback onCustomAction(actionId) mới. Sử dụng nó cho các custom action.

Sửa đổi callback onProductSelected

Trước đây, onProductSelected yêu cầu object product. Bây giờ yêu cầu productId dưới dạng chuỗi string.

Xóa các tham số tích hợp bên thứ ba khỏi phương thức updateProfile

Các identifier tích hợp bên thứ ba hiện được thiết lập bằng phương thức setIntegrationIdentifier. Phương thức updateProfile không còn chấp nhận chúng nữa.

Cập nhật cấu hình SDK tích hợp bên thứ ba

Để đảm bảo các tích hợp hoạt động đúng với Adapty React Native SDK 3.3.1 trở lên, hãy cập nhật cấu hình SDK của bạn cho các tích hợp sau đây như được mô tả trong các phần bên dưới.

Ngoài ra, nếu bạn đã sử dụng AttributionSource để lấy attribution identifier, hãy thay đổi code của bạn để cung cấp identifier cần thiết dưới dạng chuỗi string.

Adjust

Cập nhật code ứng dụng di động của bạn như hướng dẫn bên dưới. Để xem ví dụ code đầy đủ, hãy xem Cấu hình SDK cho tích hợp 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

Cập nhật code ứng dụng di động của bạn như hướng dẫn bên dưới. Để xem ví dụ code đầy đủ, hãy xem Cấu hình SDK cho tích hợp 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

Cập nhật code ứng dụng di động của bạn như hướng dẫn bên dưới. Để xem ví dụ code đầy đủ, hãy xem Cấu hình SDK cho tích hợp 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

Cập nhật code ứng dụng di động của bạn như hướng dẫn bên dưới. Để xem ví dụ code đầy đủ, hãy xem Cấu hình SDK cho tích hợp 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

Cập nhật code ứng dụng di động của bạn như hướng dẫn bên dưới. Để xem ví dụ code đầy đủ, hãy xem Cấu hình SDK cho tích hợp 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

Cập nhật code ứng dụng di động của bạn như hướng dẫn bên dưới. Để xem ví dụ code đầy đủ, hãy xem Cấu hình SDK cho tích hợp 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

Cập nhật code ứng dụng di động của bạn như hướng dẫn bên dưới. Để xem ví dụ code đầy đủ, hãy xem Cấu hình SDK cho tích hợp 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 and Google Analytics

Cập nhật code ứng dụng di động của bạn như hướng dẫn bên dưới. Để xem ví dụ code đầy đủ, hãy xem Cấu hình SDK cho tích hợp Firebase and 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

Cập nhật code ứng dụng di động của bạn như hướng dẫn bên dưới. Để xem ví dụ code đầy đủ, hãy xem Cấu hình SDK cho tích hợp 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

Cập nhật code ứng dụng di động của bạn như hướng dẫn bên dưới. Để xem ví dụ code đầy đủ, hãy xem Cấu hình SDK cho tích hợp OneSignal.

Pushwoosh

Cập nhật code ứng dụng di động của bạn như hướng dẫn bên dưới. Để xem ví dụ code đầy đủ, hãy xem Cấu hình SDK cho tích hợp 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`
 }

Cập nhật cách triển khai Observer mode

Cập nhật cách bạn liên kết paywall với giao dịch. Trước đây, bạn sử dụng phương thức setVariationId để gán variationId. Bây giờ, bạn có thể đưa variationId trực tiếp khi ghi lại giao dịch bằng phương thức reportTransaction mới. Xem ví dụ code hoàn chỉnh trong Liên kết paywall với giao dịch mua trong Observer mode.

Đừng quên ghi lại giao dịch bằng phương thức reportTransaction. Bỏ qua bước này đồng nghĩa với việc Adapty sẽ không nhận ra giao dịch, không cấp mức độ truy cập, không đưa vào analytics, và không gửi đến các tích hợp. Đây là bước không thể bỏ qua!

Hãy lưu ý rằng thứ tự các tham số của phương thức reportTransaction khác với phương thức setVariationId.

  const variationId = paywall.variationId;

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