In-App Purchases in Flutter

Samarth Agarwal
5 min readApr 2, 2019

I have been working on an amazing project using Flutter. It has been an amazing experience so far not just because Flutter is great but also because there is an amazing community of developers around. Sometimes we get help, sometimes we don’t and then we have to look for a solution when we are on our own. Adventure!

A similar situation recently arose when Apple rejected the app for the reason that it has third-party payments within the app. Apple requires that for the app to be published on the App Store, for all payments, we use Apple’s In-App Purchases that makes them the owner of 30% for all payments. So, we decide to go that way because what else can we do.

So I decided to start small and simple, Android first. So here is how I got the IAP working on Android. I haven’t got enough time to work on the iOS counterpart as of now. So here I am sharing how I managed to implement IAP in Flutter for Android.

You can follow almost the same process to get it working on iOS as well with some platform-specific changes.

First, we need to install the flutter_inapp_purchase plugin in the flutter app.

dependencies: 
...
flutter_inapp_purchase: 0.9.1

Save the file and run flutter get packages or click on Packages get in Android Studio to download the plugin files.

Now you are ready to use the FlutterInAppPurchase plugin in the app. Before we start writing the code, there are a few more things that we need to set up.

PS: You will need to get the Google Play Developer Account to proceed further. This account will be used to release your app with IAPs.

  • Log into the Google Play Developer Console and create a new app, if you haven’t already.
  • Add the following permission in your app’s manifest.
<uses-permission android:name="com.android.vending.BILLING"/>
  • Create a release build of your app with a version number and version code that is lower enough than that actual version of the app that you want in production. For example, 0.0.1+1. You can configure it in your pubspec.yaml.
  • Upload the APK file in Release Management section of the Developers Console in Production, Alpha or Beta tracks. I did that in Closed Beta so that not everyone has access to the build. In this case, I also had to assign testers to the app so that they can download the app from the Play Store.
    Keep in mind that the email that you are using for your developer account cannot be used as a tester.
  • Roll out the release and let your testers be enrolled.
  • Next, head over to the Settings in your Google Play Developers Console.
  • In the Developer Account section, select Account Details and then look for License Testing on the right. Enter the email address of your test account here. This will/can be the same email address[es] that you use for testing your beta build.
  • Save.

At this point, your testers should be able to install the Beta version of your app from the Play Store. Just below the install button, they will also see In-app Purchases text confirming that the app has IAPs. The release may take some time to reflect, so be patient.

Next, we need to create at least one IAP in the Play Console.

  • Select the app from the Developer’s Console.
  • Select Retail Presence from the left and then select In-App Products.
  • Here you can add your IAPs. Let’s quickly add one. You can add a managed product or a subscription, whichever suits your requirements. Make sure that the status is shown as Active for each IAP.

In the screenshot below, you can see that three subscriptions are added.

Note that free products are not actually free. There is no way to create an IAP with value 0. Also, it takes somewhere around half an hour for the newly created products to reflect in the app. So, be patient.

Each IAP has a unique ID that we will use in the code next to fetch it in the app.

Import the plugin on the top.

import 'package:flutter_inapp_purchase/flutter_inapp_purchase.dart';

The following code get’s you these products in the app.

List<IAPItem> _iaps = [];_initIAPs() {var result = await FlutterInappPurchase.initConnection;
print("Established IAP Connection..." + result);
_iaps = await FlutterInappPurchase.getSubscriptions(
["free", "basic_monthly", "basic_yearly"]);
for (var i = 0; i < _iaps.length; ++i) {
print(_iaps[i].title + " " + _iaps[i].price);
}
}

Now that you have the products inside the list, you can use it to display a UI to the user where they can choose the one they like. Let’s say that the user chose an IAPItem which you have stored inside the object _selectIAP.

PurchasedItem _purchasedItem;_purchaseIAP(){
try {
_purchasedItem = await FlutterInappPurchase.buySubscription(_selectedIAP.productId);
} catch (e) {
PlatformException p = e as PlatformException;
print(p.code);
print(p.message);
print(p.details);
}

You can now run the app in debug configuration on your actual device. Ensure that on your phone, you are logged into Google Play with the test account that you had specified in your Play Developer Console.

Note that IAPs cannot be tested on Android Emulators and iOS Simulators.

As the app launches, you will be able to see the following console logs.

Proceed to the payment, select an IAP and try to purchase it. You should see the following UI in your app.

Amazing right?

For the payment method, you can choose one of the two test cards, one that always approves and the one that always denies. However, if you are logged into Google Play on the device with any account other than the test account, you will have the option of making an actual payment.

Feel free to try out the test payment and once you go through the payment, you get the response that contains information like purchaseToken, transactionDate, transactionId, dataAndroid etc. All these properties are available on the object _purchasedItem .

Save the relevant information in your database or in the cloud and celebrate.

Yay! We did our very first In-app purchase but that's not the end of the story. There is a lot needed to be done in a real app when it comes to IAP. Renewals, cancelations, upgradations, downgradations but that’s for another day. Cheers.

--

--