---
title: "Samouczek: jak zaimplementować zakupy w aplikacji stworzonej za pomocą Flutter"
description: "Zakupy w aplikacji, stworzonych w Flutter za pomocą Adapty."
url: "https://adapty.io/pl/blog/in-app-purchases-for-flutter-apps/"
language: "pl"
slug: "in-app-purchases-for-flutter-apps"
category: "adapty-updates"
date: "2022-01-10T00:00:00.000Z"
date_modified: "2022-01-10T00:00:00.000Z"
author: "Alexey Goncharov"
---

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

**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](https://github.com/adaptyteam/AdaptySDK-iOS) oraz [Android SDK](https://github.com/adaptyteam/AdaptySDK-Android).

### 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](https://pub.dev/packages/in_app_purchase) (opracowana przez zespół odpowiedzialny za Flutter) oraz [flutter_inapp_purchase](https://pub.dev/packages/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](https://adapty.io/blog/ios-in-app-purchases-1/)

[Tworzenie zakupów dla Androida](https://adapty.io/blog/android-in-app-subscriptions-part-1/)

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.

![](https://adapty.io/wp-content/uploads/2023/01/61dbfcadde3e1409fe5f8314_iy6l5yif4wtrzqfjzaek9s70lntdy9bul_7h6homozvwghjkvrzry8ohu9pva-7wq18d6lyztyrc3ochoezylyispz580qelit5axr2dlrpu0dat0qjcwdbx2ecgeosqtass0c7w.png)

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 ezswlcwoiag3ixmluw25i8qerq8ybrz vj0crilc9uwnkrao9asthwrbehotn 8r7j5amw8ruxtuy2eogngkul8qubafsly9dsisdjsapx0kx2m8](https://adapty.io/wp-content/uploads/2023/01/61dbfcadc56e16884ceeda5a_34mxwyuolr8iv5x2uec0mz6-ezswlcwoiag3ixmluw25i8qerq8ybrz_vj0crilc9uwnkrao9asthwrbehotn_8r7j5amw8ruxtuy2eogngkul8qubafsly9dsisdjsapx0kx2m8.png)

#### 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 sl9nf0ixpjtzyjdk0ozq9yzn7cx7](https://adapty.io/wp-content/uploads/2023/01/61dbfcae9d2b62d615559378_zn55mgmaz86h7qtmlow-pxcwlspih63ifgswsurxtydhjlqyj3gm-jqtzo-vk8bvb3txn29f7g2oe6o2voyadhruy1lhyyvqvuo6ms5ytfq-sl9nf0ixpjtzyjdk0ozq9yzn7cx7.png)

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*:

```dart
dependencies:
  adapty_flutter: ^1.0.4
```

Następnie uruchom:

```dart
flutter pub get
```

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

```dart
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](https://app.adapty.io/settings/general):

![61dbfcaef59c49d11e233082 lsazt3ucjsc79arcgsxqdhss6j5t7gzc1ozj9kcwzet3 ouvcwuj 63wfcgl1ptjy4xpny8axipncjwfqvyks1yhf88bj2joq3qpn luafk1smbmkclwkxeehl08fbucvxi7d9tx](https://adapty.io/wp-content/uploads/2023/01/61dbfcaef59c49d11e233082_lsazt3ucjsc79arcgsxqdhss6j5t7gzc1ozj9kcwzet3-ouvcwuj-63wfcgl1ptjy4xpny8axipncjwfqvyks1yhf88bj2joq3qpn_luafk1smbmkclwkxeehl08fbucvxi7d9tx.jpg)

***Info.plist***:

```dart
<dict>
	...     
		<key>AdaptyPublicSdkKey</key>
```

AndroidManifest.xml:

```dart
<application ...>
        ...
        <meta-data
               android:name="AdaptyPublicSdkKey"
               android:value="PUBLIC_SDK_KEY" />
 </application>
```

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

```dart
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*:

```dart
Future<bool> 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](https://app.adapty.io/profiles/users).

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

```dart
Future<void> 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:

```dart
try {
  final GetPaywallsResult getPaywallsResult = await Adapty.getPaywalls(forceUpdate: Bool);
  final List<AdaptyPaywall> 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:*

```dart
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.

```dart
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.)

```dart
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:

```dart
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()*

```dart
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ć:

```dart
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ć:

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

### Wnioski

Zaprojektowaliśmy nasze [SDK](https://github.com/adaptyteam/AdaptySDK-Flutter) 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.
