Flutter. How to check that autorenewal subscription is still valid

6,836

Solution 1

==== UPDATE from 11.03.2020

Hi, I can see this post still reading by people who looking for a method of how to work with subscription in Flutter. During 2019 I made two apps with thousands installs where users can buy a renewable subscription on the 2 platforms. Until February 2020 I used for this package from Flutter team https://pub.dev/packages/in_app_purchase, BUT - there is no way to get info about the user to unsubscribe in iOS. This is not the plugin issue, but the iOS approach for the process. We should implement our own backend for security reasons (by the way Google also recommends to do the same, but still left the way to check state directly from the app).

So, after some researches, I found guys who made backend and plugin and it is free until you have less than 10 000 USD revenue for the month. https://www.revenuecat.com/ https://pub.dev/packages/purchases_flutter

I've implemented this plugin in my apps and it works like a charm. There is some good approaches that allow you to get a subscription state at any point in the app. I'm going to make an example and article, but not sure about the timing.

====

UPDATE from 15.07.2019. Just to save time. The answer below was given for an outdated plugin for payments. After that Flutter team made plugin https://pub.dev/packages/in_app_purchase and I recommend using it.

=====

The best way is to use a secure backend server for receiving Real-time Developer Notifications. But, it is possible to check status directly in the application. So, when user tries to get access to some paid functionality you can check whether his subscription is active or not. Below is the example:

Create somewhere the file with the class

import 'dart:io' show Platform;
import 'package:flutter/services.dart';
import 'package:flutter_inapp_purchase/flutter_inapp_purchase.dart';
import 'dart:async';

class SubcsriptionStatus {
static Future<bool> subscriptionStatus(
  String sku,
  [Duration duration = const Duration(days: 30),
  Duration grace = const Duration(days: 0)]) async {
    if (Platform.isIOS) {
      var history = await FlutterInappPurchase.getPurchaseHistory();

      for (var purchase in history) {
        Duration difference =
        DateTime.now().difference(purchase.transactionDate);
        if (difference.inMinutes <= (duration + grace).inMinutes &&
            purchase.productId == sku) return true;
      }
      return false;
    } else if (Platform.isAndroid) {
      var purchases = await FlutterInappPurchase.getAvailablePurchases();

      for (var purchase in purchases) {
        if (purchase.productId == sku) return true;
      }
      return false;
    }
    throw PlatformException(
        code: Platform.operatingSystem, message: "platform not supported");
  }
}

Import it where you need to check subscription status and use in Constructor. For example:

class _SubscriptionState extends State<Subscription> {
  bool userSubscribed;
  _SubscriptionState() {
  SubcsriptionStatus.subscriptionStatus(iapId, const Duration(days: 30), const 
  Duration(days: 0)).then((val) => setState(() {
  userSubscribed = val;
   }));
   }
}

In variable userSubscribed will be the state - true or false. (Please note you have to add flutter_inapp_purchase to your project).

Solution 2

There's a few ways of doing this, but I would not do this on the mobile device.

On Device like you asked for

Install Flutter Cache Manager, on start set a cache key value 'Subscription' to true with maxAgeCacheObject: Duration (days: 30). On every start check if that key still exists in the cache. If it does then it's still valid otherwise it has expired.

Suggested solution using FirebaseFunction

I would suggest setting up a backend to manage all this. This is not a task for the mobile device. You can have a Cloud Function from firebase where you pass a unique device id and it'll return whether the subscription is still valid or not. A serverless function should work for that. Pseudo steps:

  1. (On Device)When the app starts up generate a guid and make an http post request with your guid.
  2. (Server)In your serverless function save the date the request is made to your db along with the uniqueId that you sent. If your id is already in the DB then check if it's expired (date added - current date) < 30days. Return true or false from the function. True if still valid, false if not valid.
  3. (On Device) When you receive true from your function then save the generated id locally on disk and continue with what you want to do. If it's false then lock the user out or show the subscription that you want to take care of.
Share:
6,836
Timur
Author by

Timur

Updated on December 09, 2022

Comments

  • Timur
    Timur over 1 year

    My app has a 1 month autorenewal subscription. When the user clicks on a "Buy a subscription" button I am saving date of purchase to shared preferences. Then, after 1 month, I need to check is this subscription is still valid. So how can I implement it?