Solved

How to test flutter IAP using iOS simulator?

  • 29 January 2022
  • 9 replies
  • 1044 views

Badge +5

Hi there,

I’m trying to fetch my consumable offers on my iOS simulator but I get empty products. I have performed the following steps.

  1. Set app credential from app store connect to revenue cat
  2. Enable IAP on XCode
  3. Follow https://www.revenuecat.com/docs/apple-app-store and created storekit file and uploaded to revenuecat
  4. Create product on revenue cat
  5. On iOS simulator iPhone 13, when I call fetch offers I get the error

 

```

flutter: PlatformException(23, None of the products registered in the RevenueCat dashboard could be fetched from App Store Connect (or the StoreKit Configuration file if one is being used).
This could be due to a timeout, or a problem in your configuration.
More information: https://rev.cat/why-are-offerings-empty, {code: 23, message: None of the products registered in the RevenueCat dashboard could be fetched from App Store Connect (or the StoreKit Configuration file if one is being used).
This could be due to a timeout, or a problem in your configuration.
More information: https://rev.cat/why-are-offerings-empty, underlyingErrorMessage: , readable_error_code: CONFIGURATION_ERROR, readableErrorCode: CONFIGURATION_ERROR}, null)

```

 

PS:

 

Kindly help me resolve

icon

Best answer by Gokula Krishna 24 February 2022, 17:55

View original

9 replies

Userlevel 6
Badge +8

Hey @Gokula Krishna,

Can you confirm your product identifier in your StoreKit config file matches what you entered in the RevenueCat dashboard? This typically means there’s some type of configuration error and our SDK can find the products. Additionally, I’d recommend taking a look at our docs for testing StoreKit purchases: https://docs.revenuecat.com/docs/apple-app-store#ios-14-only-testing-on-the-simulator

Our Empty Offerings guide details the rest of the common problems with this type of error, too: https://rev.cat/why-are-offerings-empty

Badge +5

@cody 

 

Here are the entire steps I have performed

 

1/ Create a new StoreKit config

 

2/ Manage schemes

 

3/ Duplicate my Runner

 

4/ Finish duplicating

 

5/ Assign StoreKit config

 

6/ Add my products

 

7/ Add my products on XCode

 

8/ Save the Public cert

 

9/ Upload to test

 

10/ Signed agreements

 

11/ My bundle ID in XCode

 

12/ My bundle ID in RC

 

13/ My Bundle ID in AppStore

 

I use the latest version of the dev tools and simulators.

 

Still it doesn’t work.

 

Kindly help

Userlevel 6
Badge +8

Hey @Gokula Krishna,

Thanks for the detailed information, it certainly seems like you have things set up correctly. Can you send over full debug logs recreating this error (from app launch)? Are you able to try on a device and see if it works there?

Badge +5

@cody 

 

This is all the logs I have

Launching lib/main.dart on iPhone 13 in debug mode...
lib/main.dart:1
Xcode build done. 26.8s
Connecting to VM Service at ws://127.0.0.1:63125/yUBk-lIEQlo=/ws
flutter: PlatformException(23, None of the products registered in the RevenueCat dashboard could be fetched from App Store Connect (or the StoreKit Configuration file if one is being used).
This could be due to a timeout, or a problem in your configuration.
More information: https://rev.cat/why-are-offerings-empty, {code: 23, message: None of the products registered in the RevenueCat dashboard could be fetched from App Store Connect (or the StoreKit Configuration file if one is being used).
This could be due to a timeout, or a problem in your configuration.
More information: https://rev.cat/why-are-offerings-empty, underlyingErrorMessage: , readable_error_code: CONFIGURATION_ERROR, readableErrorCode: CONFIGURATION_ERROR}, null)

 

This is my flutter code

// PaymentPage.dart
import 'package:adrenalib/componenets/generic.dart';
import 'package:adrenalib/constants/const_colors.dart';
import 'package:adrenalib/utils/purchases.dart';
import 'package:flutter/material.dart';
import 'package:purchases_flutter/object_wrappers.dart';

// ignore: must_be_immutable
class DemoPaymentsPage extends StatefulWidget {
DemoPaymentsPage({
Key? key,
});
@override
_PaymentState createState() => _PaymentState();
}

class _PaymentState extends State<DemoPaymentsPage> {
var _offers;
bool _isPaymentProcessing = false;

@override
void initState() {
super.initState();
this._offers = PurchaseApi.fetchOffers();
}

@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back, color: Colors.black),
onPressed: () => Navigator.of(context).pop(),
),
elevation: 6.0,
centerTitle: true,
backgroundColor: kBlue3,
title: Text('Top up credits'),
),
body: FutureBuilder<List<Offering>>(
future: this._offers,
builder: (context, snapshot) {
if (snapshot.hasData) {
if (_isPaymentProcessing) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
LoadingAnimation(
loadingText:
"Please wait your payment is being processed")
],
));
}
return Padding(
padding: EdgeInsets.fromLTRB(20, 0, 20, 0),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Purchase credits to get feedback from coach",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 25,
),
),
VerticalSpace(),
...snapshot.data!
.map((item) => ElevatedButton.icon(
onPressed: () async {
setState(() {
_isPaymentProcessing = true;
});

setState(() {
_isPaymentProcessing = false;
});
},
icon: Icon(Icons.monetization_on),
label: Text(item.availablePackages.first
.product.title)))
.toList()
],
),
),
);
}
return Text("Error occured");
})));
}
}

 

// purchases.dart
import 'package:adrenalib/models/revenuecat_iap.dart';
import 'package:adrenalib/utils/api_wrapper.dart';
import 'package:dio/dio.dart';
import 'package:flutter/services.dart';
import 'package:purchases_flutter/purchases_flutter.dart';

class PurchaseApi {
static const _apiKey = '';

static Future init() async {
try {
//await Purchases.setDebugLogsEnabled(true);
await Purchases.setup(_apiKey);
} catch (e) {
print(e);
}
}

static Future<List<Offering>> fetchOffers() async {
try {
final offerings = await Purchases.getOfferings();
List<Offering> all = offerings.all.values.toList();

return all.length == 0 ? [] : all;
} on PlatformException catch (e) {
print(e);
return [];
}
}

static Future<bool> purchasePackage(Package package) async {
try {
var res = await Purchases.purchasePackage(package);
RevenueCatIAPModel revenueCatIAPModel = new RevenueCatIAPModel(
appUserId: res.originalAppUserId,
revenueCatId: res.nonSubscriptionTransactions.last.revenueCatId,
productId: res.nonSubscriptionTransactions.last.productId);

var response = await apiSingleton.demoTopUp(revenueCatIAPModel);
if (response.status == 200) {
return true;
} else {
return false;
}
} catch (e) {
return false;
}
}
}

Notes:

  1. I run my setup on https://www.macincloud.com/
  2. I test it on simulator
Badge +5

@cody

 

Can you help me check the above issue?

Userlevel 5
Badge +8

@Gokula Krishna A couple of things to check here, although at first glance the setup seems correct: 

 

  • Could you make sure that the API key is correct? 
  • Ensure that the Configuration file is included in the target, by selecting it and then in the sidebar on the right, checking that it’s included in Target membership
  • Anything else in the debug logs that might shed some light? I.e.: other warnings that might at first glance seem unrelated? 
Badge +5

@Andy 

 

  • API key is correct I checked multiple times
  • Yes the configuration is correct
  • I can’t see any other errors apart from the above logs
Badge +5

@Andy 

 

I found it. There was a configuration error on storekit product IDs.

 

Thank you for the support.

 

 

Userlevel 5
Badge +8

I’m glad you found it! Let us know if you run into anything else. 

 

Have a great day! 

 

Reply