jamesmontemagno / InAppBillingPlugin

Cross-platform In App Billing Plugin for .NET
MIT License
651 stars 152 forks source link

Apple Review Testing IAP Failure General Error Exception #342

Closed ps10019 closed 3 years ago

ps10019 commented 3 years ago

Added code for Apple IAP. Nuget package 2.0.

IAP works in sandbox for our iPhones and iPad. When we submit app to Apple and they test IAP, it failed with General Error.

What could we be doing wrong here?

We are validating the purchase, everything works in test mode.

ps10019 commented 3 years ago

Here is our code:

    public async Task<bool> PurchaseItem(string productId, string payload)
    {

        if (!CrossInAppBilling.IsSupported)
            return false;

        var billing = CrossInAppBilling.Current;
        try
        {
            var connected = await billing.ConnectAsync();
            if (!connected)
            {
                //we are offline or can't connect, don't try to purchase
                return false;
            }

            //Verify
            var verify = DependencyService.Get<IInAppBillingVerifyPurchase>();

            //check purchases
            var purchase = await billing.PurchaseAsync(productId, ItemType.InAppPurchase, "2MP", verify);

            //possibility that a null came through.
            if (purchase == null)
            {
                var okAlertController = UIAlertController.Create("Error", "Purchase was not successful.", UIAlertControllerStyle.Alert);
                okAlertController.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
                PresentViewController(okAlertController, true, null);
                //Application.Database_UpdateTransactions(0, (decimal)0.00, DateTime.Now, purchase.Id, purchase.State.ToString());
                Application.Firebase_InsertNewTransaction((decimal)0.00, purchase.State.ToString(), purchase.Id);
                return false;
            }
            else if (purchase.State == PurchaseState.Purchased)
            {
                //purchased, we can now consume the item or do it later
                Application.SendSyslogMessage("IAP Successful Purchase - ", Application.UserLoginUsername);
                this.PerformSegue("segueMainDashboard", this);
                //Application.Database_UpdateTransactions(1, (decimal)4.99, DateTime.Now, purchase.Id, purchase.State.ToString());
                //Application.Database_InsertPurchasedTrack();
                Application.Firebase_InsertNewTransaction((decimal)4.99, purchase.State.ToString(), purchase.Id);
                Application.Firebase_RecordPurchasedTrack();
                return true;
            }
            else
            {
                Application.SendSyslogMessage("IAP FAILED Purchase - ", Application.UserLoginUsername);
                var okAlertController = UIAlertController.Create("Error", "Purchase was not successful.", UIAlertControllerStyle.Alert);
                okAlertController.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
                PresentViewController(okAlertController, true, null);
                //Application.Database_UpdateTransactions(0, (decimal)0.00, DateTime.Now, purchase.Id, purchase.State.ToString());
                Application.Firebase_InsertNewTransaction((decimal)0.00, purchase.State.ToString(), purchase.Id);
                return false;
            }

        }
        catch (InAppBillingPurchaseException purchaseEx)
        {
            Debug.WriteLine("Error: " + purchaseEx);

            Application.SendSyslogMessage("IAP FAILED Purchase Exception - ", Application.UserLoginUsername);

                var message = string.Empty;
            switch (purchaseEx.PurchaseError)
            {
                case PurchaseError.AppStoreUnavailable:
                    message = "Currently the app store seems to be unavailble. Try again later.";
                    Application.SendSyslogMessage(message, Application.UserLoginUsername);
                    var okAlertController = UIAlertController.Create("Error", message, UIAlertControllerStyle.Alert);
                    okAlertController.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
                    PresentViewController(okAlertController, true, null);
                    break;
                case PurchaseError.BillingUnavailable:
                    message = "Billing seems to be unavailable, please try again later.";
                    Application.SendSyslogMessage(message, Application.UserLoginUsername);
                    var okAlertController2 = UIAlertController.Create("Error", message, UIAlertControllerStyle.Alert);
                    okAlertController2.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
                    PresentViewController(okAlertController2, true, null);
                    break;
                case PurchaseError.PaymentInvalid:
                    message = "Payment seems to be invalid, please try again.";
                    Application.SendSyslogMessage(message, Application.UserLoginUsername);
                    var okAlertController3 = UIAlertController.Create("Error", message, UIAlertControllerStyle.Alert);
                    okAlertController3.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
                    PresentViewController(okAlertController3, true, null);
                    break;
                case PurchaseError.PaymentNotAllowed:
                    message = "Payment does not seem to be enabled/allowed, please try again.";
                    Application.SendSyslogMessage(message, Application.UserLoginUsername);
                    var okAlertController4 = UIAlertController.Create("Error", message, UIAlertControllerStyle.Alert);
                    okAlertController4.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
                    PresentViewController(okAlertController4, true, null);
                    break;
                case PurchaseError.DeveloperError:
                    message = "Developer Error, please try again.";
                    Application.SendSyslogMessage(message, Application.UserLoginUsername);
                    var okAlertController5 = UIAlertController.Create("Error", message, UIAlertControllerStyle.Alert);
                    okAlertController5.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
                    PresentViewController(okAlertController5, true, null);
                    break;
                case PurchaseError.GeneralError:
                    message = "General Error, please try again.";
                    Application.SendSyslogMessage(message, Application.UserLoginUsername);
                    var okAlertController6 = UIAlertController.Create("Error", message, UIAlertControllerStyle.Alert);
                    okAlertController6.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
                    PresentViewController(okAlertController6, true, null);
                    break;
                case PurchaseError.InvalidProduct:
                    message = "Invalid Product, please try again.";
                    Application.SendSyslogMessage(message, Application.UserLoginUsername);
                    var okAlertController7 = UIAlertController.Create("Error", message, UIAlertControllerStyle.Alert);
                    okAlertController7.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
                    PresentViewController(okAlertController7, true, null);
                    break;
                case PurchaseError.ItemUnavailable:
                    message = "Item Unavailable, please try again.";
                    Application.SendSyslogMessage(message, Application.UserLoginUsername);
                    var okAlertController8 = UIAlertController.Create("Error", message, UIAlertControllerStyle.Alert);
                    okAlertController8.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
                    PresentViewController(okAlertController8, true, null);
                    break;
                case PurchaseError.NotOwned:
                    message = "Not Owned, please try again.";
                    Application.SendSyslogMessage(message, Application.UserLoginUsername);
                    var okAlertController9 = UIAlertController.Create("Error", message, UIAlertControllerStyle.Alert);
                    okAlertController9.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
                    PresentViewController(okAlertController9, true, null);
                    break;
                case PurchaseError.ProductRequestFailed:
                    message = "Product Request Failed, please try again.";
                    Application.SendSyslogMessage(message, Application.UserLoginUsername);
                    var okAlertController10 = UIAlertController.Create("Error", message, UIAlertControllerStyle.Alert);
                    okAlertController10.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
                    PresentViewController(okAlertController10, true, null);
                    break;
                case PurchaseError.ServiceUnavailable:
                    message = "Service Unavailble, please try again.";
                    Application.SendSyslogMessage(message, Application.UserLoginUsername);
                    var okAlertController11 = UIAlertController.Create("Error", message, UIAlertControllerStyle.Alert);
                    okAlertController11.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
                    PresentViewController(okAlertController11, true, null);
                    break;
                case PurchaseError.UserCancelled:
                    message = "User Cancelled.";
                    Application.SendSyslogMessage(message, Application.UserLoginUsername);
                    var okAlertController12 = UIAlertController.Create("Error", message, UIAlertControllerStyle.Alert);
                    okAlertController12.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
                    PresentViewController(okAlertController12, true, null);
                    break;
            }

        }
        catch (Exception ex)
        {
            //Something else has gone wrong, log it
            Debug.WriteLine("Issue connecting: " + ex);
            Application.SendSyslogMessage("IAP Complete Error", Application.UserLoginUsername);

            var okAlertController = UIAlertController.Create("Error", "Error - Purchase was not successful.", UIAlertControllerStyle.Alert);
            okAlertController.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
            PresentViewController(okAlertController, true, null);

        }
        finally
        {
            await billing.DisconnectAsync();
        }

        return false;
    }
ish-1313 commented 3 years ago

did you try to test it yourself in release mode ? is it working ? are you doing server side receipt verify and is your code get called while Apple test you app ? just released ios version of my app to apple with no problems. however, i am not using nuget package, but building it from source.

p/s. it seems , that if you move your alerting code to method something like void DoAlert (string msg ) your main code will be much shorter and cleaner.

ps10019 commented 3 years ago

Good to go. Apple approved our app. I believe the issue was on Apple side. We had to open a ticket with Apple to get it fixed. It was painful and took a long time.