HiĀ Team/Community,
I have a issue at the moment where a user can not make a purchase on the Apple App Store in BOTH Production and Testing, which rules out Sandbox accounts etc (have also dived down said route).Ā The same code is working perfectly for Android.Ā
Things I have explored/tried:
- Deleting and creating sandbox accounts for Apple.
- Checked I have no outstanding agreements with Apple.
- Made sure in-app purchases in enabled.
- Tried configuringĀ the purchases_flutter package with both legacy and new api key.
- I am sure a ton more, that I donāt remember.
The error looks as follows:
flutter: \^er38;5;12mā š” now trying to purchase<ā¦>
oPurchases] - DEBUG: ā¹ļø Vending Offerings from cache
Purchases] - DEBUG: ā¹ļø makePurchase
øPurchases] - DEBUG: š° Purchasing product from package Ā - finMonitor_1500_1y_1w0 in Offering App Access
OPurchases] - DEBUG: ā¹ļø PaymentQueue updatedTransaction: finMonitor_1500_1y_1w0 (null) ((null)) (null) - 0
<SKPaymentQueue: 0x2824dfa00>: Payment completed with error: Error Domain=ASDErrorDomain Code=500 "Unhandled exception" UserInfo={NSUnderlyingError=0x282863960 {Error Domain=AMSErrorDomain Code=301 "Invalid Status Code" UserInfo={NSLocalizedDescription=Invalid Status Code, NSLocalizedFailureReason=The response has an invalid status code}}, NSLocalizedFailureReason=An unknown error occurred, NSLocalizedDescription=Unhandled exception}
oPurchases] - DEBUG: ā¹ļø PaymentQueue updatedTransaction: finMonitor_1500_1y_1w0 (null) (Error Domain=SKErrorDomain Code=0 "An unknown error occurred" UserInfo={NSLocalizedDescription=An unknown error occurred, NSUnderlyingError=0x2828602a0 {Error Domain=ASDErrorDomain Code=500 "Unhandled exception" UserInfo={NSUnderlyingError=0x282863960 {Error Domain=AMSErrorDomain Code=301 "Invalid Status Code" UserInfo={NSLocalizedDescription=Invalid Status Code, NSLocalizedFailureReason=The response has an invalid status code}}, NSLocalizedFailureReason=An unknown error occurred, NSLocalizedDescription=Unhandled exception}}}) (null) - 2
ePurchases] - ERROR: šā¼ļø There was a problem with the App Store.
Purchases] - DEBUG: š° Finishing transaction finMonitor_1500_1y_1w0 (null) ((null))
iPurchases] - DEBUG: ā¹ļø PaymentQueue removedTransaction: finMonitor_1500_1y_1w0 (null) ((null) Error Domain=SKErrorDomain Code=0 "An unknown error occurred" UserInfo={NSLocalizedDescription=An unknown error occurred, NSUnderlyingError=0x2828602a0 {Error Domain=ASDErrorDomain Code=500 "Unhandled exception" UserInfo={NSUnderlyingError=0x282863960 {Error Domain=AMSErrorDomain Code=301 "Invalid Status Code" UserInfo={NSLocalizedDescription=Invalid Status Code, NSLocalizedFailureReason=The response has an invalid status code}}, NSLocalizedFailureReason=An unknown error occurred, NSLocalizedDescription=Unhandled exception}}}) {
Ā Ā NSLocalizedDescription = "An unknown error occurred";
Ā Ā NSUnderlyingError = "Error Domain=ASDErrorDomain Code=500 \"Unhandled exception\" UserInfo={NSUnderlyingError=0x282863960 {Error Domain=AMSErrorDomain Code=301 \"Invalid Status Code\" UserInfo={NSLocalizedDescription=Invalid Status Code, NSLocalizedFailureReason=The response has an invalid status code}}, NSLocalizedFailureRea
flutter: \^pa38;5;196mā ā Paywall Upgrade - Exception caught: Error code PurchasesErrorCode.storeProblemError<ā¦>
Ā
Here is the code I am using to make the purchase:
onPressed: () async {
showLoadingBanner(context, 'Purchase is progress...');
try {
loggerInfo(logMessage: 'now trying to purchase');
_purchaserInfo = await Purchases.purchasePackage(widget.package);
loggerInfo(logMessage: 'purchase completed');
paywallData.isPro = _purchaserInfo.entitlements.all "App Access"]!.isActive;
loggerDebug(logMessage: 'is user pro? ${paywallData.isPro}');
The code continues for some dialog handling etc, but it never reaches the loggerInfo(logMessage: 'purchase completed');
The widget.package is passed from the widget above, and is fetched as follows:
return FutureBuilder(
future: _fetchOfferings(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.done && snapshot.data != null) {
Offerings offerings = snapshot.data;
final offering = offerings.current;
if (offering != null) {
final annual = offering.annual;
if (annual != null) {
return TopBarAgnosticNoIcon(
text: "Welcome!",
style: kSendButtonTextStyle(context),
uniqueHeroTag: 'purchase_screen',
child: Scaffold(
backgroundColor: Theme.of(context).backgroundColor,
body: Stack(children: r
Center(
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget><
Padding(
padding: const EdgeInsets.all(18.0),
child: Image.asset("assets/logos/finMonitor_Transparent.png"),
),
Text(
'Select the subscription plan to get started.',
textAlign: TextAlign.center,
style: kSendButtonTextStyle(context),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: PurchaseButton(package: annual),
The code used for the _fetchOfferings future function is:
Future<Offerings?> _fetchOfferings() async {
Offerings? offerings;
try {
offerings = await Purchases.getOfferings();
} on PlatformException catch (e) {
loggerError(logMessage: 'Paywall Upgrade - _fetchOfferings: Exception caught $e');
if (Platform.isAndroid) {
_showSnackBar(context, 'Issue fetching information for purchase, please check you are signed into the play store');
} else {
_showSnackBar(context, 'Issue fetching information for purchase, please check you are signed into the app store');
}
}
return offerings;
}
Lastly the the SDK is configured as shown in the documentation, with a few conditional tweaks:
await Purchases.setDebugLogsEnabled(true)
.whenComplete(() => loggerInfo(logMessage: 'setDebugLogsEnabled completed'));
if (Platform.isAndroid){
if ((username != null && username != '') && (password != null && password != '') && (custKey != null && custKey != '')) {
await Purchases.setup(apiAndroidRevenueKey, appUserId: '$username-$custKey');
}else{
await Purchases.setup(apiAndroidRevenueKey);
}
}
else if (Platform.isIOS){
if ((username != null && username != '') && (password != null && password != '') && (custKey != null && custKey != '')) {
await Purchases.setup(apiIosRevenueKey, appUserId: '$username-$custKey');
}else{
await Purchases.setup(apiIosRevenueKey);
}
loggerInfo(logMessage: 'After purchases.setup');
}
Any help will be hugely appreciated.
Ā