迁移 Adapty React Native SDK 至 v3.3

Adapty SDK 3.3.1 是一个重要版本,带来了一些改进,可能需要你完成相应的迁移步骤。

  1. 升级到 Adapty SDK v3.3.x。
  2. 更新模型。
  3. 移除 getProductsIntroductoryOfferEligibility 方法。
  4. 更新购买流程。
  5. 更新付费墙编辑工具付费墙的展示方式。
  6. 修改开发者自定义计时器的实现。
  7. 更新付费墙编辑工具购买事件的处理逻辑。
  8. 更新付费墙编辑工具自定义动作事件的处理逻辑。
  9. 修改 onProductSelected 回调。
  10. 从 updateProfile 方法中移除第三方集成参数。
  11. 更新 Adjust、AirBridge、Amplitude、AppMetrica、Appsflyer、Branch、Facebook Ads、Firebase 与 Google Analytics、Mixpanel、OneSignal 及 Pushwoosh 的集成配置。
  12. 更新 Observer 模式的实现。

将 Adapty React Native SDK 升级至 3.3.x

在 3.3.1 版本之前,react-native-adapty SDK 是 Adapty 在您的应用中正常运行所必需的核心 SDK。@adapty/react-native-ui SDK 是可选的,仅在使用 Adapty 付费墙编辑工具时才需要安装。

从 3.3.1 版本起,@adapty/react-native-ui SDK 已被弃用,其功能已合并至 react-native-adapty SDK 中。请按照以下步骤升级至 3.3.1 版本:

  1. 将 react-native-adapty 包更新至 3.3.1 版本。
  2. 从项目依赖中移除 @adapty/react-native-ui 包。
  3. 同步项目依赖以应用更改。

模型变更

新增模型

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

变更的模型

  1. AdaptyPaywallProduct:

    • 将 subscriptionDetails 属性重命名为 subscription。

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

  • promotionalOffer 已移除。现在促销活动仅在可用时通过 offer 属性提供。此时 offer?.identifier?.type 的值为 'promotional'。

    • introductoryOfferEligibility 已移除(优惠仅在用户符合条件时才会返回)。

    • offerId 已移除。优惠 ID 现在存储在 AdaptySubscriptionOffer.identifier 中。

    • offerTags 已移至 AdaptySubscriptionOffer.android。

  1. AdaptyDiscountPhase:
  • AdaptyDiscountPhase 模型中移除了 identifier 字段。优惠标识符现在存储在 AdaptySubscriptionOffer.identifier 中。

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

已移除的模型

  1. AttributionSource:
    • 在之前使用 AttributionSource 的地方,现在直接使用字符串。
  2. 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
}

更新付费墙编辑工具付费墙的展示方式

有关更新后的示例,请参阅在 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 })

修改付费墙编辑工具的购买事件

之前:

  • 取消购买会触发 onPurchaseCancelled 回调。
  • 待处理的购买会返回错误码 25: 'pendingPurchase'。

现在:

  • 两者均由 onPurchaseCompleted 回调处理。

迁移步骤:

  1. 移除 onPurchaseCancelled 回调。
  2. 移除对错误码 25: 'pendingPurchase' 的处理逻辑。
  3. 更新 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';
  },
});

修改付费墙编辑工具自定义操作事件

已移除的回调:

  • onAction
  • onCustomEvent

新增的回调:

  • 新增 onCustomAction(actionId) 回调,用于处理自定义操作。

修改 onProductSelected 回调

之前,onProductSelected 需要传入 product 对象。现在改为接受字符串类型的 productId。

从 updateProfile 方法中移除第三方集成参数

第三方集成标识符现在通过 setIntegrationIdentifier 方法进行设置。updateProfile 方法不再接受这些参数。

更新第三方集成 SDK 配置

为确保集成能够与 Adapty React Native SDK 3.3.1 及更高版本正常工作,请按照以下各节的说明更新您的 SDK 配置。

此外,如果您之前使用 AttributionSource 获取归因标识符,请将代码修改为以字符串形式提供所需标识符。

Adjust

按照以下说明更新您的移动应用代码。完整代码示例请参阅 Adjust 集成的 SDK 配置。

 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

按如下方式更新您的移动应用代码。完整代码示例请参阅 AirBridge 集成的 SDK 配置。

 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

按如下方式更新您的移动应用代码。完整代码示例请参阅 Amplitude 集成的 SDK 配置。

  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

按照以下示例更新您的移动应用代码。完整代码示例请参阅 AppMetrica 集成的 SDK 配置。

 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

按照以下示例更新你的移动应用代码。完整代码示例请参阅 AppsFlyer 集成的 SDK 配置。

 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

按如下方式更新您的移动应用代码。完整代码示例请参阅 Branch 集成的 SDK 配置。

 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

按照以下方式更新您的移动应用代码。完整代码示例请参阅 Facebook Ads 集成的 SDK 配置。

 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

按以下方式更新您的移动应用代码。完整代码示例请参阅 Firebase 与 Google Analytics 集成的 SDK 配置。

 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

按如下方式更新您的移动应用代码。完整代码示例请参阅 Mixpanel 集成的 SDK 配置。

 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

按照以下示例更新您的移动应用代码。完整代码示例请参阅 OneSignal 集成的 SDK 配置。

Pushwoosh

按如下方式更新您的移动应用代码。完整代码示例请参阅 Pushwoosh 集成的 SDK 配置。

 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 模式实现

更新付费墙与交易的关联方式。以前,你需要使用 setVariationId 方法来指定 variationId。现在,你可以在使用新的 reportTransaction 方法记录交易时直接传入 variationId。请参阅在 Observer 模式下将付费墙与购买交易关联中的完整代码示例。

Warning

不要忘记使用 reportTransaction 方法记录交易。跳过此步骤意味着 Adapty 将无法识别该交易,不会授予访问等级,不会将其纳入分析统计,也不会将其发送至集成渠道。此步骤至关重要!

Note

请注意,reportTransaction 方法的参数顺序与 setVariationId 方法的参数顺序不同。

  const variationId = paywall.variationId;

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