In app purchase subscription stream provides wrong AppStorePurchaseDetails on iOS

20 Views Asked by At

Create a single subscription in the app store connect account and run the following commands on iOS side multiple times to buy and restore subscriptions

InAppPurchase.instance.buyNonConsumable(purchaseParam: purchaseParam); or InAppPurchase.instance.restorePurchases();

For example: buyNonConsumable() and on successful test transaction, delete the app and reinstall the app. Then execute the restorePurchases() to restore your subscription.

Repeat the above step 5 to 7 times and then you will start receiving wrong and huge list of AppStorePurchaseDetails in subscription stream.

Expected results As there is only one non-consumable subscription, there should be only one transaction details object on purchasing or restoring a subscription by using the following code:

InAppPurchase.instance.buyNonConsumable(purchaseParam: purchaseParam); or InAppPurchase.instance.restorePurchases();

This feature works perfectly fine on android side.

 Future<void> _onPurchaseUpdate(
      List<PurchaseDetails> purchaseDetailsList) async {
    for (final purchaseDetails in purchaseDetailsList) {
      if (purchaseDetails.status == PurchaseStatus.canceled) {
        finishTransaction();
        paymentState.value = PaymentState.failed;
        errorMessage = "Purchase Cancelled";
        update();
        Future.delayed(Duration(seconds: 1))
            .then((value) => paymentState.value = PaymentState.init);
      }

      if (purchaseDetails.status == PurchaseStatus.purchased) {
        if (Platform.isIOS) {
          final String? IOSpurchaseToken;
          IOSpurchaseToken =
              purchaseDetails.verificationData.localVerificationData;

          if (IOSpurchaseToken.isNotEmpty &&
              IOSpurchaseToken != null &&
              IOSpurchaseToken != "") {
            print("IOS >> $IOSpurchaseToken");

            final checkPurchaseTokenParams = CheckPurchaseTokenValidityParams(
              deviceType: 'IOS',
              token: IOSpurchaseToken,
              price: _purchasePrice,
            );
            checkPurchaseTokenValidityUseCase(checkPurchaseTokenParams)
                .then((result) => result.fold(
                      (failure) {
                        errorMessage = failure.toString();

                        paymentState.value = PaymentState.failed;

                        update();
                      },
                      (SubscriptionDetails isValid) {
                        _subscriptionDetailsData = isValid;
                        SharedPrefUtility.setisPremium();

                        paymentState.value = PaymentState.success;
                        finishTransaction();

                        if (!isNavigated &&
                            !SharedPrefUtility.getIsVisitedToWelcomeScreen()) {
                          locator.get<NavigationService>().pushNamed(
                              AppRoutes.welcomePlusUser,
                              arguments: <String, dynamic>{"isFirst": false});

                          SharedPrefUtility.setIsVisitedToWelcomeScreen();

                          isNavigated = true;
                          update();
                        }
                        update();
                      },
                    ));
          }
        }

        Map? purchaseData;

        purchaseData =
            json.decode(purchaseDetails.verificationData.localVerificationData);
        final susbcriptionID = purchaseData?["productId"];
        final packageName = purchaseData?["packageName"];

        final purchaseToken = purchaseData?["purchaseToken"];

        if (purchaseData?["acknowledged"] == false) {
          final InAppPurchaseAndroidPlatformAddition androidPlatformAddition =
              InAppPurchase.instance
                  .getPlatformAddition<InAppPurchaseAndroidPlatformAddition>();
          await androidPlatformAddition.consumePurchase(purchaseDetails);
        }

        InAppPurchase.instance.completePurchase(purchaseDetails);

        final checkPurchaseTokenParams = CheckPurchaseTokenValidityParams(
            deviceType: "ANDROID",
            token: purchaseToken,
            price: _purchasePrice,
            packageName: packageName,
            subscriptionID: susbcriptionID,
            isUpgraded: _isSubscribed);
        checkPurchaseTokenValidityUseCase(checkPurchaseTokenParams)
            .then((result) => result.fold(
                  (failure) {
                    errorMessage = failure.toString();
                    paymentState.value = PaymentState.failed;
                    update();
                  },
                  (SubscriptionDetails isValid) {
                    _subscriptionDetailsData = isValid;
                    SharedPrefUtility.setisPremium();

                    paymentState.value = PaymentState.success;

                    if (!isNavigated &&
                        !SharedPrefUtility.getIsVisitedToWelcomeScreen()) {
                      locator.get<NavigationService>().pushNamed(
                          AppRoutes.welcomePlusUser,
                          arguments: <String, dynamic>{"isFirst": false});

                      SharedPrefUtility.setIsVisitedToWelcomeScreen();

                      isNavigated = true;
                      update();
                    }
                    update();
                  },
                ));

        update();
      } else if (purchaseDetails.status == PurchaseStatus.error) {
        errorMessage = purchaseDetails.error.toString();
        paymentState.value = PaymentState.failed;
        update();
      } else if (purchaseDetails.status == PurchaseStatus.restored) {
        print("Restore Purchased Called");
      }
    }

    purchaseDetailsList.clear();
  }

0

There are 0 best solutions below