Flutter is a relatively new framework developed by Google which lets you quickly create cross-platform apps. The other popular framework is React Native by Facebook. Flutter apps are built for both iOS and Android at once. Therefore, a purchase library must be compatible with both StoreKit and Billing Library.
Architecture-wise, any payment plugin – including our Adapty Flutter SDK – is a wrapper around the native libraries, StoreKit and Billing Library. In our case, it’s a wrapper around our own Adapty iOS and Android SDK libraries.
Open source libraries for in-app purchases in Flutter-based apps
These plugins were made to implement client-side purchases. They don’t feature server-side receipt validation. You’ll need to set up your own server-side infrastructure to validate receipts and collect payment analytics concerning renewals, refunds, trials, cancellations, and more.
What’s more, these libraries are usually slow to support new store features. Just to name a few of these, right now, they lack promo offers, pay-as-you-go features, and the pay upfront feature for iOS.
Since our library talks to our server, it features all of these:
- Purchase server validation
- Full native payment features support
- DRY syntax
- Subscriptions and purchases analytics and some other data collection
- A/B tests, as well as quick experimenting with purchases, pricing, and promo periods
- Paywalls and promo offers
To keep this article brief and easy to read, we’ll link a few articles we’ve previously written about some steps you should take before you start working on purchases for your Flutter app.
Creating purchases on iOS and Android
First, you’ll need to create a developer account if you don’t have one. Next, you’ll need to create a weekly purchase for both iOS and Android. We’ve explained how to do this in our previous articles:
Once you’re done, you can start creating and configuring your project.
Creating and configuring the project
To get your purchases running both in your implementation and our system, you’ll need to fill in these technical details.
For iOS, you’ll need to:
- Specify the Bundle ID to link your Adapty project to your app;
- Set up App Store Server Notifications in App Store Connect, so that you can be notified about subscription events;
- Specify the App Store Shared Secret, which the Adapty server will use to establish a connection to Apple’s servers and validate receipts.
For Android, both Package Name and Service Account Key File must be specified. Package name is the iOS Bundle ID for Android. You need to use the same one that’s used in the code. It can be found in the /android/app/build.gradle file, which is situated in the android.defaultConfig.applicationId directory.
Configuring products and paywalls
An Adapty product encapsulates those of various stores. It’s just the App Store and Google Play for now, but we’ll introduce other stores in future. The idea behind this approach is to make cross-platform stats collection easier, as well as let you work with top-level entities, as opposed to identifiers.
Paywall is an abstract entity that contains a product array and a remote config file (which is a JSON file containing the metadata you specified in your dashboard). You hard code the paywall ID into your app – this ID is used to retrieve the config file and product data. You can edit both of these without having to update the app. In the usual scenario, you design the paywall and fill it with the data received from us.
Creating a product
Let’s use Google Play Console and App Store Connect to create a product that corresponds to a weekly subscription. Fill in the ID of corresponding products, which you can retrieve from payment systems. It’s important to note that since App Store Connect has no API, you’ll need to do this manually. Just once, though.
Creating a paywall
When creating a paywall, the key thing is to specify its ID in a convenient format. This identifier will later be used by the SDK to request the paywall data. We believe this to be a good approach: with this architecture, there’s no need to hard code your products on the client side. You can be flexible with your product management, versioning, tests, etc. The alternative option would be Firebase JSON with a set of built-in products. This doesn’t provide error validation and isn’t as user-friendly, though.
Voila! Having created a product and a paywall, you’re now ready for your first purchase. Let’s proceed to installing the SDK.
How to use the SDK
Let’s look at the main functions we’ll need to configure and use subscriptions.
Installing the library
First, you’ll need to add the adapty_flutter library to your project. To do that, add the following dependency to your pubspec.yaml file:
After that, run:
From here, you can import Adapty SDK into your app like this:
You’ll need to configure your app to work with Adapty. To do so, add the AdaptyPublicSdkKey flag with your public SDK key into Info.plist (for iOS) or into AndroidManifest.xml (for Android).
You can find your SDK key in Adapty settings:
Next, activate the SDK by invoking this code on the Flutter side - e.g. in the main() method of your project:
The void Adapty.activate() function activates the Adapty_Flutter library:
Adapty.identify lets you retrieve the user’s id. Adapty sends it over to the subscription and analytics systems to assign events to this profile. You’ll also be able to find your clients by customerUserId in Profiles.
Adapty logs error messages and other important data to help you understand what’s going on. The function lets you choose one of the three possible values:
- AdaptyLogLevel.none (the default setting): nothing will be logged.
- AdaptyLogLevel.errors: only error messages will be logged.
- AdaptyLogLevel.verbose: method calls, API requests and responses, and error messages will be logged.
To retrieve the paywall list, run this code:
The Adapty.getPaywalls() function returns the GetPaywallsResult object that contains:
- Paywalls: A paywall array ( AdaptyPaywall ). The model contains the product list, paywall ID, custom payload, and a few other values.
In the previous step, you’ve retrieved the paywall array. Now, we’ll look for the one you need to display those products in your UI. Let’s assume this paywall is named your_paywall_id:
Next, using the product array from the products field, display all of its items. Let’s say the user wants to buy the first product. For the sake of simplicity, we’ll assume it to be the first item of the product array.
To initiate the purchase, invoke the makePurchaseResult function. (Remember to wrap this in a try-catch block to still receive all error messages from the SDK.)
Once the function has been successfully executed, the makePurchaseResult variable will take the result as its value. Here’s how to check the access level after the purchase has been completed:
Note that AdaptyErrorCode.paymentCancelled means the user canceled the purchase themselves, which means it isn’t an actual error message.
To restore purchases, use the .restorePurchases() method:
Take into account that both the MakePurchaseResult and RestorePurchasesResult objects include purchaserInfo. This object contains data about access levels, subscriptions, and purchases. Usually, you can tell whether the user can access the premium features of your app or not, just by checking their access level.
To avoid having to check through the entire preceding transaction chain, we’re introducing the term “access level.” Access level is a flag that explains how much of the app’s functionality the user can access. If they haven’t made any purchases yet, then their access level will be null. Otherwise, it’ll be what you specified for your product.
For example, you can have two access levels, namely, silver and golden. Different purchases will unlock different access levels and features. Most apps have just one access level.
To see whether the subscription is active, it’s enough to check if the user has an active access level. You can use the.getPurchaserInfo() method to do just that:
You can also subscribe to the .purchaserInfoUpdateStream stream to timely learn of any changes in the subscriber’s access level. Here’s how:
We’ve designed our SDK to help you quickly integrate payments into your app. What’s more, we’ve also tried to simplify all the other steps you might need to take, such as A/B testing, analytics, and further integrations.
We’ll provide full purchase functionality free of charge if your revenue amounts to less than $10,000 per month. Save yourself months of work and focus on the most important thing: your product.