jamesmontemagno / InAppBillingPlugin

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

Subscription Purchase Fails with "GeneralError" on iOS (Sandbox) When Subscription Has Duration "None" #510

Closed vppetrov closed 1 year ago

vppetrov commented 1 year ago

Bug Information

Version Number of Plugin: 6.7.0 Device Tested On: iPhone 6s, iOS 15.2.1 Simulator Tested On: - Version of VS: Community 2022, 17.4.0 Version of Xamarin: 17.4.0.301 (d17-4@96af3ae) Versions of other things you are using: -

Steps to reproduce the Behavior

Purchase subscription using the provided code (and a label to show the result) on iOS in Sandbox fails with GeneralError. The subscription is registered in App Store Connect but not verified by Apple (still in development/Sandbox). The purchase process goes through from the user's point of view but at the end there is the failure.

Additional info: The subscription has no duration defined (acceptable in App Store Connect, duration set to "None").

Purchasing a consumable product with the same code works without any issues.

Expected Behavior

Purchase process completes successfully.

Actual Behavior

User goes through the purchase process (confirmation of the purchase, sign in for Sandbox, success screen). Then a InAppBillingPurchaseException with PurchaseError set to GeneralError is thrown. The stack trace is:

An unknown error ocurred
at
Plugin.InAppBilling.InAppBillingImplementation.PurchaseAsync (System.String productId, Plugin.InAppBilling.Itemtype itemType, System.String applicationUserName) [0x0017a] in D:\a\s\src\Plugin.InAppBilling\InAppBilling.apple.cs:426
at
Plugin.InAppBilling.InAppBillingImplementation.PurchaseAsync (System.String productId, Plugin.InAppBilling.ItemType itemType, System.String obfuscatedAccountId, System.String obfuscatedProfileId) [0x00036] in D:\a\1\s\src\Plugin.InAppBilling\InAppBilling.apple.cs:321

Code snippet

try
{
    var connected = await billing.ConnectAsync();
    if (!connected) throw new Exception("Could not connect");
    var purchase = await billing.PurchaseAsync("mySubscriptionId", ItemType.Subscription);
    if (purchase == null) throw new Exception("Purchase is null");
    if (purchase.State != PurchaseState.Purchased) throw new Exception($"Purchase failed: {purchase.State}");
    this.StatusLabel.Text = "Success";
}
catch (Exception ex)
{
    if (ex is InAppBillingPurchaseException purchaseEx)
        this.StatusLabel.Text = $"Purchase exception: {purchaseEx.PurchaseError}\r\n{ex}";
    else
        this.StatusLabel.Text = $"{ex}";
}
finally
{
    await billing.DisconnectAsync();
}

Screenshots

Process step 1: purchase information 1

Process step 2: sign in (Sandbox) 2

Process step 3: confirmation payment successful 3

Error: 4

jamesmontemagno commented 1 year ago

Hmmmm i can't imagine what the issue would be here.... I don't try to parse any data on subscription length at all... hmmmm would need to see full stack trace please

vppetrov commented 1 year ago

@jamesmontemagno Thank you for looking into this. I provided the full stack trace that I receive in the original post, no more details from Visual Studio.

jamesmontemagno commented 1 year ago

Why wouldn't you have a duration? That doesn't make sense as it would just be a 1 time purchase non-consumable... i don't know why they let you set that.

vppetrov commented 1 year ago

@jamesmontemagno In my case it was the first time I was implementing it and just hadn't set it. Then I got an unknown error and lost days to figure it out. It would be nice to have a good error, e.g. "ArgumentOutOfRangeException" with the argument name set to "duration". That would point the developer directly to the problem.

jamesmontemagno commented 1 year ago

The error is coming from Apple itself. I don't have insight into the duration when you are purchasing the item.

Going to close as nothing I can do here and not a valid scenario from what I can see.