How to Implement Subscriptions In-App Purchase in Flutter

Varun Kamani
BOSC Tech Labs Private Limited
8 min readOct 5, 2020
How to Implement Subscriptions In-App Purchase in Flutter
How to Implement Subscriptions In-App Purchase in Flutter

One way or another we build our apps to make money out of it. Sometimes we sell ads and ask users to upgrade for a better experience and sometimes we have premium content only for paid users.

Let’s add In-App Purchase in your app and get rich in no time😇

To add a premium user feature we need to add a payment gateway in our app. Configuring payment gateways are a big hassle. The easiest way to integrate payment gateway is by adding in-app purchases in your app.

So before we start I want to give you heads up that this article is going to be a little bit lengthy. We should know about each and every detail before handling the payment related things. So grab yourself a cup of coffee before you start deep diving in Subscriptions In-App Purchase in Flutter.

Before we get into the coding part let’s talk more about in-app purchases and how it is different for both the platforms.

In-app purchase products on both platforms have very few differences. Let’s see what are they.

Products in Android

  1. Consumable product: Products like in-game currency are consumable products. Once the user consumes them user can purchase it again.
  2. Non-Consumable product: These products can be bought only once and it provides a permanent benefit.
  3. Subscriptions: These products give benefits to the user for a limited amount of time. You can compare Netflix, Medium, Spotify subscriptions to these products. Subscriptions renew automatically until they’re canceled.

Products in iOS

  1. Consumable product: As same as android.
  2. Non-Consumable product: As same as android.
  3. Auto-Renewable Subscriptions: As same as android subscriptions.
  4. Non-Renewing Subscriptions: It is almost similar to Auto-Renewable Subscriptions. The only difference is it does not renew automatically.

For both iOS and Android, you can not re-purchase a subscription before it expires.

Based on your requirement you have to create products on Google Play Console and App Store Connect.

Both the platform gives features like a grace period, trial period, upgrade or downgrade a subscription, etc.

In this post, we will see how to add subscriptions in the Flutter app.

In order to test the in-app purchase, your app must have an alpha release in android.

Step 1: Create a Product

Create a product for Android

  1. Go to Google Play Console.
  2. Select the app for which you want to create a subscription.
  3. Inside menu under Monetize > Products select Subscriptions.
  4. Fill the form with the required information. Here product id is the most important field. Product id is used to uniquely identify each product.

Don’t forget to activate the newly created subscription.

Create a product for iOS

  1. Go to App Store Connect.
  2. Select the app for which you want to create a subscription.
  3. In the side menu under the in-app purchase, section select the manage option.
  4. Click on the plus sign to add new products and choose the type of subscription you want. (For this tutorial, we will select Auto-Renewable Subscription.)
  5. Enter the product name and product id. Here product id is as same as android.
  6. Choose a subscription group or create a new group.
  7. Choose a subscription group or create a new group.
  8. Fill every mandatory detail. If any detail is missing for the product then the status of the product will be Missing Metadata. Fill every detail until the status changes to Ready to Submit.

For simplicity use same product id for same products on both the platform.

User can activate any one of the product in one subscription group and user can upgrade and downgrade their subscription within the group.

Yay! You have successfully created a product for both platforms.

Now let’s go to the second step.

Step 2: Setup Testing Accounts

You must need to test the in-app purchase flow before publishing it to the stable release.

You don’t want to pay, every time you purchase a product while testing the in-app purchase flow.

For that, you have to set up a tester account for Android and iOS both.

Setup Testing Account For Android

Setting up a testing account for Android is very easy. Just follow below two steps and you are ready to test.

  1. Add the tester’s email address in the app’s license testers.
  2. Add the same email address in the app’s tester list.

Follow this detailed guide on how to add testers: Test your Google Play Billing Library integration

Setup Testing Account For iOS

Setting up a sandbox testing account for iOS is not as straight forward as Android.

  1. Go to the app store connect
  2. Go to User and Access
  3. On the left side, you will find the Tester option under Sandbox. Click on that.
  4. Click on the plus sign to add a sandbox tester.

Adding a sandbox tester is like creating a new apple id. You can not use an existing apple id as an email address for the sandbox tester. You’ll have to create a new email address for beta testing.

Tip: You can use temporary email address services to create a new sandbox tester account.

Log in with this account while processing in-app purchases in iOS.

Before we actually start coding we need to understand how in-app purchase works for Android and iOS both. Let’s see.

Step 3: Understanding How Purchase of Subscription Works

Purchase Flow reference taken from flutter_inapp_purchase
Purchase flow reference is taken from flutter_inapp_purchase

The flow of purchase for both platforms is more or less similar.

At the start of the app, you initiate a connection with Google / Apple billing server. Connection initialization may fail if billing SDK is not supported for the particular OS version.

After the connection is initialized your app subscribes to PurchaseUpdateStream of the billing server. The billing server notifies you about the status of every purchase made by the current user (inside or outside of the app from Play Store /App Store) via PurchaseUpdateStream.

After your app successfully subscribes to the PurchaseUpdateStream you load a list of all available products for the user.

The user chooses any product from the list and proceeds further to buy the product. Now following events happen.

  1. The app notifies the billing server that the current user wants to buy a product with this product id.
  2. The billing Server proceeds the purchase and returns the response.
  3. The response arrives at the app through PurchaseUpdateStream.
  4. Your app checks the status of the purchase and take the action accordingly.
  5. If the purchase was successful your app will notify your app’s back end that this user has successfully purchased a product and this is the purchase token I got from the billing server. The app’s back end will verify the purchase with the billing server before giving any benefits to the user. After successful validation, your app’s back end will mark the current user as a premium user and respond to your app.
  6. Now your app has to complete the transaction with the billing server. Completion of the transaction is a way of telling the billing server that you have successfully delivered the product to the user. Transaction completion is different for Android and iOS. In Android, you just have to complete the transaction which is successful. In iOS, you have to complete each and every transaction irrespective of the status of the transaction. Transaction completion is very important because if you don’t complete the transaction in Android, Google will refund the amount of purchase considering that the purchase was failed. In case of app crashed or network issue occurs during the transaction when the user opens the app again your app will be notified with all the uncompleted transactions through the PurchaseUpdateStream. So, you can continue the process of purchase of the product.
  7. Based on the response got from the app’s back end you will show a particular screen to the user.

Now let’s got to our last and the most important step the actual integration of in-app purchases in Flutter.

Step 4: Integrate In-App Purchase With Flutter

This is the most important step of all steps. You’ll have to handle the purchase and payment related details. You have to handle each and every possible exception that can happen during purchasing a product.

If you have understood the flow of purchase of subscription then this step will make more sense to you.

So let’s code.

I used the flutter_inapp_purchase plugin for my in-app purchase project. The reason for that was I find this plugin well documented and easy to understand.

To manage our code we will create one new file called payment_service.dart.

Now let’s create some variables to store the data and stream to listen to the latest status of all purchases.

If view(UI) want to get the latest updates then it can subscribe with the following methods and it can also cancel the subscription.

PaymentService will use the following methods to notify all the listeners.

Create initConnection and dispose method inside PaymentService. Don’t forget to call the initConnection method at the startup of your app.

Handle purchase errors using following method.

Now let’s see how to handle purchase updates.

Create two separate methods for Android and iOS to handle purchase updates. In iOS call finishTransaction in each case. In Android call finishTransaction only when the status is PURCHASED.

Now let’s verify the purchase if the status is a success.

in _verifyPurchase call the API of your back end to verify the purchase and based on the response handle the UI.

To get all the available products call the _getItems() in initConnection().

If you have noticed that in initConnection we are calling the _getPastPurchases() method. In iOS, this method returns all the purchases made in past(only finished). Another use of this method in iOS is when the user changes the device and you want to allow the user to restore his/her purchases then call this method. In Android, this method returns only active subscriptions (finished & unfinished both).

To buy the product call the following method.

If any error occurs during the transaction in iOS then the next time when the user will open the app the same purchased item will arrive at PurchaseUpdateStream. In Android, you will get the unfinished transaction via _pastPurchases.

Now all you have to do is call the initConnection method at the startup of your app. Get all the items from PaymentService to the UI & showcase your products. When users select a product and click on the buy button call the buyProduct() method with the selected product. Listen to the _proStatusChangedListeners and _errorListeners to handle all the scenarios.

So finally we did it.

To read more about the In-App Purchases read these official blogs.

Android: https://developer.android.com/google/play/billing/integrate

iOS: https://developer.apple.com/documentation/storekit/in-app_purchase

Check out other articles written by me.

Thank you for reading this. If you have any doubts about this article comment below.

--

--