How to handle Apple subscription with serverside verification

20 Views Asked by At

I am trying to implement a subscription in my flutter application, with server side verification. My code is pretty much a copy of the example of in_app_purchase package

Future<void> _listenToPurchaseUpdated(
      List<PurchaseDetails> purchaseDetailsList) async {
    for (final PurchaseDetails purchaseDetails in purchaseDetailsList) {
      if (purchaseDetails.status == PurchaseStatus.pending) {
        showPendingUI();
      } else {
        if (purchaseDetails.status == PurchaseStatus.error) {
          handleError(purchaseDetails.error!);
        } else if (purchaseDetails.status == PurchaseStatus.purchased ||
            purchaseDetails.status == PurchaseStatus.restored) {
          final bool valid = await _verifyPurchase(purchaseDetails);
          if (valid) {
            unawaited(deliverProduct(purchaseDetails));
          } else {
            _handleInvalidPurchase(purchaseDetails);
            return;
          }
        }
        if (Platform.isAndroid) {
          if (!_kAutoConsume && purchaseDetails.productID == _kConsumableId) {
            final InAppPurchaseAndroidPlatformAddition androidAddition =
                _inAppPurchase.getPlatformAddition<
                    InAppPurchaseAndroidPlatformAddition>();
            await androidAddition.consumePurchase(purchaseDetails);
          }
        }
        if (purchaseDetails.pendingCompletePurchase) {
          await _inAppPurchase.completePurchase(purchaseDetails);
        }
      }
    }
  }

My _verifyPurchase method calls backend to verify the authenticity of the purchase, and returns a validity status.

The problem with Apple implementation is that, it streams all the purchases to this method. That means that all the old purchases are going through this method. If a user is subscribed for two years, every time they open the application, this method is invoked 24 times. That is not ideal and causes problems.

I tried filtering expired transactions, but I couldn't decode the verification data on the mobile, so I cannot access expiration date.

How can I tell a new purchase, from an already verified one?

1

There are 1 best solutions below

0
AndroDevs On

By using the purchases_flutter package you can first fetch your products, show them to the users (if not yet subscribed) and than offer a buy button for each product.

Fetch products, you will geht a List of StoreProduct

  final List<StoreProduct> products = await Purchases.getProducts([
    inAppProductPremiumMonthly,
    inAppProductPremiumYearly,
  ]);

Show the StoreProduct list to users and create a buy option, something like this:

Future<void> _buyProduct(StoreProduct product) async {
try {
  showDialog(
    context: context,
    barrierDismissible: false,
    builder: (context) => const LoadingWidget(),
  );
  await Purchases.purchaseStoreProduct(product);
  widget.callback(product);
} catch (e) {
  widget.errorCallback(e);
} finally {
  if (context.mounted) {
    Navigator.pop(context);
  }
}}