2026-04-25 00:00:03 +02:00
|
|
|
import 'dart:io';
|
|
|
|
|
import 'package:flutter/services.dart';
|
|
|
|
|
import 'package:purchases_flutter/purchases_flutter.dart';
|
|
|
|
|
import 'package:cid_app/global_data.dart';
|
|
|
|
|
|
|
|
|
|
class SubscriptionService {
|
2026-04-29 01:00:04 +02:00
|
|
|
static const _googleApiKey = 'goog_DsVhrIMoiOlmkzeTDXSXLkuHdoj';
|
2026-04-28 22:00:03 +02:00
|
|
|
static const _appleApiKey = 'appl_dIdoPnRhnqwYwstFZSmoABcMJRW';
|
2026-04-25 00:00:03 +02:00
|
|
|
static const entitlementID = 'pro'; // Il nome dell'entitlement su RevenueCat
|
|
|
|
|
|
|
|
|
|
static Future<void> init() async {
|
|
|
|
|
await Purchases.setLogLevel(LogLevel.debug);
|
|
|
|
|
|
|
|
|
|
PurchasesConfiguration? configuration;
|
|
|
|
|
|
|
|
|
|
if (Platform.isAndroid) {
|
2026-04-28 21:00:02 +02:00
|
|
|
configuration = PurchasesConfiguration(_googleApiKey);
|
2026-04-25 00:00:03 +02:00
|
|
|
} else if (Platform.isIOS) {
|
2026-04-28 21:00:02 +02:00
|
|
|
configuration = PurchasesConfiguration(_appleApiKey);
|
2026-04-25 00:00:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (configuration != null) {
|
|
|
|
|
await Purchases.configure(configuration);
|
|
|
|
|
await checkSubscriptionStatus();
|
|
|
|
|
|
|
|
|
|
// Ascolta i cambiamenti di stato (es. rinnovi in background)
|
|
|
|
|
Purchases.addCustomerInfoUpdateListener((customerInfo) {
|
|
|
|
|
_updateProStatus(customerInfo);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static Future<void> checkSubscriptionStatus() async {
|
|
|
|
|
try {
|
|
|
|
|
final customerInfo = await Purchases.getCustomerInfo();
|
|
|
|
|
_updateProStatus(customerInfo);
|
|
|
|
|
} on PlatformException catch (e) {
|
|
|
|
|
print('Errore controllo abbonamento: \${e.message}');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void _updateProStatus(CustomerInfo customerInfo) {
|
|
|
|
|
if (customerInfo.entitlements.all[entitlementID] != null &&
|
|
|
|
|
customerInfo.entitlements.all[entitlementID]!.isActive) {
|
|
|
|
|
GlobalData.isPro = true;
|
|
|
|
|
} else {
|
|
|
|
|
GlobalData.isPro = false;
|
|
|
|
|
}
|
|
|
|
|
// TODO: Notifica l'interfaccia utente se necessario (es. tramite un Provider o ValueNotifier)
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-25 01:00:02 +02:00
|
|
|
static Future<Offerings?> fetchOfferings() async {
|
|
|
|
|
try {
|
|
|
|
|
final offerings = await Purchases.getOfferings();
|
|
|
|
|
return offerings;
|
|
|
|
|
} on PlatformException catch (e) {
|
|
|
|
|
print('Errore fetch offerte: \${e.message}');
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-25 00:00:03 +02:00
|
|
|
static Future<bool> purchasePackage(Package package) async {
|
|
|
|
|
try {
|
|
|
|
|
final customerInfo = await Purchases.purchasePackage(package);
|
|
|
|
|
_updateProStatus(customerInfo);
|
|
|
|
|
return GlobalData.isPro;
|
|
|
|
|
} on PlatformException catch (e) {
|
|
|
|
|
final errorCode = PurchasesErrorHelper.getErrorCode(e);
|
|
|
|
|
if (errorCode != PurchasesErrorCode.purchaseCancelledError) {
|
|
|
|
|
print('Errore acquisto: \${e.message}');
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static Future<bool> restorePurchases() async {
|
|
|
|
|
try {
|
|
|
|
|
final customerInfo = await Purchases.restorePurchases();
|
|
|
|
|
_updateProStatus(customerInfo);
|
|
|
|
|
return GlobalData.isPro;
|
|
|
|
|
} on PlatformException catch (e) {
|
|
|
|
|
print('Errore ripristino: \${e.message}');
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|