Tutorial: So implementieren Sie In-App-Käufe in eine Flutter App
Updated: März 20, 2023
Flutter ist ein noch relativ neues Framework von Google, mit dem Sie schnell plattformübergreifende Apps erstellen können. Auf der anderen Seite gibt es noch das React Native Framework von Facebook. Flutter-Apps werden in der Regel gleichzeitig für iOS und Android erstellt. Die Purchase Library muss daher sowohl mit StoreKit als auch mit der Billing Library kompatibel sein.
Bezüglich der Architektur ist jedes Zahlungs-Plugin (einschließlich unseres Adapty Flutter SDK) ein Wrapper um die nativen Bibliotheken StoreKit und Billing Library. In unserem Fall ist es ein Wrapper um unsere eigenen Adapty iOS– und Android-SDK-Bibliotheken.
Open Source Plugins für In-App-Käufe (in app purchases) in Flutter-basierten Apps
Zu den beliebten Lösungen für Einkäufe in Flutter-Apps zählen die Open Source Plugins in_app_purchase (von Flutter entwickelt) und flutter_inapp_purchase (inoffizielles Plugin).
Ziel dieser Plugins ist die Implementierung clientseitiger Käufe. Sie bieten keine serverseitige Validierung. Sie selbst müssen Ihre eigene serverseitige Infrastruktur einrichten, um Käufe zu validieren und Analysen zu Verlängerungen, Rückerstattungen, Testversionen, Stornierungen und so weiter durchführen zu können.
Diese Plugins unterstützen normalerweise nur nach einiger Zeit neue Store-Funktionen. Aktuell unterstützen Sie weder Promo-Angebote, noch Pay-as-you-go-Funktionen oder die Vorauszahlungsfunktion für iOS.
Weil unsere Bibliothek mit unserem Server kommuniziert, haben wir diese Features:
- Server-Kaufvalidierung;
- Vollständige Unterstützung nativer Zahlungsfunktionen;
- DRY Syntax;
- Abonnement- und Kaufanalysen sowie weitere Datenerfassungen;
- A/B-Tests sowie schnelles Experimentieren mit Käufen, Preisen und Aktionszeiträumen;
- Paywalls und Promo-Angebote.
Ich möchte diesen Artikel kurz und leicht verständlich halten. Daher verlinke ich einige Artikel zu anderen Themen und Aspekten, die Sie noch vor Ihrer Arbeit an den Einkäufen für Ihre Flutter-App lesen sollten.
Die Erstellung von Käufen für iOS und Android
Als erstes müssen Sie ein Entwicklerkonto erstellen, falls Sie noch keines haben. Anschließend müssen Sie einen wöchentlichen Kauf für iOS und Android erstellen. Wie das geht, haben wir in unseren vorherigen Artikeln erklärt:
Erstellung von Käufen für Android
Danach können Sie mit der Erstellung und Konfiguration Ihres Projekts beginnen.
Erstellung und Konfiguration des Projekts
Sie müssen die folgenden technischen Einzelheiten angeben, damit Ihre Käufe sowohl in Ihrer Implementierung als auch in unserem System ausgeführt werden können.
Für iOS müssen Sie:
- Die Bundle ID angeben, die Ihr Adapty-Projekt mit Ihrer App verknüpft;
- App Store Serverbenachrichtigungen in App Store Connect einrichten, damit Sie über Abonnement-Ereignisse benachrichtigt werden;
- Das gemeinsame Geheimnis (shared secret) von App Store angeben, das der Adapty Server nutzt, um eine Verbindung mit den Apple Servern herzustellen und Käufe zu validieren.
Im Falle von Android müssen sowohl der Package Name als auch die Key File des Service Accounts angegeben werden. Der Package Name ist sozusagen die iOS-Bundle-ID für Android. Sie müssen denselben Namen verwenden, der im Code verwendet wird. Sie finden ihn in der Datei /android/app/build.gradle, die sich im Verzeichnis android.defaultConfig.applicationId befindet.
Konfiguration von Produkten und Paywalls
Das Adapty-Produkt umfasst mehrere Stores. Im Moment sind es nur der App Store und Google Play, aber wir werden in Zukunft andere Stores einführen. Die Idee hinter diesem Ansatz ist es, die plattformübergreifende Statistikerfassung zu vereinfachen und Ihnen die Arbeit mit Entities der obersten Ebene zu ermöglichen (im Gegensatz zu Identifiers).
Die Paywall ist eine abstrakte Entity, die ein Produkt-Array und eine Remote-Konfigurationsdatei (eine JSON-Datei mit den Metadaten, die Sie in Ihrem Dashboard angegeben haben) enthält. Sie codieren die Paywall-ID fest in Ihre App. Diese ID wird verwendet, um die Konfigurationsdatei und die Produktdaten abzurufen. Sie können beide bearbeiten, ohne die App aktualisieren zu müssen. In der Regel gestalten Sie die Paywall und füllen diese mit den von uns erhaltenen Daten.
Die Erstellung eines Produkts
Verwenden Sie die Google Play Console und App Store Connect, um ein Produkt zu erstellen, das einem wöchentlichen Abonnement entspricht. Geben Sie die IDs der entsprechenden Produkte ein, die Sie von Zahlungssystemen abrufen können. Beachten Sie, dass Sie dies manuell tun müssen, da App Store Connect keine API hat. Sie müssen dies jedoch nur einmal tun.
Die Erstellung einer Paywall
Achten Sie beim Erstellen einer Paywall darauf, Ihre ID in einem praktischen Format anzugeben. Diese Kennung wird später von SDK verwendet, um die Paywall-Daten anzufordern. Dies ist ein guter Ansatz, denn mit dieser Struktur müssen Sie Ihre Produkte nicht auf der Client-Seite fest codieren. Sie können bei der Produktverwaltung, Versionierung, den Tests usw. flexibel sein. Die alternative Option wäre die Nutzung von Firebase JSON mit einer Reihe von integrierten Produkten. Dies bietet jedoch keine Fehlervalidierung und ist weniger benutzerfreundlich.
Siehe da! Nachdem Sie ein Produkt und eine Paywall erstellt haben, sind Sie nun bereit für Ihren ersten Einkauf. Fahren Sie mit der Installation des SDK fort.
So verwenden Sie das SDK
Schauen Sie sich die Hauptfunktionen an, die Sie zum Konfigurieren und Verwenden von Abonnements benötigen.
Die Installation der Library
Als erstes müssen Sie Ihrem Projekt die Library adapty_flutter hinzufügen. Als nächstes fügen Sie Ihrer pubspec.yaml-Datei die folgende Abhängigkeit hinzu:
dependencies:
adapty_flutter: ^1.0.4
Führen Sie nun dies aus:
flutter pub get
Nun können Sie Adapty SDK wie folgt in Ihre App importieren:
import 'package:adapty_flutter/adapty_flutter.dart';
Konfiguration
Es ist wichtig, dass Sie Ihre App so konfigurieren, dass sie mit Adapty funktioniert. Fügen Sie dazu das AdaptyPublicSdkKey-Flag mit Ihrem öffentlichen SDK-Key in „Info.plist“ (für iOS) oder in „AndroidManifest.xml“ (für Android) hinzu.
Sie finden Ihren SDK-Key in den Adapty-Einstellungen:
Info.plist:
<dict>
...
<key>AdaptyPublicSdkKey</key>
AndroidManifest.xml:
<application ...>
...
<meta-data
android:name="AdaptyPublicSdkKey"
android:value="PUBLIC_SDK_KEY" />
</application>
Als nächstes aktivieren Sie das SDK, indem Sie diesen Code auf der Flutter-Seite aufrufen (z. B. in der main()-Methode Ihres Projekts):
void main() {
runZoned(() async {
Adapty.activate();
final installId = await Service.getOrCreateInstallId();
await Adapty.identify(***customer-user-id***);
await Adapty.setLogLevel(AdaptyLogLevel.verbose);
runApp(MyApp());
});
}
Die Funktion Adapty.activate() aktiviert die Library Adapty_Flutter:
Future<bool> Adapty.identify(String customerUserId)
Anhand von Adapty.identify können Sie die Nutzer-ID abrufen. Adapty sendet sie an die Abonnement- und Analysesysteme, um diesem Profil Ereignisse zuzuweisen. Sie können Ihre Kunden auch anhand der Kunden-Benutzer-ID in den Profilen finden.
Adapty protokolliert Fehlermeldungen und andere wichtige Daten, damit Sie verstehen, was passiert.
Future<void> Adapty.identify(AdaptyLogLevel value)
Die Funktion können Sie einen der drei möglichen Werte auswählen:
- AdaptyLogLevel.none (Standardeinstellung): nichts wird protokolliert.
- AdaptyLogLevel.errors: Nur Fehlermeldungen werden protokolliert.
- AdaptyLogLevel.verbose: Methodenaufrufe, API-Anfragen und -Antworten sowie Fehlermeldungen werden protokolliert.
Das Abrufen von Paywalls
Führen Sie diesen Code aus, um die Paywall-Liste abzurufen:
try {
final GetPaywallsResult getPaywallsResult = await Adapty.getPaywalls(forceUpdate: Bool);
final List<AdaptyPaywall> paywalls = getPaywallsResult.paywalls;
} on AdaptyError(adaptyError) {}
catch(e) {}
Die Funktion Adapty.getPaywalls() gibt das Objekt GetPaywallsResult zurück. Dieses enthält Folgendes:
- Paywalls: Ein Paywall-Array (AdaptyPaywall). Das Modell enthält die Produktliste, die Paywall-ID, die Payload und einige andere Werte.
Das Tätigen von Käufen
Sie haben soeben das Paywall-Array abgerufen. Jetzt suchen wir nach etwas, um diese Produkte in Ihrer Benutzeroberfläche anzuzeigen. Nehmen wir an, Ihre Paywall heißt your_paywall_id:
final List<AdaptyPaywall>? paywalls = getPaywallsResult.paywalls;
myPaywall = paywalls?.firstWhere((paywall) => paywall.developerId == "your_paywall_id", orElse: null);
Mithilfe des Produkt-Arrays aus dem Produktfeld zeigen Sie alle Artikel an. Nehmen wir an, der Nutzer möchte das erste Produkt kaufen. Der Einfachheit halber gehen wir davon aus, dass es sich um das erste Element der Produktpalette handelt.
final AdaptyProduct? product = myPaywall?.products?.first;
Um den Kauf durchzuführen, rufen Sie die Funktion makePurchaseResult auf. (Beachten Sie, dies in einen Try-Catch Block einzuschließen, um weiterhin alle Fehlermeldungen von SDK zu erhalten.)
final MakePurchaseResult makePurchaseResult = await Adapty.makePurchase(product);
Nachdem die Funktion erfolgreich ausgeführt wurde, übernimmt die Variable makePurchaseResult das Ergebnis als Wert. So überprüfen Sie die Zugriffsebene nach Abschluss des Kaufs:
final isPremium = makePurchaseResult?.purchaserInfo?.accessLevels['premium']?.isActive ?? false;
Beachten Sie, dass AdaptyErrorCode.paymentCancelled bedeutet, dass der Nutzer den Kauf selbst storniert hat. Es handelt sich also nicht um eine tatsächliche Fehlermeldung.
Verwenden Sie die Methode .restorePurchases(), um Käufe wiederherzustellen:
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) {}
Denken Sie daran, dass sowohl die beiden Objekte MakePurchaseResult– und RestorePurchasesResult Informationen zum Käufer enthalten. Sie enthalten Daten zu Zugriffsebenen, Abonnements und Käufen. Normalerweise können Sie feststellen, ob der Nutzer auf die Premium-Funktionen Ihrer App zugreifen kann, indem Sie einfach seine Zugriffsebene überprüfen.
Abonnement-Status
Der Begriff „Zugriffsebene“ ist dafür gedacht, nicht die gesamte vorangegangene Transaktionskette prüfen zu müssen. Die Zugriffsebene ist ein Flag und zeigt an, auf wie viele Funktionen der App der Nutzer zugreifen kann. Hat er noch keine Einkäufe getätigt, ist seine Zugriffsebene null. Andernfalls ist sie das, was Sie für Ihr Produkt angegeben haben.
Sie können beispielsweise zwei Zugriffsebenen haben (beispielsweise Silber und Gold). Unterschiedliche Käufe schalten unterschiedliche Zugriffsebenen und Funktionen frei. Die meisten Apps haben nur eine Zugriffsebene.
Überprüfen Sie einfach, ob der Benutzer Zugriff auf eine aktive Zugriffsebene hat. Ist dem so, ist sein Abonnement aktiv. Sie können dafür die Methode .getPurchaserInfo() verwenden:
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) {}
Alternativ bietet sich auch .purchaserInfoUpdateStream an, um rechtzeitig über Änderungen der Zugriffsebene des Abonnenten informiert zu werden. So geht’s:
Adapty.purchaserInfoUpdateStream.listen((purchaserInfo) {
print('#Adapty# Purchaser Info Updated');
if (purchaserInfo.accessLevels['premium'].isActive) {
// grant access to premium features
}
});
2024 subscription benchmarks and insights
Get your free copy of our latest subscription report to stay ahead in 2024.
Fazit
Wir haben den SDK so konzipiert, dass er Ihnen hilft, Zahlungen schnell in Ihre App zu integrieren. Darüber hinaus haben wir versucht, alle anderen Schritte wie AB-Tests, Analysen und weitere Integrationen möglichst einfach zu gestalten
Wenn Ihr Umsatz weniger als 10.000 $ pro Monat beträgt, stellen wir die komplette Kauffunktion kostenlos zur Verfügung. So sparen Sie sich monatelange Arbeit und können sich auf das Wichtigste konzentrieren: Ihr Produkt.