Monday, 20 February 2023

flutter: Can't detect subscription renewal (in_app_purchase)

I'm using a tool called in_app_purchase (version: ^3.1.4 ) to manage subscriptions in my app. It's working well, and I'm able to give users access to the product they're subscribing to.

Right now, my app is in test mode. I get emails from Google to let me know if a subscription has been canceled, renewed, or if it's new.

When a subscription is renewed, I want to know about it so I can update the user's account. To do that, I use a method called restorePurchases() to check past purchases. I then compare the date of the latest purchase with the one I have stored in my FireStore database. If the new purchase is more recent than the last one, I update the user's account and give them access to the product they're subscribed to.

Bellow is how I implemented that logic:

  • initState method:

    @override
       void initState() {
         super.initState();
    
         final Stream purchaseUpdated = _inAppPurchase.purchaseStream;
         _subscription = purchaseUpdated.listen(
           (purchaseDetailsList) {
             loggy.info("I AM LISTENING....");
             _listenToPurchaseUpdated(purchaseDetailsList);
           },
           onDone: () {
             _subscription.cancel();
           },
           onError: (error) {
             // handle error here.
           },
         );
         _inAppPurchase.restorePurchases();//here I trigger the purchaseStream each time initState is called
       }
    

_listenToPurchaseUpdated method:

Future<void> _listenToPurchaseUpdated(purchaseDetailsList) async {
    for (final PurchaseDetails purchaseDetails in purchaseDetailsList) {
      if (purchaseDetails.status == PurchaseStatus.pending) {
        showPendingUI();
      } else {
        if (purchaseDetails.status == PurchaseStatus.error) {
          hendleError(purchaseDetails);
        } else if (purchaseDetails.status == PurchaseStatus.purchased ||
            purchaseDetails.status == PurchaseStatus.restored) {
          if (!mounted) return;

          final lastTransactionDate =
              await SubscriptionService().getLastTransactionDate();
          if (lastTransactionDate.isNotEmpty) {
            loggy.info(
              "last transaction date: $lastTransactionDate",
            );
          }
          loggy.info(
            "current transaction date: ${purchaseDetails.transactionDate}",
          );

          if (lastTransactionDate.isEmpty ||
              lastTransactionDate != purchaseDetails.transactionDate) {
            final bool isRecentRenewal = DateTime.fromMillisecondsSinceEpoch(
              int.parse(purchaseDetails.transactionDate!),
            ).isAfter(
              DateTime.fromMillisecondsSinceEpoch(
                int.parse(lastTransactionDate),
              ),
            );

            if (isRecentRenewal) {
              loggy.info("delivering product in progress....");
              await deliverProduct(purchaseDetails);
            }
          }
        }

        if (purchaseDetails.pendingCompletePurchase) {
          await _inAppPurchase.completePurchase(purchaseDetails);
        }
      }
    }
}

In the above method, I'm just getting the last transactionDate that was stored in FireStore and comparing it with the current transactionDate, this field can be found on:

purchaseDetails.transactionDate

Unfortunately, when the subscription is renewed, I can't detect it in the app, and the transactionDate remains the same: enter image description here



from flutter: Can't detect subscription renewal (in_app_purchase)

No comments:

Post a Comment