Subscriptions 101: learn how to get +23% app revenue Read more

Samouczek: jak zaimplementować zakupy w aplikacji stworzonej za pomocą Flutter

Alexey Goncharov

September 7, 2022

19 min read

Table of Contents

62fdf15a5a9626b86649d085 jp android tutorial 1 configuration 6

Flutter to stosunkowo nowy framework opracowany przez Google, który pozwala szybko tworzyć aplikacje wieloplatformowe. Innym popularnym frameworkiem jest React Native od Facebooka. Aplikacje Flutter są tworzone jednocześnie dla iOS i Androida. Dlatego też biblioteka zakupu musi być kompatybilna zarówno z StoreKit, jak i z Billing Library. 

Pod względem architektury, każda wtyczka płatności, w tym nasz ADAPTY Flutter SDK – jest opakowaniem (wrapper) wokół bibliotek natywnych, StoreKit i Billing Library. W naszym przypadku jest to wrapper wokół naszych bibliotek Adapty iOS oraz Android SDK

Biblioteki open source do zakupów w aplikacji w aplikacjach opartych na Flutter

Popularne rozwiązania do zakupów w aplikacjach Flutter to wtyczki open source in_app_purchase (opracowana przez zespół odpowiedzialny za Flutter) oraz flutter_inapp_purchase (wtyczka nieoficjalna). 

Wtyczki te zostały wykonane w celu realizacji zakupów po stronie klienta. Nie są one wyposażone w weryfikację potwierdzeń zakupu po stronie serwera (server-side). Musisz skonfigurować własną infrastrukturę po stronie serwera, aby sprawdzać potwierdzenia (receipts) i zbierać analizy płatności dotyczące odnowień, zwrotów, wersji próbnych, anulowań i tak dalej. 

Co więcej, biblioteki te są zwykle wolno aktualizowane i często nie obsługują nowych funkcji sklepu. Aby wymienić tylko kilka podobnych kwestii, w tej chwili brakuje im ofert promocyjnych (promo offers), funkcji pay-as-you-go i funkcji pay upfront dla iOS.

Ponieważ nasza biblioteka kontaktuje się z naszym serwerem, zawiera je wszystkie:

  • Walidacja serwerowa zakupu; 
  • Pełna obsługa funkcji płatności natywnych; 
  • DRY syntax;
  • Analityka subskrypcji i zakupów oraz inne zbieranie danych;
  • Testy A/B (A/B tests), a także szybkie eksperymentowanie z zakupami, cenami i okresami promocyjnymi;
  • Paywalle i oferty promocyjne.

Aby ten artykuł był krótki i łatwy do przeczytania, podamy linki do kilku artykułów, które wcześniej napisaliśmy na temat kroków, które należy podjąć przed rozpoczęciem pracy nad zakupami w ramach aplikacji, stworzonej za pomocą Flutter.

Tworzenie zakupów na iOS i Androida

Najpierw musisz utworzyć konto dewelopera, jeśli go jeszcze nie posiadasz. Następnie musisz utworzyć cotygodniowy zakup dla systemów iOS i Android. Wyjaśniliśmy, jak to zrobić w naszych poprzednich artykułach:

Tworzenie zakupów dla iOS

Tworzenie zakupów dla Androida

Po zakończeniu możesz rozpocząć tworzenie i konfigurowanie projektu.

Tworzenie i konfigurowanie projektu

Aby Twoje zakupy działały zarówno w Twojej implementacji, jak i w naszym systemie, musisz wypełnić te dane techniczne.

61dbfcadde3e1409fe5f8314 iy6l5yif4wtrzqfjzaek9s70lntdy9bul 7h6homozvwghjkvrzry8ohu9pva

W przypadku systemu iOS musisz:

  • Określić identyfikator pakietu (Bundle ID), aby połączyć projekt Adapty ze swoją aplikacją;
  • Skonfigurować powiadomienia serwera  (Server Notifications) App Store w App Store Connect, dzięki czemu będziesz powiadamiany o zdarzeniach subskrypcji (subscription events);
  • Określ App Store Shared Secret, którego serwer Adapty użyje do nawiązania połączenia z serwerami Apple i weryfikacji potwierdzeń zakupu.

W przypadku systemu Android należy podać zarówno nazwę pakietu (Package Name), jak i plik klucza konta usługi (Service Account Key File). Nazwa pakietu to identyfikator pakietu iOS (iOS Bundle ID) dla Androida. Musisz użyć tego samego, co zostało użyte w kodzie. Można to znaleźć w pliku /android/app/build.gradle, który znajduje się w katalogu android.defaultConfig.applicationId.

Konfigurowanie produktów i paywalli

Produkt Adapty zawiera je z różnych sklepów. Na razie mowa tylko o App Store i Google Play, ale w przyszłości wprowadzimy inne sklepy. Ideą tego podejścia jest ułatwienie gromadzenia statystyk między platformami, a także umożliwienie pracy z podmiotami najwyższego poziomu, w przeciwieństwie do identyfikatorów.

Paywall jest abstrakcyjnym podmiotem, który zawiera tablicę produktów i zdalny plik konfiguracyjny (który jest plikiem JSON zawierającym metadane określone w pulpicie nawigacyjnym). Twardo kodujesz paywall ID do aplikacji – ten identyfikator jest używany do pobierania pliku konfiguracyjnego i danych produktów. Możesz edytować oba bez konieczności aktualizacji aplikacji. W zwykłym scenariuszu projektujesz paywall i wypełniasz go danymi otrzymanymi od nas.

Tworzenie produktu

Skorzystajmy z konsoli Google Play i App Store Connect, aby stworzyć produkt odpowiadający tygodniowej subskrypcji. Wypełnij identyfikator powiązanych produktów, które możesz pobrać z systemów płatności. Ważne jest, aby pamiętać, że ponieważ App Store Connect nie ma interfejsu API, musisz to zrobić ręcznie. Na szczęście tylko raz. 

61dbfcadc56e16884ceeda5a 34mxwyuolr8iv5x2uec0mz6

Tworzenie paywalla

Podczas tworzenia paywalla najważniejsze jest podanie jego identyfikatora w wygodnym formacie. Identyfikator ten będzie później używany przez zestaw SDK do żądania danych paywall. Wierzymy, że jest to dobre podejście: dzięki tej architekturze nie ma potrzeby kodowania produktów po stronie klienta. Możesz być elastyczny w zarządzaniu produktem, wersjami, testach itp. Alternatywną opcją byłby Firebase JSON z zestawem wbudowanych produktów. Nie zapewnia to walidacji błędów i nie jest tak przyjazne dla użytkownika.

61dbfcae9d2b62d615559378 zn55mgmaz86h7qtmlow pxcwlspih63ifgswsurxtydhjlqyj3gm jqtzo vk8bvb3txn29f7g2oe6o2voyadhruy1lhyyvqvuo6ms5ytfq

Voila! Po utworzeniu produktu i paywalla jesteś teraz gotowy do pierwszego zakupu. Przejdźmy do instalacji SDK.

Jak korzystać z SDK

Przyjrzyjmy się głównym funkcjom, których będziemy potrzebować do skonfigurowania i korzystania z subskrypcji.

Instalacja biblioteki

Najpierw musisz dodać bibliotekę adapty_flutter do swojego projektu. Aby to zrobić, dodaj następującą zależność do swojego pliku pubspec.yaml:

dependencies:
  adapty_flutter: ^1.0.4

Następnie uruchom:

flutter pub get

Stąd możesz zaimportować Adapty SDK do swojej aplikacji w ten sposób:

import 'package:adapty_flutter/adapty_flutter.dart';

Konfiguracja

Musisz skonfigurować aplikację do pracy z Adapty. Aby to zrobić, dodaj oznaczenie AdaptyPublicSdkKey ze swoim publicznym kluczem SDK do Info.plist (dla iOS) lub do AndroidManifest.xml (dla Androida).

Klucz SDK znajdziesz w ustawieniach Adapty:

61dbfcaef59c49d11e233082 lsazt3ucjsc79arcgsxqdhss6j5t7gzc1ozj9kcwzet3 ouvcwuj

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

Następnie aktywuj SDK, wywołując ten kod po stronie Flutter – np. w metodzie main() swojego projektu:

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

Pusta funkcja Adapty.activate() aktywuje bibliotekę Adapty_Flutter:

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

Adapty.identify pozwala odzyskać identyfikator użytkownika. Adapty przesyła je do systemów subskrypcyjnych i analitycznych w celu przypisania zdarzeń do tego profilu. Będziesz mógł również znaleźć swoich klientów poprzez customerUserId w Profiles.

Adapty rejestruje komunikaty o błędach i inne ważne dane, aby pomóc ci zrozumieć, co się dzieje.

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

Funkcja pozwala wybrać jedną z trzech możliwych wartości:

  • AdaptyLogLevel.none (ustawienie domyślne): nic nie będzie rejestrowane.
  • AdaptyLogLevel.errors: rejestrowane będą tylko komunikaty o błędach. 
  • AdaptyLogLevel.verbose: będą rejestrowane wywołania metod, żądania i odpowiedzi API oraz komunikaty o błędach. 

Pobieranie paywalli

Aby pobrać listę paywalli, uruchom ten kod:

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

Funkcja Adapty.getPaywalls() zwraca obiekt GetPaywallsResult zawierający:

  • Paywalle: tablica paywalli ( AdaptyPaywall ). Model zawiera listę produktów, paywall ID, zawartość niestandardową i kilka innych wartości.

Dokonywanie zakupów 

W poprzednim kroku pobraliśmy tablicę paywall. Teraz poszukamy tego, którego potrzebujesz, aby wyświetlić te produkty w interfejsie użytkownika. Załóżmy, że ten paywall ma nazwę your_paywall_id:

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

Następnie, korzystając z tablicy produktów z pola produkty, wyświetlamy wszystkie jej elementy. Załóżmy, że użytkownik chce kupić pierwszy produkt. Dla uproszczenia przyjmiemy, że jest to pierwszy element tablicy produktów.

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

Aby zainicjować zakup, należy powołać się na funkcję makePurchaseResult. (Pamiętaj, aby otoczyć go w blok try-catch, aby nadal otrzymywać wszystkie komunikaty o błędach z SDK.)

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

Po pomyślnym wykonaniu funkcji, zmienna makePurchaseResult przyjmie wynik jako swoją wartość. Oto jak sprawdzić poziom dostępu po zakończeniu zakupu: 

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

Zauważ, że AdaptyErrorCode.paymentCancelled oznacza, że użytkownik sam anulował zakup, co oznacza, że nie jest to faktyczny komunikat o błędzie. 

Aby przywrócić zakupy, użyj metody .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) {}

Należy wziąć pod uwagę, że zarówno MakePurchaseResult, jak i obiekty RestorePurchasesResult zawierają purchaserInfo. Obiekt ten zawiera dane o poziomach dostępu, subskrypcjach i zakupach. Zazwyczaj możesz sprawdzić, czy użytkownik może uzyskać dostęp do funkcji premium Twojej aplikacji, sprawdzając poziom dostępu.

Status subskrypcji

Aby uniknąć konieczności sprawdzania poprzez cały wcześniejszy łańcuch transakcji, wprowadzamy termin “poziom dostępu.” Poziom dostępu to oznaczenie, które wyjaśnia, do jak wielu funkcji aplikacji użytkownik może uzyskać dostęp. Jeśli nie dokonał on jeszcze żadnych zakupów, jego poziom dostępu będzie zerowy. W przeciwnym razie będzie on taki, jak określiłeś dla swojego produktu.

Na przykład możesz mieć dwa poziomy dostępu, a mianowicie srebrny i złoty. Różne zakupy odblokowują różne poziomy dostępu i funkcje. Większość aplikacji ma tylko jeden poziom dostępu.

Aby sprawdzić, czy subskrypcja jest aktywna, wystarczy sprawdzić, czy użytkownik ma aktywny poziom dostępu. Możesz użyć metody the.getPurchaserInfo() aby to zrobić:

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) {}

Możesz również subskrybować strumień  .purchaserInfoUpdateStream , aby na czas dowiadywać się o wszelkich zmianach w poziomie dostępu subskrybenta. Jak to zrobić: 

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

Wnioski

Zaprojektowaliśmy nasze SDK w taki sposób, aby pomóc Ci szybko zintegrować płatności z aplikacją.  Co więcej, staraliśmy się również uprościć wszystkie inne kroki, które mogą być konieczne, takie jak testy A/B, analizy i dalsze integracje.

Zapewniamy pełną funkcjonalność zakupową bezpłatnie, jeśli przychody wynoszą mniej niż 10 000 USD miesięcznie. Zaoszczędź sobie miesięcy pracy i skup się na najważniejszej rzeczy: swoim produkcie.