---
title: "Kích hoạt mua hàng bằng cách sử dụng paywall trong Flutter SDK"
description: "Hướng dẫn nhanh để thiết lập Adapty cho việc quản lý gói đăng ký trong ứng dụng."
---

Để kích hoạt in-app purchase, bạn cần nắm vững ba khái niệm cốt lõi:

- [**Sản phẩm**](product) – bất cứ thứ gì người dùng có thể mua (gói đăng ký, consumable, quyền truy cập trọn đời)
- [**Paywall**](paywalls) là các cấu hình xác định sản phẩm nào sẽ được cung cấp. Trong Adapty, paywall là cách duy nhất để lấy sản phẩm, nhưng thiết kế này cho phép bạn thay đổi ưu đãi, giá cả và tổ hợp sản phẩm mà không cần chỉnh sửa code của ứng dụng.
- [**Placement**](placements) – nơi và thời điểm bạn hiển thị paywall trong ứng dụng (ví dụ: `main`, `onboarding`, `settings`). Bạn thiết lập paywall cho các placement trên dashboard, sau đó yêu cầu chúng bằng placement ID trong code. Điều này giúp bạn dễ dàng chạy A/B test và hiển thị các paywall khác nhau cho các nhóm người dùng khác nhau.

Adapty cung cấp ba cách để kích hoạt mua hàng trong ứng dụng của bạn. Hãy chọn một trong số đó tùy theo yêu cầu của ứng dụng:

| Cách triển khai | Độ phức tạp | Khi nào dùng |
|------------------------|------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Adapty Paywall Builder | ✅ Dễ | Bạn [tạo một paywall hoàn chỉnh, sẵn sàng để mua hàng trong no-code builder](quickstart-paywalls). Adapty tự động render và xử lý toàn bộ quy trình mua hàng phức tạp, xác thực biên lai và quản lý gói đăng ký ở phía sau. |
| Paywall tạo thủ công | 🟡 Trung bình | Bạn tự triển khai giao diện paywall trong code ứng dụng, nhưng vẫn lấy đối tượng paywall từ Adapty để duy trì sự linh hoạt trong việc cung cấp sản phẩm. Xem [hướng dẫn](flutter-quickstart-manual). |
| Chế độ Observer | 🔴 Khó | Bạn đã có cơ sở hạ tầng xử lý mua hàng riêng và muốn tiếp tục sử dụng nó. Lưu ý rằng chế độ observer có một số hạn chế trong Adapty. Xem [bài viết](observer-vs-full-mode). |

:::important
**Các bước dưới đây hướng dẫn cách triển khai paywall được tạo trong Adapty paywall builder.**

Nếu bạn không muốn sử dụng paywall builder, hãy xem [hướng dẫn xử lý mua hàng trong paywall tạo thủ công](flutter-making-purchases).
:::

Để hiển thị paywall được tạo trong Adapty paywall builder, trong code ứng dụng, bạn chỉ cần:

1. **Lấy paywall**: Lấy paywall từ Adapty.
2. **Hiển thị paywall và Adapty sẽ xử lý mua hàng cho bạn**: Hiển thị container paywall mà bạn đã lấy trong ứng dụng.
3. **Xử lý hành động nút**: Liên kết tương tác của người dùng với paywall với phản hồi của ứng dụng. Ví dụ: mở liên kết hoặc đóng paywall khi người dùng nhấn nút.

## Trước khi bắt đầu \{#before-you-start\}

Trước khi bắt đầu, hãy hoàn thành các bước sau:

1. Kết nối ứng dụng của bạn với [App Store](initial_ios) và/hoặc [Google Play](initial-android) trong Adapty Dashboard.
2. [Tạo sản phẩm](create-product) trong Adapty.
3. [Tạo paywall và thêm sản phẩm vào đó](create-paywall).
4. [Tạo placement và thêm paywall vào đó](create-placement).
5. [Cài đặt và kích hoạt SDK](sdk-installation-flutter) trong code ứng dụng của bạn.

:::tip
Cách nhanh nhất để hoàn thành các bước này là làm theo [hướng dẫn nhanh](quickstart) hoặc tạo paywall và placement bằng [Developer CLI](developer-cli-quickstart).
:::

## 1. Lấy paywall \{#1-get-the-paywall\}

Các paywall của bạn được liên kết với các placement được cấu hình trên dashboard. Placement cho phép bạn chạy các paywall khác nhau cho các đối tượng khác nhau hoặc chạy [A/B test](ab-tests).

Để lấy paywall được tạo trong Adapty paywall builder, bạn cần:

1. Lấy đối tượng `paywall` theo [placement](placements) ID bằng phương thức `getPaywall` và kiểm tra xem đó có phải là paywall được tạo trong builder hay không thông qua thuộc tính `hasViewConfiguration`.

2. Tạo paywall view bằng phương thức `createPaywallView`. View chứa các phần tử giao diện và kiểu dáng cần thiết để hiển thị paywall.

:::important
Để lấy cấu hình view, bạn phải bật toggle **Show on device** trong Paywall Builder. Nếu không, bạn sẽ nhận được cấu hình view rỗng và paywall sẽ không được hiển thị.
:::

```dart showLineNumbers

try {
  final paywall = await Adapty().getPaywall(placementId: "YOUR_PLACEMENT_ID", locale: "en");
  // the requested paywall
} on AdaptyError catch (adaptyError) {
  // handle the error
} catch (e) {
}

try {
  final view = await AdaptyUI().createPaywallView(
        paywall: paywall,
      );
} on AdaptyError catch (e) {
  // handle the error
} catch (e) {
  // handle the error
}
```

## 2. Hiển thị paywall \{#2-display-the-paywall\}

Khi bạn đã có cấu hình paywall, chỉ cần thêm vài dòng code là đủ để hiển thị paywall của mình.

Để hiển thị paywall, sử dụng phương thức `view.present()` trên `view` được tạo bởi phương thức `createPaywallView`. Mỗi `view` chỉ có thể được sử dụng một lần. Nếu bạn cần hiển thị lại paywall, hãy gọi `createPaywallView` thêm một lần nữa để tạo một instance `view` mới.

```dart showLineNumbers title="Flutter"
try {
  await view.present();
} on AdaptyError catch (e) {
  // handle the error
} catch (e) {
  // handle the error
}
```

:::tip
Để biết thêm chi tiết về cách hiển thị paywall, hãy xem [hướng dẫn](flutter-present-paywalls) của chúng tôi.
:::

## 3. Xử lý hành động nút \{#3-handle-button-actions\}

Khi người dùng nhấn các nút trong paywall, Flutter SDK tự động xử lý việc mua hàng và khôi phục. Tuy nhiên, các nút khác có ID tùy chỉnh hoặc được định nghĩa sẵn và yêu cầu xử lý hành động trong code của bạn.

Để kiểm soát hoặc theo dõi các tiến trình trên màn hình paywall, hãy triển khai các phương thức `AdaptyUIPaywallsEventsObserver` và đặt observer trước khi hiển thị bất kỳ màn hình nào. Nếu người dùng đã thực hiện một hành động nào đó, `paywallViewDidPerformAction` sẽ được gọi và ứng dụng của bạn cần phản hồi tùy theo action ID.

Ví dụ: paywall của bạn có thể có nút đóng và các URL cần mở (ví dụ: điều khoản sử dụng và chính sách bảo mật). Vì vậy, bạn cần phản hồi các hành động với ID `Close` và `OpenUrl`.

:::tip
Đọc hướng dẫn của chúng tôi về cách xử lý [hành động](flutter-handle-paywall-actions) và [sự kiện](flutter-handling-events) nút.
:::

```dart showLineNumbers title="Flutter"
class _PaywallScreenState extends State<PaywallScreen> implements AdaptyUIPaywallsEventsObserver {
  @override
  void initState() {
    super.initState();
    // Register this class as the paywalls event observer
    AdaptyUI().setPaywallsEventsObserver(this);
  }

  // This method is called when user performs an action on the paywall UI
  @override
  void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) {
    switch (action) {
      case const CloseAction():
      case const AndroidSystemBackAction():
        view.dismiss();
        break;
      case OpenUrlAction(url: final url):
        // Open the URL using url_launcher package
        _launchUrl(url);
        break;
    }
  }

  // Helper method to launch URLs
  Future<void> _launchUrl(String url) async {
    try {
      final Uri uri = Uri.parse(url);
      if (await canLaunchUrl(uri)) {
        await launchUrl(uri, mode: LaunchMode.externalApplication);
      } else {
        // Handle case where URL cannot be launched
        print('Could not launch $url');
      }
    } catch (e) {
      // Handle any errors
      print('Error launching URL: $e');
    }
  }
}

```

## Bước tiếp theo \{#next-steps\}

---
no_index: true
---
import Callout from '../../../components/Callout.astro';

<Callout type="tip">
Bạn có câu hỏi hoặc gặp sự cố? Hãy xem [diễn đàn hỗ trợ](https://adapty.featurebase.app/) của chúng tôi — nơi bạn có thể tìm câu trả lời cho các câu hỏi thường gặp hoặc đặt câu hỏi của riêng mình. Đội ngũ và cộng đồng của chúng tôi luôn sẵn sàng giúp đỡ!
</Callout>

Paywall của bạn đã sẵn sàng để hiển thị trong ứng dụng. Hãy kiểm tra mua hàng trong [sandbox App Store](test-purchases-in-sandbox) hoặc [Google Play Store](testing-on-android) để đảm bảo bạn có thể hoàn thành một lần mua thử từ paywall.

Tiếp theo, bạn cần [kiểm tra mức độ truy cập của người dùng](flutter-check-subscription-status) để đảm bảo bạn hiển thị paywall hoặc cấp quyền truy cập vào các tính năng trả phí cho đúng người dùng.

## Ví dụ đầy đủ \{#full-example\}

Đây là cách tất cả các bước đó có thể được tích hợp cùng nhau trong ứng dụng của bạn.

```dart

void main() async {
  runApp(MaterialApp(home: PaywallScreen()));
}

class PaywallScreen extends StatefulWidget {
  @override
  State<PaywallScreen> createState() => _PaywallScreenState();
}

class _PaywallScreenState extends State<PaywallScreen> implements AdaptyUIPaywallsEventsObserver {
  @override
  void initState() {
    super.initState();
    // Register this class as the paywalls event observer
    AdaptyUI().setPaywallsEventsObserver(this);
    _showPaywallIfNeeded();
  }

  Future<void> _showPaywallIfNeeded() async {
    try {

      final paywall = await Adapty().getPaywall(
        placementId: 'YOUR_PLACEMENT_ID',
      );

      if (!paywall.hasViewConfiguration) return;

      final view = await AdaptyUI().createPaywallView(paywall: paywall);

      await view.present();
    } catch (_) {
      // Handle any errors (network, SDK issues, etc.)
    }
  }

  // This method is called when user performs an action on the paywall UI
  @override
  void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) {
    switch (action) {
      case const CloseAction():
      case const AndroidSystemBackAction():
        view.dismiss();
        break;
      case OpenUrlAction(url: final url):
        // Open the URL using url_launcher package
        _launchUrl(url);
        break;
    }
  }

  // Helper method to launch URLs
  Future<void> _launchUrl(String url) async {
    try {
      final Uri uri = Uri.parse(url);
      if (await canLaunchUrl(uri)) {
        await launchUrl(uri, mode: LaunchMode.externalApplication);
      } else {
        // Handle case where URL cannot be launched
        print('Could not launch $url');
      }
    } catch (e) {
      // Handle any errors
      print('Error launching URL: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Adapty Paywall Example')),
      body: Center(
        // Add a button to re-trigger the paywall for testing purposes
        child: ElevatedButton(
          onPressed: _showPaywallIfNeeded,
          child: Text('Show Paywall'),
        ),
      ),
    );
  }
}

```