Report: State of in-app subscriptions in the US 2023 Get a report

Hướng dẫn: cách triển khai tính năng mua trong ứng dụng cho ứng dụng flutter

Alexey Goncharov

Updated: March 20, 2023

Content

62fdf15a5a9626b86649d085 jp android tutorial 1 configuration 6 5

Flutter là một khung tương đối mới do Google phát triển, cho phép bạn tạo ứng dụng đa nền tảng nhanh chóng. Ngoài Flutter còn có một khung phổ biến khác là React Native của Facebook. Ứng dụng Flutter được xây dựng cùng lúc cho cả iOS và Android. Do đó, thư viện mua hàng phải tương thích với cả StoreKit và Billing Library. 

Về mặt kiến trúc, bất kỳ plugin thanh toán nào – bao gồm cả Adapty Flutter SDK của chúng tôi – đều là một trình bọc xung quanh các thư viện gốc (native), StoreKit và Billing Library. Với chúng tôi, plugin thanh toán là trình bọc xung quanh thư viện Adapty iOS Android SDK

Thư viện nguồn mở dành cho mua trong ứng dụng (in-app purchases) trong ứng dụng dựa trên Flutter

Giải pháp phổ biến cho giao dịch mua trong ứng dụng Flutter là plugin nguồn mở in_app_purchase (do đội ngũ đứng sau Flutter phát triển) và flutter_inapp_purchase (plugin không chính thức). 

Hai plugin này được tạo để triển khai giao dịch mua phía máy khách. Chúng không có xác thực biên nhận (receipt validation) phía máy chủ (server-side). Bạn sẽ cần thiết lập cơ sở hạ tầng phía máy chủ của riêng mình để xác thực biên nhận và thu thập phân tích thanh toán liên quan đến gia hạn, hoàn lại tiền, dùng thử (trial), hủy, v.v. 

Hơn nữa, các thư viện này thường chậm hỗ trợ các tính năng cửa hàng mới. Ví dụ như hiện tại, chúng thiếu ưu đãi khuyến mãi, tính năng thanh toán theo mức sử dụng (pay-as-you-go) và tính năng thanh toán trước (pay upfront) cho iOS.

Nhờ hoạt động giao tiếp với máy chủ nên thư viện của chúng tôi có tất cả những tính năng sau:

  • Xác thực máy chủ mua; 
  • Hỗ trợ đầy đủ các tính năng thanh toán gốc; 
  • Cấu trúc cú pháp DRY;
  • Phân tích gói đăng ký (subscription) và mua hàng cùng một số tính năng thu thập dữ liệu khác;
  • Thử nghiệm A/B (A/B test), cũng như thử nghiệm nhanh với mua hàng, định giá và thời gian khuyến mãi;
  • Tường phí (paywall) và ưu đãi khuyến mãi (promo offer).

Để đảm bảo bài viết này ngắn gọn và dễ đọc, chúng tôi sẽ liên kết một số bài viết trước đây của chúng tôi về những bước bạn nên thực hiện trước khi bắt tay vào làm việc với giao dịch mua cho ứng dụng Flutter của mình.

Tạo giao dịch mua trên iOS và Android

Trước tiên, bạn cần tạo tài khoản nhà phát triển nếu chưa có. Tiếp theo, bạn sẽ cần tạo giao dịch mua hàng tuần cho cả iOS và Android. Chúng tôi đã giải thích cách thực hiện việc này trong các bài viết trước đây:

Tạo giao dịch mua cho iOS

Tạo giao dịch mua cho Android

Sau khi hoàn tất, bạn có thể bắt đầu tạo và định cấu hình dự án của mình.

Tạo và cấu hình dự án

Để cho giao dịch mua chạy trong cả triển khai của bạn và hệ thống của chúng tôi, bạn cần điền các thông tin chi tiết về kỹ thuật sau.

61dbfcadde3e1409fe5f8314 iy6l5yif4wtrzqfjzaek9s70lntdy9bul 7h6homozvwghjkvrzry8ohu9pva 7wq18d6lyztyrc3ochoezylyispz580qelit5axr2dlrpu0dat0qjcwdbx2ecgeosqtass0c7w 4

Đối với iOS, bạn cần:

  • Chỉ định ID gói để liên kết dự án Adapty với ứng dụng của bạn;
  • Thiết lập Thông báo máy chủ (server notification) App Store trong App Store Connect, để nhận thông báo về sự kiện đăng ký;
  • Chỉ định Khóa bí mật chia sẻ (shared secret) App Store, máy chủ Adapty sẽ sử dụng khóa này để thiết lập kết nối tới máy chủ Apple và xác thực biên nhận.

Đối với Android, phải chỉ định cả Tên gói và Tệp khóa tài khoản dịch vụ. Tên gói là ID gói iOS dành cho Android. Bạn cần sử dụng cùng một tên gói được sử dụng trong mã. Tên gói có trong tệp /android/app/build.gradle trong thư mục android.defaultConfig.applicationId.

Cấu hình sản phẩm và tường phí

Một sản phẩm Adapty bao gồm những sản phẩm của các cửa hàng khác nhau. Hiện tại chỉ có App Store và Google Play, nhưng chúng tôi sẽ giới thiệu các cửa hàng khác trong tương lai. Ý tưởng phía sau cách tiếp cận này là làm cho việc thu thập số liệu thống kê đa nền tảng trở nên dễ dàng hơn, cũng như cho phép bạn làm việc với các thực thể cấp cao nhất, trái ngược với số nhận dạng.

Tường phí là một thực thể trừu tượng chứa mảng sản phẩm và tệp cấu hình từ xa (là tệp JSON chứa siêu dữ liệu mà bạn chỉ định trong bảng điều khiển). Bạn mã hóa cứng ID tường phí vào ứng dụng của mình – ID này dùng để truy xuất tệp cấu hình và dữ liệu sản phẩm. Bạn có thể chỉnh sửa cả hai mà không cần cập nhật ứng dụng. Thông thường, bạn thiết kế tường phí và điền vào dữ liệu nhận được từ chúng tôi.

Tạo sản phẩm

Chúng ta sẽ sử dụng Google Play Console và App Store Connect để tạo sản phẩm tương ứng với gói đăng ký hàng tuần. Điền ID của các sản phẩm tương ứng. Bạn có thể lấy ID này từ hệ thống thanh toán. Bạn cần đặc biệt lưu ý rằng vì App Store Connect không có API nên bạn sẽ phải thực hiện theo cách thủ công. Tuy nhiên, bạn chỉ cần thực hiện một lần. 

61dbfcadc56e16884ceeda5a 34mxwyuolr8iv5x2uec0mz6 ezswlcwoiag3ixmluw25i8qerq8ybrz vj0crilc9uwnkrao9asthwrbehotn 8r7j5amw8ruxtuy2eogngkul8qubafsly9dsisdjsapx0kx2m8 4

Tạo tường phí

Khi tạo tường phí, quan trọng là phải chỉ định ID ở định dạng thuận tiện. Số nhận dạng này sau đó sẽ được SDK sử dụng để yêu cầu dữ liệu tường phí. Chúng tôi tin rằng đây là cách tiếp cận phù hợp: Với kiến trúc này, bạn không cần phải mã hóa cứng sản phẩm của mình ở phía máy khách. Bạn có thể linh hoạt trong việc quản lý sản phẩm, lập phiên bản, thử nghiệm, v.v. Tùy chọn thay thế sẽ là Firebase JSON với một bộ sản phẩm tích hợp sẵn. Tuy nhiên, tùy chọn thay thế này không cung cấp tính năng xác thực lỗi và không thân thiện với người dùng.

61dbfcae9d2b62d615559378 zn55mgmaz86h7qtmlow pxcwlspih63ifgswsurxtydhjlqyj3gm jqtzo vk8bvb3txn29f7g2oe6o2voyadhruy1lhyyvqvuo6ms5ytfq sl9nf0ixpjtzyjdk0ozq9yzn7cx7 3

Vậy là xong! Sau khi tạo sản phẩm và tường phí, bạn hiện đã sẵn sàng cho giao dịch mua đầu tiên của mình. Hãy cùng chuyển sang cài đặt SDK.

Cách sử dụng SDK

Hãy cùng nghiên cứu các chức năng chính cần thiết để cấu hình và sử dụng gói đăng ký.

Cài đặt thư viện

Trước tiên, bạn cần thêm thư viện adapty_flutter vào dự án. Để làm vậy, hãy thêm phần phụ thuộc sau vào tệp pubspec.yaml:

dependencies:   adapty_flutter: ^1.0.4

Sau đó, chạy:

flutter pub get

Từ đây, bạn có thể nhập Adapty SDK vào ứng dụng như sau:

import 'package:adapty_flutter/adapty_flutter.dart';

Cấu hình

Bạn cần cấu hình ứng dụng để hoạt động với Adapty. Để làm vậy, thêm cờ AdaptyPublicSdkKey với khóa SDK công khai của bạn vào Info.plist (đối với iOS) hoặc vào AndroidManifest.xml (đối với Android).

Bạn có thể tìm khóa SDK của bản thân trong Cài đặt Adapty:

61dbfcaef59c49d11e233082 lsazt3ucjsc79arcgsxqdhss6j5t7gzc1ozj9kcwzet3 ouvcwuj 63wfcgl1ptjy4xpny8axipncjwfqvyks1yhf88bj2joq3qpn luafk1smbmkclwkxeehl08fbucvxi7d9tx 4

Info.plist:

&ltdict&gt 	...      		&ltkey&gtAdaptyPublicSdkKey&lt/key&gt

AndroidManifest.xml:

&ltapplication ...&gt         ...         &ltmeta-data                android:name="AdaptyPublicSdkKey"                android:value="PUBLIC_SDK_KEY" /&gt  &lt/application&gt

Tiếp theo, kích hoạt SDK bằng cách gọi mã này ở phía Flutter – ví dụ: trong phương thức main() của dự án:

void main() {    runZoned(() async {      Adapty.activate();      final installId = await Service.getOrCreateInstallId();      await Adapty.identify(***customer-user-id***);      await Adapty.setLogLevel(AdaptyLogLevel.verbose);      runApp(MyApp());   });  }

Hàm Adapty.activate() kiểu void kích hoạt thư viện Adapty_Flutter:

Future&ltbool&gt Adapty.identify(String customerUserId)

Adapty.identify cho phép bạn truy xuất id người dùng. Adapty gửi thông tin này tới hệ thống gói đăng ký và phân tích để gán các sự kiện cho hồ sơ này. Bạn cũng có thể tìm máy khách bằng customerUserId trong Hồ sơ.

Adapty ghi nhật ký các thông báo lỗi và dữ liệu quan trọng khác để giúp bạn nắm được những gì đang diễn ra.

Future&ltvoid&gt Adapty.identify(AdaptyLogLevel value)

Hàm cho phép bạn chọn một trong ba giá trị có thể sau:

  • AdaptyLogLevel.none (cài đặt mặc định): không ghi nhật ký
  • AdaptyLogLevel.errors: chỉ ghi nhật ký thông báo lỗi. 
  • AdaptyLogLevel.verbose: ghi nhật ký lệnh gọi phương thức, yêu cầu và phản hồi API cùng thông báo lỗi. 

Truy xuất tường phí

Để truy xuất danh sách tường phí, chạy mã sau:

try {   final GetPaywallsResult getPaywallsResult = await Adapty.getPaywalls(forceUpdate: Bool);   final List&ltAdaptyPaywall&gt paywalls = getPaywallsResult.paywalls;  } on AdaptyError(adaptyError) {}   catch(e) {}

Hàm Adapty.getPaywalls() trả về đối tượng GetPaywallsResult có chứa:

  • Tường phí: Mảng tường phí ( AdaptyPaywall ). Mô hình chứa danh sách sản phẩm, ID tường phí, tải trọng tùy chỉnh và một số giá trị khác.

Tạo giao dịch mua 

Tại bước trước, bạn đã truy xuất mảng tường phí. Bây giờ, chúng ta sẽ tìm kiếm thứ bạn cần để hiển thị các sản phẩm đó trong giao diện người dùng của mình. Giả sử tường phí này có tên là your_paywall_id:

final List<AdaptyPaywall>? paywalls = getPaywallsResult.paywalls;     myPaywall = paywalls?.firstWhere((paywall) => paywall.developerId == "your_paywall_id", orElse: null);

Tiếp theo, sử dụng mảng sản phẩm từ trường sản phẩm, hiển thị tất cả các mục trong đó. Giả sử người dùng muốn mua sản phẩm đầu tiên. Để đơn giản, chúng tôi sẽ giả định đó là mục đầu tiên của mảng sản phẩm. 

final AdaptyProduct? product = myPaywall?.products?.first;

Để bắt đầu giao dịch mua, hãy gọi hàm makePurchaseResult. (Hãy nhớ bọc trong một khối try-catch để vẫn nhận được tất cả các thông báo lỗi từ SDK.)

final MakePurchaseResult makePurchaseResult = await Adapty.makePurchase(product);

Khi đã thực thi thành công hàm, biến makePurchaseResult sẽ nhận kết quả làm giá trị của nó. Sau đây là cách kiểm tra cấp độ truy cập sau khi hoàn tất quá trình mua:

final isPremium = makePurchaseResult?.purchaserInfo?.accessLevels['premium']?.isActive ?? false;

Lưu ý rằng AdaptyErrorCode.paymentCancelled nghĩa là người dùng tự hủy giao dịch mua nên không phải là một thông báo lỗi thực sự. 

Để khôi phụ giao dịch mua, sử dụng phương thức .restorePurchases():

try { 	final RestorePurchasesResult restorePurchasesResult = await Adapty.restorePurchases(); // "premium" is an identifier of default access level   if (restorePurchasesResult?.purchaserInfo?.accessLevels['premium']?.isActive ?? false) {   	// grant access to premium features   } } on AdaptyError catch (adaptyError) {} catch (e) {}

Hãy lưu ý rằng cả hai đối tượng MakePurchaseResult vaf RestorePurchasesResult đều chứa purchaserInfo. Đối tượng này chứa dữ liệu về cấp độ truy cập, gói đăng ký và mua hàng. Thông thường, bạn có thể biết liệu người dùng có thể truy cập các tính năng cao cấp trong ứng dụng hay không chỉ bằng cách kiểm tra cấp độ truy cập của họ.

Trạng thái gói đăng ký

Để tránh phải kiểm tra toàn bộ chuỗi giao dịch trước đó, chúng tôi đã đưa ra thuật ngữ “cấp độ truy cập”. Cấp độ truy cập là cờ giải thích về mức độ mà người dùng có thể truy cập vào chức năng của ứng dụng . Nếu họ chưa thực hiện bất kỳ giao dịch mua nào thì cấp truy cập của họ sẽ bằng không. Hoặc sẽ là giá trị bạn đã chỉ định cho sản phẩm của mình.

Ví dụ: bạn có thể có hai cấp độ truy cập là bạc và vàng. Các giao dịch mua khác nhau sẽ mở khóa các cấp độ truy cập và tính năng khác nhau. Hầu hết các ứng dụng chỉ có một cấp độ truy cập.

Để xem liệu gói đăng ký có đang hoạt động hay không, chỉ cần kiểm tra xem người dùng có cấp độ truy cập đang hoạt động hay không. Bạn có thể sử dụng phương thức the.getPurchaserInfo() để kiểm tra như vậy:

try { 	AdaptyPurchaserInfo purchaserInfo = await Adapty.getPurchaserInfo();    // "premium" is an identifier of default access level   if (purchaserInfo.accessLevels['premium']?.isActive ?? false) {   	// grant access to premium features   } } on AdaptyError catch (adaptyError) {} catch (e) {}

Bạn cũng có thể đăng ký luồng .purchaserInfoUpdateStream để kịp thời nắm được bất kỳ thay đổi nào trong cấp độ truy cập của người đăng ký. Sau đây là cách thức:

Adapty.purchaserInfoUpdateStream.listen((purchaserInfo) {   print('#Adapty# Purchaser Info Updated'); 	if (purchaserInfo.accessLevels['premium'].isActive) {   	// grant access to premium features   } });

Subscribe to Adapty newsletter

Get fresh paywall ideas, subscription insights, and mobile app news every month!

Tổng kết

Chúng tôi đã thiết kế SDK theo cách giúp bạn nhanh chóng tích hợp các khoản thanh toán vào ứng dụng của mình.  Hơn nữa, chúng tôi cũng đã cố gắng đơn giản hóa tất cả các bước khác mà bạn có thể cần thực hiện, chẳng hạn như thử nghiệm AB (AB testing), phân tích và tích hợp thêm.

Chúng tôi sẽ cung cấp miễn phí đầy đủ chức năng mua nếu doanh thu của bạn dưới 10.000 USD mỗi tháng. Tiết kiệm hàng tháng trời làm việc và tập trung vào yếu tố quan trọng nhất: sản phẩm.