jamesmontemagno / InAppBillingPlugin

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

PurchaseItemAsync continually loops without providing a result #609

Closed spenol closed 3 months ago

spenol commented 4 months ago

Bug Information

Version Number of Plugin: 7.1.0 Device Tested On: Visual Studio for Mac 2022 Simulator Tested On: 17.0 Version of VS: 17.6.12 Version of Xamarin: 5.0.0.2662 Versions of other things you are using: Essential 1.8.1

Steps to reproduce the Behavior

  1. Implement the PurchaseItem routine as set out at https://jamesmontemagno.github.io/InAppBillingPlugin/PurchaseSubscription.html
  2. Run on iOS simulator using iPad 10
  3. Log in with App Store Sandbox credentials
  4. Click 'Purchase'
  5. Purchase successfully says it's completed and the dialog box disappears.
  6. However, after a few seconds the dialog simply re-appears and asks for the purchase again.
  7. This continues on an infinite loop, and the billing.PurchaseAsync line item in PurchaseItem never completes.
  8. Eventually you close the dialog box, and the purchase variable simply returns null.

Video of issue: https://youtube.com/shorts/uFx8-VSUR0E

Expected Behavior

  1. Once the UI says the purchase completes, the 'await billing.PurchaseAsync' command should complete with the 'purchase' variable containing a successful result, rather than the UI simply looping and the 'await billing.PurchaseAsync' never completing.

Actual Behavior

  1. The 'await billing.PurchaseAsync' never completes and the UI keeps displaying the purchase form despite the UI confirming the purchase has gone through.

Code snippet

See https://jamesmontemagno.github.io/InAppBillingPlugin/PurchaseSubscription.html for the example code.

Main call to subscription:

var purchase = await Helpers.AppStorePaymentHelper.PurchaseItemAsync(ItemType.Subscription, "com.test.appname.subscription1");
Console.WriteLine($"State = {purchase.State}, Consumption state = {purchase.ConsumptionState}");

Helper code (minor modification from the original in https://jamesmontemagno.github.io/InAppBillingPlugin/PurchaseSubscription.html:

static public async Task<InAppBillingPurchase> PurchaseItemAsync(Plugin.InAppBilling.ItemType itemType, string productId)
        {
            IInAppBilling billing = CrossInAppBilling.Current;
            InAppBillingPurchase purchase = null;
            try
            {
                var connected = await billing.ConnectAsync();

                if (!connected)
                {
                    //we are offline or can't connect, don't try to purchase
                    return null;
                }

                //check purchases
                purchase = await billing.PurchaseAsync(productId, itemType);

                //possibility that a null came through.
                if (purchase == null)
                {
                    //did not purchase
                    return purchase;
                }
                else if (purchase.State == PurchaseState.Purchased)
                {
                    //only needed on android unless you turn off auto finalize
                    var ack = await CrossInAppBilling.Current.FinalizePurchaseAsync(purchase.TransactionIdentifier);

                    // Handle if acknowledge was successful or not
                    return purchase;
                }
            }
            catch (InAppBillingPurchaseException purchaseEx)
            {
                //Billing Exception handle this based on the type
                Console.WriteLine("Error: " + purchaseEx);
            }
            catch (Exception ex)
            {
                //Something else has gone wrong, log it
                Console.WriteLine("Issue connecting: " + ex);
            }
            finally
            {
                await billing.DisconnectAsync();
            }
            return purchase;
        }
hinnerkweiler commented 4 months ago

Simulator Tested On: 17.0

You might want to try on a real device. I see the same on iphone simulator but it works well when testing on real device.

jamesmontemagno commented 4 months ago

correct you must test on a real device

spenol commented 3 months ago

Thank you so much @jamesmontemagno and @hinnerkweiler, that was the solution. I'll close the ticket.