I would like to know how I can check if a user has an active subscription. In this case, I have created a 1 month subscription and everything is working correctly. However, in what way can I determine if a user's subscription is still active or not? I am using the in_app_purchase library, and I noticed that the way to access past purchases was updated. In my code, I modified the line final PurchaserInfo purchaserInfo = await InAppPurchase.instance.queryPastPurchases();
updating InAppPurchaseConnection.instance
to InAppPurchase.instance
. Despite this fix, I still get an error because "PurchaserInfo" is not defined. Also, I'm not sure if I'm implementing this the right way, as this is my first time working with subscriptions in Flutter. I appreciate in advance any guidance or help. thanks! :)
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:in_app_purchase/in_app_purchase.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:shared_preferences/shared_preferences.dart';
class SubscriptionStatusChecker extends StatefulWidget {
@override
_SubscriptionStatusCheckerState createState() =>
_SubscriptionStatusCheckerState();
}
class _SubscriptionStatusCheckerState extends State<SubscriptionStatusChecker> {
bool _isSubscriptionActive = false;
@override
void initState() {
super.initState();
_checkSubscriptionStatus();
}
Future<void> _checkSubscriptionStatus() async {
try {
final PurchaserInfo purchaserInfo = await InAppPurchase.instance
.queryPastPurchases();
final List<PurchaseDetails> purchases =
purchaserInfo.purchases.toList();
for (var purchase in purchases) {
if (purchase.productID == 's2424' &&
purchase.status == PurchaseStatus.purchased) {
setState(() {
_isSubscriptionActive = true;
});
break;
}
}
} catch (e) {
Fluttertoast.showToast(
msg: 'Error: $e',
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Subscription Status Checker'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Estado de la suscripción:',
style: TextStyle(fontSize: 18),
),
Text(
_isSubscriptionActive ? 'Activa' : 'Inactiva',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
],
),
),
);
}
}
class UpdatePlan extends StatefulWidget {
@override
_UpdatePlanScreenState createState() => _UpdatePlanScreenState();
}
class _UpdatePlanScreenState extends State<UpdatePlan> {
final InAppPurchase _inAppPurchase = InAppPurchase.instance;
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
static const String _productId = 's2424'
final StreamController<List<PurchaseDetails>> _purchaseUpdatedController =
StreamController<List<PurchaseDetails>>.broadcast();
Stream<List<PurchaseDetails>> get purchaseUpdatedStream =>
_purchaseUpdatedController.stream;
late StreamSubscription<List<PurchaseDetails>> _subscription;
bool _isPlanPremiumActive = false;
bool get isPlanPremiumActive => _isPlanPremiumActive;
String? _username;
@override
void initState() {
super.initState();
_loadUsername();
initialize();
}
void _loadUsername() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
_username = prefs.getString('username');
});
}
void initialize() async {
final bool available = await _inAppPurchase.isAvailable();
if (!available) {
// The store is not available. Update the UI accordingly.
return;
}
await _inAppPurchase.restorePurchases();
_subscription = _inAppPurchase.purchaseStream.listen((purchaseDetailsList) {
_handlePurchases(purchaseDetailsList);
}, onDone: () {
_subscription.cancel();
}, onError: (error) {
// Handle errors here.
});
}
void _handlePurchases(List<PurchaseDetails> purchaseDetailsList) {
for (var purchaseDetails in purchaseDetailsList) {
if (purchaseDetails.status == PurchaseStatus.purchased) {
if (purchaseDetails.productID == _productId) {
_grantPlanPremium();
_updateFirebaseSubscription(purchaseDetails);
}
} else if (purchaseDetails.status == PurchaseStatus.error) {
Fluttertoast.showToast(
msg: 'Error al realizar la compra: ${purchaseDetails.error}',
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
);
}
}
_purchaseUpdatedController.add(purchaseDetailsList);
}
void _grantPlanPremium() {
setState(() {
_isPlanPremiumActive = true;
});
}
Future<void> purchaseProduct() async {
try {
final PurchaseParam purchaseParam =
PurchaseParam(productDetails: await _getProductDetails());
await _inAppPurchase.buyNonConsumable(purchaseParam: purchaseParam);
} catch (error) {
Fluttertoast.showToast(
msg: 'Error al iniciar la compra: $error',
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
);
}
}
Future<ProductDetails> _getProductDetails() async {
final Set<String> ids = <String>{_productId};
final ProductDetailsResponse response =
await _inAppPurchase.queryProductDetails(ids);
return response.productDetails.first;
}
void _updateFirebaseSubscription(PurchaseDetails purchaseDetails) {
if (_username != null) {
_firestore.collection('users').doc(_username).update({
'subscription': true,
});
}
}
@override
void dispose() {
_subscription.cancel();
_purchaseUpdatedController.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Test'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Premium Plan: ${_isPlanPremiumActive ? 'Active' : 'Inactive'}',
style: TextStyle(fontSize: 18),
),
ElevatedButton(
onPressed: () => purchaseProduct(),
child: Text('Update VIP'),
),
ElevatedButton(
onPressed: () => SubscriptionStatusChecker(),
child: Text('Status'),
),
],
),
),
);
}
}
I saw this thread, but, it has no response: How to check if a user have a active subscription using in_app_purchase My expectation is to be able to determine whether the user has an active subscription or not.