diff --git a/src/Plugin.InAppBilling/InAppBilling.apple.cs b/src/Plugin.InAppBilling/InAppBilling.apple.cs index d4b36eb..e09718b 100644 --- a/src/Plugin.InAppBilling/InAppBilling.apple.cs +++ b/src/Plugin.InAppBilling/InAppBilling.apple.cs @@ -5,7 +5,6 @@ using System.Diagnostics; using System.Linq; using System.Threading.Tasks; -using UIKit; namespace Plugin.InAppBilling { @@ -13,9 +12,29 @@ namespace Plugin.InAppBilling /// Implementation for InAppBilling /// [Preserve(AllMembers = true)] - public class InAppBillingImplementation : BaseInAppBilling + public class InAppBillingImplementation : BaseInAppBilling, ISKProductsRequestDelegate { - static bool IsiOS112 => UIDevice.CurrentDevice.CheckSystemVersion(11, 2); +#if __IOS__ || __TVOS__ + static bool HasIntroductoryPrice => UIKit.UIDevice.CurrentDevice.CheckSystemVersion(11, 2); +#else + static bool initIntro, hasIntro; + static bool HasIntroductoryPrice + { + get + { + if (initIntro) + return hasIntro; + + initIntro = true; + + + using var info = new NSProcessInfo(); + hasIntro = info.IsOperatingSystemAtLeastVersion(new NSOperatingSystemVersion(10,13,2)); + return hasIntro; + + } + } +#endif /// /// Gets or sets a callback for out of band purchases to complete. @@ -38,13 +57,15 @@ public InAppBillingImplementation() /// public override bool InTestingMode { get; set; } - /// - /// Get product information of a specific product - /// - /// Sku or Id of the product(s) - /// Type of product offering - /// - public async override Task> GetProductInfoAsync(ItemType itemType, params string[] productIds) + public IntPtr Handle => throw new NotImplementedException(); + + /// + /// Get product information of a specific product + /// + /// Sku or Id of the product(s) + /// Type of product offering + /// + public async override Task> GetProductInfoAsync(ItemType itemType, params string[] productIds) { var products = await GetProductAsync(productIds); @@ -56,8 +77,8 @@ public async override Task> GetProductInfoAsync ProductId = p.ProductIdentifier, Description = p.LocalizedDescription, CurrencyCode = p.PriceLocale?.CurrencyCode ?? string.Empty, - LocalizedIntroductoryPrice = IsiOS112 ? (p.IntroductoryPrice?.LocalizedPrice() ?? string.Empty) : string.Empty, - MicrosIntroductoryPrice = IsiOS112 ? (long)((p.IntroductoryPrice?.Price?.DoubleValue ?? 0) * 1000000d) : 0 + LocalizedIntroductoryPrice = HasIntroductoryPrice ? (p.IntroductoryPrice?.LocalizedPrice() ?? string.Empty) : string.Empty, + MicrosIntroductoryPrice = HasIntroductoryPrice ? (long)((p.IntroductoryPrice?.Price?.DoubleValue ?? 0) * 1000000d) : 0 }); } @@ -175,7 +196,9 @@ public async override Task PurchaseAsync(string productId, Id = p.TransactionIdentifier, ProductId = p.Payment?.ProductIdentifier ?? string.Empty, State = p.GetPurchaseState(), +#if __IOS__ || __TVOS__ PurchaseToken = p.TransactionReceipt?.GetBase64EncodedString(NSDataBase64EncodingOptions.None) ?? string.Empty +#endif }; if (verifyPurchase == null) @@ -203,7 +226,9 @@ Task ValidateReceipt(IInAppBillingVerifyPurchase verifyPurchase, string pr } - Task PurchaseAsync(string productId) + TaskCompletionSource productTCS; + + async Task PurchaseAsync(string productId) { var tcsTransaction = new TaskCompletionSource(); @@ -257,13 +282,35 @@ Task PurchaseAsync(string productId) paymentObserver.TransactionCompleted += handler; +#if __IOS__ || __TVOS__ + var payment = SKPayment.CreateFrom(productId); +#else + productTCS?.TrySetCanceled(); + productTCS = new TaskCompletionSource(); + var productIdentifiers = NSSet.MakeNSObjectSet(new NSString[] { new NSString(productId) }); + var productsRequest = new SKProductsRequest(productIdentifiers); + productsRequest.Delegate = this; // for SKProductsRequestDelegate.ReceivedResponse + productsRequest.Start(); + var product = await productTCS.Task; + if (product == null) + throw new InAppBillingPurchaseException(PurchaseError.InvalidProduct); + + var payment = SKPayment.CreateFrom(product); + //var payment = SKPayment.CreateFrom((SKProduct)SKProduct.FromObject(new NSString(productId))); +#endif SKPaymentQueue.DefaultQueue.AddPayment(payment); - return tcsTransaction.Task; + return await tcsTransaction.Task; } + public void ReceivedResponse(SKProductsRequest request, SKProductsResponse response) + { + productTCS?.TrySetResult(response?.Products?.FirstOrDefault()); + } + + /// /// Consume a purchase with a purchase token. /// @@ -341,6 +388,7 @@ public override void Dispose(bool disposing) base.Dispose(disposing); } + } @@ -471,11 +519,15 @@ public static InAppBillingPurchase ToIABPurchase(this SKPaymentTransaction trans if (p == null) return null; +#if __IOS__ || __TVOS__ var finalToken = p.TransactionReceipt?.GetBase64EncodedString(NSDataBase64EncodingOptions.None); if (string.IsNullOrEmpty(finalToken)) finalToken = transaction.TransactionReceipt?.GetBase64EncodedString(NSDataBase64EncodingOptions.None); - return new InAppBillingPurchase +#else + var finalToken = string.Empty; +#endif + return new InAppBillingPurchase { TransactionDateUtc = NSDateToDateTimeUtc(transaction.TransactionDate), Id = p.TransactionIdentifier, diff --git a/src/Plugin.InAppBilling/Plugin.InAppBilling.csproj b/src/Plugin.InAppBilling/Plugin.InAppBilling.csproj index b9471e2..cd4c861 100644 --- a/src/Plugin.InAppBilling/Plugin.InAppBilling.csproj +++ b/src/Plugin.InAppBilling/Plugin.InAppBilling.csproj @@ -1,6 +1,6 @@  - netstandard2.0;MonoAndroid10.0;Xamarin.iOS10;Xamarin.TVOS10 + netstandard2.0;MonoAndroid10.0;Xamarin.iOS10;Xamarin.TVOS10;Xamarin.Mac20 $(TargetFrameworks);uap10.0.16299; Plugin.InAppBilling Plugin.InAppBilling @@ -61,6 +61,7 @@ + @@ -77,7 +78,7 @@ - + @@ -90,4 +91,8 @@ + + + + \ No newline at end of file