Flutter In App Purchases with List of products | paying for App features/Digital items and Unlock them | Non Consumable.

 

Flutter In App Purchases with List of products | paying for App features/Digital items and Unlock them | Non Consumable.




NOTE: For list of digital items we need to create more than one Product IDs in our google play console which is explained in our youtube video and add them in our providermodel.dart class and we need to some changes in our UI homescreen.dart file.

1- Add these permissions to

android/app/src/main/AndroidManifest.xml

1
2
<uses-permission android:name="com.android.vending.BILLING" />   
<uses-permission android:name="android.permission.INTERNET"/>

2- Add this to dependencies block

android/app/build.gradle

1
2
3
4
5
dependencies {
 
implementation 'com.android.billingclient:billing:3.0.2'
 
}

3- Make sure you are using your own product ID



4- Add this to  pubspec.yaml file:

1
in_app_purchase: ^0.5.2

This is  main.dart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import 'package:flutter/material.dart';
import 'package:in_app_purchase/in_app_purchase.dart';
import 'homescreen.dart';
import 'package:provider/provider.dart';
 
import 'providermodel.dart';
 
 
 
void main() {
  InAppPurchaseConnection.enablePendingPurchases();
 
 
  runApp(ChangeNotifierProvider(
      create: (context) => ProviderModel(),
 
      child: MaterialApp(home: MyApp(),)));
}
 
class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}
 
class _MyAppState extends State<MyApp> {
 
 
  @override
  void initState() {
    var provider = Provider.of<ProviderModel>(context, listen: false);
provider.initialize();
    super.initState();
  }
 
 
  @override
  void dispose() {
    var provider = Provider.of<ProviderModel>(context, listen: false);
    provider.subscription.cancel();
    super.dispose();
  }
 
  @override
  Widget build(BuildContext context) {
    return HomeScreen();
  }
}

Here is our UI : homescreen.dart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import 'package:flutter/material.dart';
import 'package:in_app_purchase/in_app_purchase.dart';
import 'package:provider/provider.dart';
 
import 'providermodel.dart';
 
class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}
 
class _HomeScreenState extends State<HomeScreen> {
  InAppPurchaseConnection _iap = InAppPurchaseConnection.instance;
  @override
  void initState() {
    var provider = Provider.of<ProviderModel>(context, listen: false);
    provider.verifyPurchase();
    super.initState();
  }
  void _buyProduct(ProductDetails prod) {
    final PurchaseParam purchaseParam = PurchaseParam(productDetails: prod);
    _iap.buyNonConsumable(purchaseParam: purchaseParam);
  }
 
  @override
  Widget build(BuildContext context) {
    var provider = Provider.of<ProviderModel>(context);
// This is our app UI where we show our products
    return Scaffold(
      appBar: AppBar(
        title: Text("In App Purchase List of products"),
      ),
      body: Center(
        child: Container(
          width: 300,
          child: ListView(
            children: [
              Container(
                child: Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Container(
                    color: Colors.grey.withOpacity(0.2),
                    child: FittedBox(
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.start,
                        children: [
                          Text(
                            provider.available
                                ? "Store is Available"
                                : "Store is not Available",
                            style: TextStyle(fontSize: 22, color: Colors.green),
                          ),
                        ],
                      ),
                    ),
                  ),
                ),
              ),
              for (var prod in provider.products)
                if (provider.hasPurchased(prod.id) != null) ...[
                  Center(
                    child: Text(
// If you want to change title change it from google console in-app products section
                      "You Paid for ${prod.title} \n THANK YOU!<img draggable="false" role="img" class="emoji" alt="💕" src="https://s0.wp.com/wp-content/mu-plugins/wpcom-smileys/twemoji/2/svg/1f495.svg">",
                      textAlign: TextAlign.center,
                      style: TextStyle(fontSize: 22, color: Colors.black),
                    ),
                  ),
                  Container(
                    height: 50,
                  ),
                ] else ...[
                  Container(
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.start,
                      children: [
                        Text(
// If you want to change description change it from google console in-app products section
                          "${prod.description}",
                          style: TextStyle(fontSize: 22, color: Colors.black54),
                          textAlign: TextAlign.center,
                        ),
                        Text(
// If you want to change price change it from google console in-app products section
                          "${prod.price}",
                          style: TextStyle(fontSize: 22, color: Colors.black54),
                          textAlign: TextAlign.center,
                        ),
                        FlatButton(
                          onPressed: () => _buyProduct(prod),
                          child: Text('Pay'),
                          color: Colors.green,
                        ),
                      ],
                    ),
                  ),
                  Container(
                    height: 10,
                  )
                ]
            ],
          ),
        ),
      ),
    );
  }
}

We are using provider state management so add this to your package’s pubspec.yaml file:

provider: ^4.3.1

Our provider model: providermodel.dart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import 'dart:async';
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:in_app_purchase/in_app_purchase.dart';
import 'package:collection/collection.dart';
 
 
class ProviderModel with ChangeNotifier {
  InAppPurchaseConnection _iap = InAppPurchaseConnection.instance;
  bool available = true;
  StreamSubscription subscription;
 
// here to add more Products in this case we have 2 Product IDs
 
  final String myFirstProductID = 'in_app_payment_test';
  final String mySecondProductID = 'in_app_payment_test2';
 
// here to Create boolean for our First Product to check if its Purchased our not.
 
  bool _isFirstItemPurchased = false;
  bool get isFirstItemPurchased => _isFirstItemPurchased;
  set isFirstItemPurchased(bool value) {
    _isFirstItemPurchased = value;
    notifyListeners();
  }
 
// here to Create boolean for our Second Product to check if its Purchased our not.
 
  bool _isSecondItemPurchased = false;
  bool get isSecondItemPurchased => _isSecondItemPurchased;
  set isSecondItemPurchased(bool value) {
    _isSecondItemPurchased = value;
    notifyListeners();
  }
 
// here is the list of purchases
 
  List _purchases = [];
  List get purchases => _purchases;
  set purchases(List value) {
    _purchases = value;
    notifyListeners();
  }
 
// our product list
 
  List _products = [];
  List get products => _products;
  set products(List value) {
    _products = value;
    notifyListeners();
  }
 
// here we initialize and check our purchases
 
  void initialize() async {
    available = await _iap.isAvailable();
    if (available) {
      await _getProducts();
      await _getPastPurchases();
      verifyPurchase();
      subscription = _iap.purchaseUpdatedStream.listen((data) {
        purchases.addAll(data);
        verifyPurchase();
      });
    }
  }
 
  void verifyPurchase() {
//   here verify and complete our First Product Purchase
    PurchaseDetails purchase = hasPurchased(myFirstProductID);
    if (purchase != null && purchase.status == PurchaseStatus.purchased) {
      if (purchase.pendingCompletePurchase) {
        _iap.completePurchase(purchase);
        
if (purchase != null && purchase.status == PurchaseStatus.purchased) {
          isFirstItemPurchased = true;
        }
      }
    }
 
//   here verify and complete our second Product Purchase
 
    PurchaseDetails secondPurchase = hasPurchased(mySecondProductID);
    if (secondPurchase != null &&
        secondPurchase.status == PurchaseStatus.purchased) {
      if (secondPurchase.pendingCompletePurchase) {
        _iap.completePurchase(secondPurchase);
         
if (secondPurchase != null && secondPurchase.status == PurchaseStatus.purchased) {
         isSecondItemPurchased = true;
        }
 
      }
    }
  }
 
 PurchaseDetails hasPurchased(String productID) {
    return purchases
        .firstWhereOrNull((purchase) => purchase.productID == productID);
  }
 
  Future<void> _getProducts() async {
    Set<String> ids = Set.from([myFirstProductID, mySecondProductID]);
    ProductDetailsResponse response = await _iap.queryProductDetails(ids);
    products = response.productDetails;
  }
 
  Future<void> _getPastPurchases() async {
    QueryPurchaseDetailsResponse response = await _iap.queryPastPurchases();
    for (PurchaseDetails purchase in response.pastPurchases) {
      if (Platform.isIOS) {
        _iap.consumePurchase(purchase);
      }
    }
    purchases = response.pastPurchases;
  }
}

Popular posts from this blog

In-App Purchase with null safety in Flutter 2.5.

How to add In-App Purchase subscription in Flutter.

Flutter Native Ad Templates Implementation