Flutter iOS: In-App Buy Listener Reflecting Outdated Purchases on Initialization
Hello everybody,
I’m integrating in-app purchases into my Flutter utility utilizing the in_app_purchase package deal. I’ve efficiently configured the whole lot for each Google Play Retailer and Apple App Retailer within the sandbox atmosphere.
Present Setup
Purchases are working nice on each platforms. I could make a subscription buy, and it displays accurately on Google Play and within the iOS sandbox.
I’ve created a Getx Controller the place I initialize the acquisition listener and the shop data. Under is the related code:
Listener Initialization in onInit:
late InAppPurchasePlatform _inAppPurchasePlatform;
@override
Future<void> onInit() async {
_inAppPurchasePlatform = InAppPurchasePlatform.occasion;
remaining Stream<Listing<PurchaseDetails>> purchaseUpdated =
_inAppPurchasePlatform.purchaseStream;
_subscription0 =
purchaseUpdated.pay attention((Listing<PurchaseDetails> purchaseDetailsList) {
_handlePurchaseUpdates(purchaseDetailsList);
}, onDone: () {
_subscription0.cancel();
print("buy listener onDone :");
}, onError: (Object error) {
print("buy listener erro :" + error.toString());
});
initStoreInfo();
tremendous.onInit();
}
initStoreInfo Implementation:
Future<void> initStoreInfo() async {
print("initStoreInfo known as:");
strive {
remaining bool isAvailable = await _inAppPurchasePlatform.isAvailable();
if (!isAvailable) {
error.worth="Retailer is unavailable. Please strive once more later.";
return;
}
print("Retailer is offered.");
remaining Listing<IAPPlanModel> fetchedPlans = await fetchIAPPlanModel();
plans.addAll(fetchedPlans);
_kProductIds.addAll(fetchedPlans
.map((plan) => plan.productId ?? '')
.the place((id) => id.isNotEmpty));
remaining ProductDetailsResponse productDetailResponse =
await _inAppPurchasePlatform
.queryProductDetails(_kProductIds.toSet());
if (productDetailResponse.error != null) {
error.worth = productDetailResponse.error!.message!;
return;
}
if (productDetailResponse.productDetails.isEmpty) {
error.worth="No merchandise out there in the intervening time.";
return;
}
// print(
// "Product Particulars Fetched: ${productDetailResponse.productDetails.map((e) =>
e.rawPrice).toList()}");
_linkPlansWithProductDetails(productDetailResponse.productDetails);
if (GetPlatform.isAndroid) {
// Set person alternative billing
remaining InAppPurchaseAndroidPlatformAddition addition =
InAppPurchasePlatformAddition.occasion!
as InAppPurchaseAndroidPlatformAddition;
unawaited(
addition.setBillingChoice(BillingChoiceMode.userChoiceBilling));
} else if (Platform.isIOS) {
//write code for ios
}
} catch (e) {
print("Error initializing retailer: $e");
error.worth = "Error initializing retailer: $e";
isLoading.worth = false;
return;
}
}
The Situation
On iOS, as quickly because the app launches and the Getx Controller is initialized, the in-app buy listener (purchaseStream) can also be initialized. Nonetheless, the listener instantly supplies a purchaseDetailsList containing earlier purchases, although no new cost has been made.
For instance, it displays the next standing on launch:
PurchaseStatus.bought
This habits is problematic as a result of I’m unable to distinguish between previous purchases (from earlier classes) and new purchases.
What I’ve Tried
I set off the billing popup by way of a button after launch, which works nice. However this subject happens earlier than any new buy is made.
My Query
Why does the purchaseStream listener return earlier purchases on iOS throughout initialization?
How can I differentiate between previous purchases and new ones?
Is there a really useful method to deal with such eventualities, guaranteeing previous purchases are usually not reprocessed?
Any assist or various implementation concepts can be tremendously appreciated!