I'm using the in_app_purchase package, but I only can get one plan inside the subscriptions
I have 3 subscriptions:
Basic subscription
Premium subscription
Enterprise subscription
And inside each subscription, I want to have 2 plans:
Month plan
Year plan
I always get the plan that has the "backward compatibility"("This will be the baseline returned by the deprecated Google Play Billing Library method querySkuDetailsAsync()") enabled.
Is any way to get all plans, or do I have to have 6 subscriptions with only 1 plan in each one?
Edit:
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_i18n/flutter_i18n.dart';
import 'package:in_app_purchase/in_app_purchase.dart';
import 'package:in_app_purchase_storekit/in_app_purchase_storekit.dart';
import 'package:in_app_purchase_storekit/store_kit_wrappers.dart';
import 'package:motorline_home/widgets/materials/appbar/appbar_title_widget.dart';
import 'package:motorline_home/widgets/materials/pop_button_widget.dart';
import 'package:rxdart/subjects.dart';
class SubscriptionPage extends StatefulWidget {
const SubscriptionPage({
Key? key,
}) : super(key: key);
@override
State<SubscriptionPage> createState() => _SubscriptionPageState();
}
class _SubscriptionPageState extends State<SubscriptionPage> {
// In app subscriptions
InAppPurchase _inAppPurchase = InAppPurchase.instance;
late StreamSubscription<List<PurchaseDetails>> _inAppPurchaseSubscription;
StreamController<List<ProductDetails>> _streamGooglePlaySubscriptions =
BehaviorSubject();
final List<String> _subscriptionsIDs = [
"basic",
"premium",
"enterprise",
];
@override
void initState() {
super.initState();
// In app purchase subscription
_inAppPurchaseSubscription =
_inAppPurchase.purchaseStream.listen((purchaseDetailsList) {
_listenToPurchaseUpdated(purchaseDetailsList);
}, onDone: () {
print("In app purchase onDone");
_inAppPurchaseSubscription.cancel();
}, onError: (error) {
print("In app purchase error: ${error.toString()}");
// handle error here.
_inAppPurchaseSubscription.cancel();
});
// Initialize in app purchase
_initializeInAppPurchase();
}
@override
void dispose() {
if (Platform.isIOS) {
final InAppPurchaseStoreKitPlatformAddition iosPlatformAddition =
_inAppPurchase
.getPlatformAddition<InAppPurchaseStoreKitPlatformAddition>();
iosPlatformAddition.setDelegate(null);
}
// Cancel in app purchase listener
_inAppPurchaseSubscription.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: AppBarTitleWidget(
title: FlutterI18n.translate(context, "subscriptions"),
),
leading: PopButtonWidget(),
),
// Body
body: Container(),
);
}
void _initializeInAppPurchase() async {
print("Initializing in app purchase");
bool available = await _inAppPurchase.isAvailable();
print("In app purchase initialized: $available");
if (available) {
if (Platform.isIOS) {
final InAppPurchaseStoreKitPlatformAddition iosPlatformAddition =
_inAppPurchase
.getPlatformAddition<InAppPurchaseStoreKitPlatformAddition>();
await iosPlatformAddition.setDelegate(ExamplePaymentQueueDelegate());
}
// Get subscriptions
List<ProductDetails> subscriptions = await _getSubscriptions(
productIds:
_subscriptionsIDs.toSet(),
);
// Sort by price
subscriptions.sort((a, b) => a.rawPrice.compareTo(b.rawPrice));
// Add subscriptions to stream
_streamGooglePlaySubscriptions.add(subscriptions);
// DEBUG: Print subscriptions
print("In app purchase subscription subscriptions: ${subscriptions}");
for (var subscription in subscriptions) {
print("In app purchase plan: ${subscription.id}: ${subscription.rawPrice}");
print("In app purchase description: ${subscription.description}");
// HOW GET ALL PLANS IN EACH SUBSCRIPTION ID?
}
await InAppPurchase.instance.restorePurchases();
}
}
// In app purchase updates
void _listenToPurchaseUpdated(List<PurchaseDetails> purchaseDetailsList) {
purchaseDetailsList.forEach((PurchaseDetails purchaseDetails) async {
// If purchase is pending
if (purchaseDetails.status == PurchaseStatus.pending) {
print("In app purchase pending...");
// Show pending ui
} else {
if (purchaseDetails.status == PurchaseStatus.canceled) {
print("In app purchase cancelled");
}
// If purchase failed
if (purchaseDetails.status == PurchaseStatus.error) {
print("In app purchase error");
// Show error
} else if (purchaseDetails.status == PurchaseStatus.purchased ||
purchaseDetails.status == PurchaseStatus.restored) {
print("In app purchase restored or purchased");
}
if (purchaseDetails.pendingCompletePurchase) {
debugPrint("In app purchase complete purchased");
debugPrint(
"In app purchase purchase id : ${purchaseDetails.purchaseID}");
debugPrint(
"In app purchase server data : ${purchaseDetails.verificationData.serverVerificationData}");
debugPrint(
"In app purchase local data : ${purchaseDetails.verificationData.localVerificationData}");
// Verify purchase on backend
try {
// VALIDADE PURCHASE IN BACKEND
} catch (error) {
debugPrint("In app purchase error: ${error.toString()}");
}
}
}
});
}
// Get subscription
Future<List<ProductDetails>> _getSubscriptions(
{required Set<String> productIds}) async {
ProductDetailsResponse response =
await _inAppPurchase.queryProductDetails(productIds);
return response.productDetails;
}
}
/// Example implementation of the
/// [`SKPaymentQueueDelegate`](https://developer.apple.com/documentation/storekit/skpaymentqueuedelegate?language=objc).
///
/// The payment queue delegate can be implementated to provide information
/// needed to complete transactions.
class ExamplePaymentQueueDelegate implements SKPaymentQueueDelegateWrapper {
@override
bool shouldContinueTransaction(
SKPaymentTransactionWrapper transaction, SKStorefrontWrapper storefront) {
return true;
}
@override
bool shouldShowPriceConsent() {
return false;
}
}
What you like to do is not possible. You need to create for each subscription a new plan, you can't say a Premium Subscription does have a yearly and a monthly plan.