Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter - How to verify InAppPurchases (iOS)

I've tried to implement in-app purchases of non-consumable items but I got stuck with the verification of the purchase, atleast on iOS.
Whenever I make the function "_verifyPurchase()" just return true, everything is fine.
That's what makes me think that the verifying process is the problem.

  Future<bool> _verifyPurchase(String productID) async {
    final appState = Provider.of<AppState>(context);
    PurchaseDetails purchase = await _hasPurchased(productID);
    SharedPreferences prefs = await SharedPreferences.getInstance();
    print('verify'+purchase?.productID.toString()+(purchase?.error).toString());
    if (purchase != null &&
        (purchase.status == PurchaseStatus.purchased || purchase.transactionDate != null) &&
        _kProductIds.contains(productID)) {
      if(productID == _kProductIds[0]) {
        print('has purchased remove ads');
        prefs.setBool(productID, true);
        setState(() {
          appState.setBoughtRemoveAds = true;
        });
      }else if(productID == _kProductIds[1]){
        print('has purchased premium');
        prefs.setBool(productID, true);
        setState(() {
          appState.setBoughtPremium = true;
        });
      }
      return true;
    }
    return false;
  }

I don't want to verify the purchase server-sided and think the "_hasPurchased()" function is most likely broken

Future<PurchaseDetails> _hasPurchased(String productID) async {
    final QueryPurchaseDetailsResponse response = await InAppPurchaseConnection.instance.queryPastPurchases();
    return response.pastPurchases.firstWhere((purchase) => purchase.productID == productID,
        orElse: () => null);
  }

I've followed the tutorial by Fireship.io

Edit: minor mistake in code.

like image 607
DavidGetter Avatar asked Mar 02 '23 23:03

DavidGetter


2 Answers

After spending hours finally I was able to solve this issue, unfortunately both plugins (in_app_purchase and flutter_inapp_purchase) for flutter does not share this information very clearly how you can verify your purchase recipt, here is the example code.

solution 1: Make a post request from the app (Not Recommended)

     Future<http.Response> validateReceiptIos(receiptBody,isTest) async {
          final String url = isTest
            ? 'https://sandbox.itunes.apple.com/verifyReceipt'
             : 'https://buy.itunes.apple.com/verifyReceipt';
           return  await http.post(
           Uri.parse(url),
            headers: {
            'Accept': 'application/json',
             'Content-Type': 'application/json',
              },
            body: json.encode(receiptBody),
              );
             }

Pass the function arguments

    var receiptBody = {
    'receipt-data': purchaseDetails.verificationData.localVerificationData, // receipt key you will receive in request purchase callback function 
    'exclude-old-transactions':true,
     'password':'You can get this from App store-> In app purchase-> App specific shared secert'
     };

Solution 2: (Recommended Solution) On your API server make an API and call the [sandbox] or for [production] 3 this and then later use this api in your app.

like image 90
Usman Ali Aslam Avatar answered Mar 05 '23 16:03

Usman Ali Aslam


While I love fireship.io. This tutorial is lacking in that he doesn't teach you how to properly verify the purchase.

I also followed the tutorial but found it wanting in regards to verification. I am focused on Android doing a subscription and I came across these docs https://developer.android.com/google/play/billing/billing_library_overview#Verify which were kind of difficult to understand since I wanted to try to verify on the device.

I switched to RevenueCat https://pub.dev/packages/purchases_flutter and they handle the verification on the server side for you and I've found it to be much easier.

I hope this helps!

like image 31
BrennenRocks Avatar answered Mar 05 '23 15:03

BrennenRocks