Migrate Adapty React Native SDK to v4.0

Adapty React Native SDK 4.0 giới thiệu các flow và đổi tên các paywall API tương ứng. Các API mới hoạt động được với cả Flow Builder mới lẫn Paywall Builder hiện có — không cần thay đổi cấu hình nào trên Adapty Dashboard.

Tham chiếu nhanh

v3v4
adapty.getPaywall(placementId, locale?, params?)adapty.getFlow(placementId, params?)
adapty.getPaywallForDefaultAudience(placementId, locale?, params?)adapty.getFlowForDefaultAudience(placementId, params?)
adapty.getPaywallProducts(paywall)adapty.getPaywallProducts(flow)
adapty.logShowPaywall(paywall)adapty.logShowFlow(flow)
AdaptyPaywall (kiểu)AdaptyFlow
createPaywallView(paywall)createFlowView(flow)
AdaptyPaywallView (component)AdaptyFlowView
EventHandlers (kiểu)FlowEventHandlers
onPaywallShownonAppeared
onPaywallClosedonDisappeared
onRenderingFailedonError
AdaptyPaywallProduct giữ nguyên tên — sản phẩm vẫn thuộc về một flow, và getPaywallProducts bây giờ nhận một AdaptyFlow. Các phương thức getFlowgetFlowForDefaultAudience không còn nhận tham số locale nữa — thay vào đó hãy truyền nó vào createFlowView. Các phương thức view present, dismiss, setEventHandlers, và showDialog, cùng các event handler onCloseButtonPress, onUrlPress, onCustomAction, onProductSelected, onPurchaseStarted, onPurchaseCompleted, onPurchaseFailed, onRestoreStarted, onRestoreCompleted, onRestoreFailed, onLoadingProductsFailed, onWebPaymentNavigationFinished, và onAndroidSystemBack giữ nguyên tên như trong v3. Một số hành vi mặc định đã thay đổi — xem Thay đổi hành vi mặc định.

Phiên bản iOS tối thiểu

Adapty React Native SDK 4.0 nâng phiên bản iOS deployment target tối thiểu từ iOS 13.0 lên iOS 15.0. Hãy đặt iOS deployment target của bạn thành 15.0 hoặc cao hơn trước khi nâng cấp.

Cài đặt

Cập nhật gói

v4.0 là bản phát hành thử nghiệm (pre-release), vì vậy hãy chỉ định chính xác phiên bản — npm không tự động chọn các phiên bản pre-release qua cú pháp caret/tilde:

npm install react-native-adapty@4.0.2
# or
yarn add react-native-adapty@4.0.2

iOS: Các SDK native hiện được phân phối qua Swift Package Manager

Repo spec của CocoaPods sẽ chuyển sang chế độ chỉ đọc vào tháng 12 năm 2026, vì vậy bắt đầu từ v4, các SDK native Adapty, AdaptyUIAdaptyPlugin không còn được kéo vào dưới dạng sub-dependency của CocoaPods nữa — podspec sẽ kéo chúng qua Swift Package Manager (thông qua helper spm_dependency). Điều này yêu cầu hai thay đổi sau:

  • React Native 0.75 trở lên — cần thiết cho helper spm_dependency trong podspec. Nếu dùng phiên bản cũ hơn, pod install sẽ báo lỗi rõ ràng; hãy nâng cấp React Native trước, hoặc tiếp tục dùng react-native-adapty 3.x.
  • Dynamic frameworks — các dependency SPM yêu cầu dynamic linkage. Cách bật tính năng này khác nhau giữa Expo và bare React Native.

Expo

Thêm config plugin expo-build-properties và đặt iOS frameworks thành dynamic trong app.json (hoặc app.config.js):

{
  "expo": {
    "plugins": [
      [
        "expo-build-properties",
        {
          "ios": {
            "useFrameworks": "dynamic",
            "buildReactNativeFromSource": true
          }
        }
      ]
    ]
  }
}

buildReactNativeFromSource là bắt buộc trên Expo SDK 57 trở lên. Expo SDK 57 đi kèm với React Native framework được build sẵn mà các package khác không thể truy cập header khi frameworks là dynamic, khiến iOS build thất bại với các lỗi như 'React/RCTBridge.h' file not found trong expo-updates hoặc @expo/ui. Build React Native từ source sẽ tránh được xung đột này, nhưng đổi lại thời gian build iOS sẽ lâu hơn. Trên Expo SDK 56 trở xuống, bạn có thể bỏ qua tùy chọn này.

Sau đó cài plugin và tạo lại native project:

npx expo install expo-build-properties
npx expo prebuild --clean

Bare React Native

Thêm dynamic frameworks vào iOS target, sau đó cài lại pods:

use_frameworks! :linkage => :dynamic
cd ios && pod install --repo-update

Nếu trước đây bạn đã kéo Adapty, AdaptyUI, hoặc AdaptyPlugin dưới dạng sub-dependencies của CocoaPods, hãy xóa các dòng pod 'Adapty', pod 'AdaptyUI', hoặc pod 'AdaptyPlugin' trong Podfile trước.

Warning

Chuyển từ liên kết tĩnh mặc định sang dynamic framework có thể xung đột với các thư viện chưa hỗ trợ modular headers, và không tương thích với Flipper. Nếu gặp lỗi build, xem bài viết này về tích hợp Swift Package Manager với thư viện React Native.

Xem Cài đặt Adapty SDK để biết hướng dẫn thiết lập đầy đủ.

Lấy flows

getPaywall → getFlow

Kiểu trả về thay đổi từ AdaptyPaywall sang AdaptyFlow, và tham số locale chuyển từ lệnh gọi fetch sang createFlowView; với các paywall tùy chỉnh, tất cả locale được trả về trong flow.remoteConfigs:

- const paywall = await adapty.getPaywall('YOUR_PLACEMENT_ID', 'en');
+ const flow = await adapty.getFlow('YOUR_PLACEMENT_ID');
+ const view = await createFlowView(flow, { locale: 'en' });

locale là tùy chọn trong createFlowView: bỏ qua nó và view sẽ hiển thị bằng en, hoặc theo ngôn ngữ mặc định của flow khi flow không có en. Yêu cầu SDK 4.0.2 trở lên — xem Localizations và mã locale.

getPaywallForDefaultAudience được đổi tên tương tự:

- const paywall = await adapty.getPaywallForDefaultAudience('YOUR_PLACEMENT_ID', 'en');
+ const flow = await adapty.getFlowForDefaultAudience('YOUR_PLACEMENT_ID');

getPaywallProducts(paywall) → getPaywallProducts(flow)

getPaywallProducts giữ nguyên tên nhưng giờ nhận một AdaptyFlow:

- const products = await adapty.getPaywallProducts(paywall);
+ const products = await adapty.getPaywallProducts(flow);

Tệp dự phòng

Định dạng tệp dự phòng đã thay đổi trong SDK v4. Tải tệp mới từ Placements > Fallbacks và đóng gói vào ứng dụng của bạn.

Mô hình dữ liệu

getFlow trả về AdaptyFlow thay vì AdaptyPaywall, và cấu trúc đối tượng đã thay đổi:

Trường AdaptyPaywall v3Trường AdaptyFlow v4Hành động
remoteConfig? (đơn lẻ)remoteConfigs?: AdaptyRemoteConfig[] (mảng)Một flow chứa một remote config cho mỗi ngôn ngữ đã cấu hình. Đọc cái phù hợp với người dùng: flow.remoteConfigs?.find((c) => c.lang === 'en').
productsflow.paywalls[i].productIdentifiersCác định danh sản phẩm hiện nằm trên từng biến thể flow, không còn trên flow nữa.
webPurchaseUrl?flow.paywalls[i].webPurchaseUrlChuyển từ flow sang từng biến thể paywall.
version?: numberflowVersionId?: stringĐổi tên, và kiểu dữ liệu thay đổi từ number sang string.
hasViewConfigurationđã xóaXóa mọi kiểm tra hasViewConfiguration khỏi code của bạn.
requestLocaleđã xóaLocale không còn là một phần của model nữa.
(mới)paywalls: AdaptyFlowPaywall[]Mỗi mục là một biến thể paywall trong flow.
(mới)responseCreatedAt: numberTimestamp phản hồi từ server, tính bằng mili giây.
Product identifiers moved from the flow to each variation:
- const ids = paywall.products;
+ const ids = flow.paywalls[0].productIdentifiers;

Các phương thức Web paywall

openWebPaywallcreateWebPaywallUrl vẫn giữ nguyên tên, nhưng tham số đầu tiên bây giờ là AdaptyFlowPaywall (một biến thể flow) thay vì AdaptyPaywall. Bạn vẫn có thể truyền vào AdaptyPaywallProduct.

  const flow = await adapty.getFlow('YOUR_PLACEMENT_ID');
- await adapty.openWebPaywall(paywall);
+ await adapty.openWebPaywall(flow.paywalls[0]);

Theo dõi lượt xem flow

logShowPaywall → logShowFlow

logShowPaywall được đổi tên thành logShowFlow và giờ nhận vào một AdaptyFlow. Sự kiện vẫn được ghi lại theo cùng một biến thể, nên các chỉ số funnel và A/B test hiện có vẫn hoạt động bình thường mà không cần thay đổi trên dashboard.

- await adapty.logShowPaywall(paywall);
+ await adapty.logShowFlow(flow);

Giống như ở v3, bạn không cần gọi phương thức này khi hiển thị các flow hoặc paywall được dựng bởi Flow Builder hoặc Paywall Builder — Adapty tự động theo dõi các lượt xem đó.

Hiển thị flow

createPaywallView → createFlowView

Đổi tên hàm factory và truyền vào AdaptyFlow. Các phương thức của controller được trả về (present, dismiss, setEventHandlers, showDialog) không thay đổi:

- import { createPaywallView } from 'react-native-adapty';
+ import { createFlowView } from 'react-native-adapty';

- const view = await createPaywallView(paywall);
+ const view = await createFlowView(flow);
  await view.present();

AdaptyPaywallView → AdaptyFlowView

Nếu bạn render bằng React component, hãy đổi tên component và truyền prop flow:

- import { AdaptyPaywallView } from 'react-native-adapty';
+ import { AdaptyFlowView } from 'react-native-adapty';

- <AdaptyPaywallView paywall={paywall} /* … */ />
+ <AdaptyFlowView flow={flow} /* … */ />
Note

Một flow view được tạo bằng createFlowView chỉ dùng một lần: sau khi gọi dismiss(), view đó sẽ bị hủy, vì vậy hãy gọi lại createFlowView để hiển thị flow thêm lần nữa. Một AdaptyFlowView được nhúng sẽ bị đóng khi unmount — trả về true từ một handler không đóng view được nhúng, vì vậy hãy tự thay đổi state của bạn thay thế, ví dụ trong onCloseButtonPress.

Xử lý sự kiện

Giao diện xử lý sự kiện được đổi tên từ EventHandlers thành FlowEventHandlers, và ba callback cũng được đổi tên. Phần thân của các handler hiện có không cần thay đổi code — chỉ cần đổi tên:

- onPaywallShown: () => { /* … */ },
+ onAppeared: () => { /* … */ },

- onPaywallClosed: () => { /* … */ },
+ onDisappeared: () => { /* … */ },

- onRenderingFailed: (error) => { /* … */ },
+ onError: (error) => { /* … */ },

Tất cả các event handler khác vẫn giữ nguyên tên. Hai handler cũng nhận thêm tham số thứ hai: onPurchaseCompleted nay là (purchaseResult, product)onPurchaseFailed nay là (error, product), trong đó productAdaptyPaywallProduct liên quan. Xem Xử lý sự kiện flow & paywall để biết danh sách đầy đủ.

Note

onDisappeared chỉ kích hoạt khi một flow được trình bày dưới dạng modal với createFlowView().present(). Component AdaptyFlowView không expose nó dưới dạng prop — để đóng một embedded view, hãy unmount nó.

v4 cũng bổ sung một số tính năng bạn có thể tùy chọn bật:

  • Các phương thức adapty.openWebUrl(url, openIn?)adapty.requestAppReview() — hỗ trợ các handler mặc định onUrlPressonRequestAppReview, giúp xử lý URL và yêu cầu đánh giá ứng dụng theo cách native ngay từ đầu. Chỉ gọi trực tiếp khi bạn ghi đè các handler đó.
  • Xử lý giao dịch mua trong Observer mode bên trong flow thông qua các handler mới onObserverPurchaseInitiated / onObserverRestoreInitiated. Xem Xử lý giao dịch mua trong Observer mode.

Các API đã bị xóa và deprecated

setFallbackPaywalls → setFallback

setFallbackPaywalls đã bị xóa. Hãy dùng setFallback, nhận cùng tham số:

- await adapty.setFallbackPaywalls(fileLocation);
+ await adapty.setFallback(fileLocation);

Các export đã bị xóa

Các symbol này không còn được export từ react-native-adapty nữa. Hãy xóa các import liên quan:

  • AdaptyPaywall: Dùng AdaptyFlow thay thế.
  • ProductReference: Dùng AdaptyProductIdentifier, đọc từ flow.paywalls[i].productIdentifiers.
  • AdaptyPaywallBuilder: Đã bị xóa. Flow và paywall được render natively.
  • AdaptyAndroidSubscriptionUpdateParameters: Dùng shape lồng nhau subscriptionUpdateParams (xem bên dưới).

activate: lockMethodsUntilReady

lockMethodsUntilReady đã bị xóa và hành vi này hiện luôn được bật. Hãy xóa nó khỏi lệnh gọi activate — giữ lại nó sẽ gây lỗi biên dịch:

- await adapty.activate('PUBLIC_SDK_KEY', { lockMethodsUntilReady: true });
+ await adapty.activate('PUBLIC_SDK_KEY');

Cập nhật gói đăng ký Android trong makePurchase

Cấu trúc phẳng cho việc cập nhật gói đăng ký Android đã bị loại bỏ. Hãy chuyển oldSubVendorProductIdprorationMode vào một object lồng nhau tên là subscriptionUpdateParams, và giữ isOfferPersonalized ở cấp cao nhất. Xem Thực hiện mua hàng để xem ví dụ đầy đủ.

Android: safe-area paddings

Tài nguyên boolean Android <bool name="adapty_paywall_enable_safe_area_paddings">…</bool> đã bị xóa. Hãy xóa nó khỏi res/values/bools.xml và kiểm soát safe-area paddings tại runtime bằng tham số enableSafeArea khi bạn tạo flow view. Mặc định là true cho kiểu hiển thị modal và false cho component nhúng.

Chế độ mock

Nếu bạn chạy SDK ở chế độ mock (Expo Go hoặc web preview), hãy đổi tên khóa cấu hình mock paywalls thành flows.

Thay đổi hành vi mặc định

Những thay đổi này không gây lỗi biên dịch, vì vậy hãy kiểm tra chúng trong khi chạy:

  • onAndroidSystemBack: Mặc định đã thay đổi từ đóng view sang giữ nguyên. Để khôi phục hành vi cũ, trả về true từ handler.
  • onPurchaseCompleted: Mặc định đã thay đổi từ đóng view (trừ khi người dùng hủy mua) sang luôn giữ nguyên. Để khôi phục hành vi cũ, trả về purchaseResult.type !== 'user_cancelled' từ handler.
  • onRestoreCompleted: Mặc định đã thay đổi từ đóng view sau khi khôi phục thành công sang giữ nguyên. Để khôi phục hành vi cũ, trả về true từ handler.
  • onUrlPress: Mặc định hiện tại mở URL thông qua native layer, tuân theo cài đặt trình duyệt trong ứng dụng hoặc trình duyệt ngoài từ dashboard. Ghi đè handler để tự xử lý việc mở URL.

Onboarding API không còn được hỗ trợ

Onboarding API cũ đã bị deprecated trong v4.0, thay thế bằng Flow Builder. API này vẫn hoạt động bình thường, và IDE của bạn sẽ đánh dấu các symbol bị deprecated thông qua annotation @deprecated — không có cảnh báo nào xuất hiện lúc runtime. Các symbol này sẽ bị xóa trong một bản phát hành tương lai, vì vậy hãy lên kế hoạch migration các onboarding của bạn sang Flow Builder.

Các symbol bị deprecated: getOnboarding, getOnboardingForDefaultAudience, createOnboardingView, và AdaptyOnboardingView.