/// <summary> /// Purchase a specific product or subscription /// </summary> /// <param name="productId">Sku or ID of product</param> /// <param name="itemType">Type of product being requested</param> /// <param name="payload">Developer specific payload</param> /// <param name="verifyPurchase">Interface to verify purchase</param> /// <returns></returns> public async override Task <InAppBillingPurchase> PurchaseAsync(string productId, ItemType itemType, string payload, IInAppBillingVerifyPurchase verifyPurchase = null) { Console.WriteLine($"PurchaseAsync1() - productId: { productId }"); var p = await PurchaseAsync(productId); var reference = new DateTime(2001, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); var purchase = new InAppBillingPurchase { TransactionDateUtc = reference.AddSeconds(p.TransactionDate.SecondsSinceReferenceDate), Id = p.TransactionIdentifier, ProductId = p.Payment?.ProductIdentifier ?? string.Empty, State = p.GetPurchaseState(), PurchaseToken = p.TransactionReceipt?.GetBase64EncodedString(NSDataBase64EncodingOptions.None) ?? string.Empty }; if (verifyPurchase == null) { Console.WriteLine($"PurchaseAsync1() - verifyPurchase is null - return"); return(purchase); } var validated = await ValidateReceipt(verifyPurchase, purchase.ProductId, purchase.Id); Console.WriteLine($"PurchaseAsync1() - validated: { validated }"); return(validated ? purchase : null); }
//inapp:{Context.PackageName}:{productSku} /// <summary> /// Consume a purchase with a purchase token. /// </summary> /// <param name="productId">Id or Sku of product</param> /// <param name="purchaseToken">Original Purchase Token</param> /// <returns>If consumed successful</returns> public override Task <InAppBillingPurchase> ConsumePurchaseAsync(string productId, string purchaseToken) { if (serviceConnection?.Service == null) { throw new InAppBillingPurchaseException(PurchaseError.ServiceUnavailable, "You are not connected to the Google Play App store."); } var response = serviceConnection.Service.ConsumePurchase(3, Context.PackageName, purchaseToken); var result = ParseConsumeResult(response); if (!result) { return(null); } var purchase = new InAppBillingPurchase { Id = string.Empty, PurchaseToken = purchaseToken, State = PurchaseState.Purchased, ConsumptionState = ConsumptionState.Consumed, AutoRenewing = false, Payload = string.Empty, ProductId = productId, TransactionDateUtc = DateTime.UtcNow }; return(Task.FromResult(purchase)); }
/// <summary> /// Purchase a specific product or subscription /// </summary> /// <param name="productId">Sku or ID of product</param> /// <param name="itemType">Type of product being requested</param> /// <param name="verifyPurchase">Interface to verify purchase</param> /// <param name="obfuscatedAccountId">Specifies an optional obfuscated string that is uniquely associated with the user's account in your app.</param> /// <param name="obfuscatedProfileId">Specifies an optional obfuscated string that is uniquely associated with the user's profile in your app.</param> /// <returns></returns> public async override Task <InAppBillingPurchase> PurchaseAsync(string productId, ItemType itemType, IInAppBillingVerifyPurchase verifyPurchase = null, string obfuscatedAccountId = null, string obfuscatedProfileId = null) { var p = await PurchaseAsync(productId); var reference = new DateTime(2001, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); var purchase = new InAppBillingPurchase { TransactionDateUtc = reference.AddSeconds(p.TransactionDate.SecondsSinceReferenceDate), 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) { return(purchase); } var validated = await ValidateReceipt(verifyPurchase, purchase.ProductId, purchase.Id); return(validated ? purchase : null); }
public static InAppBillingPurchase ToIABPurchase(this Purchase purchase) { var finalPurchase = new InAppBillingPurchase { AutoRenewing = purchase.IsAutoRenewing, ConsumptionState = ConsumptionState.NoYetConsumed, Id = purchase.OrderId, IsAcknowledged = purchase.IsAcknowledged, Payload = purchase.DeveloperPayload, ProductId = purchase.Sku, PurchaseToken = purchase.PurchaseToken, TransactionDateUtc = DateTimeOffset.FromUnixTimeMilliseconds(purchase.PurchaseTime).DateTime, ObfuscatedAccountId = purchase.AccountIdentifiers?.ObfuscatedAccountId, ObfuscatedProfileId = purchase.AccountIdentifiers?.ObfuscatedProfileId }; finalPurchase.State = purchase.PurchaseState switch { Android.BillingClient.Api.PurchaseState.Pending => PurchaseState.PaymentPending, Android.BillingClient.Api.PurchaseState.Purchased => PurchaseState.Purchased, _ => PurchaseState.Unknown }; return(finalPurchase); } }
/// <summary> /// Purchase a specific product or subscription /// </summary> /// <param name="productId">Sku or ID of product</param> /// <param name="itemType">Type of product being requested</param> /// <param name="payload">Developer specific payload</param> /// <param name="verifyPurchase">Interface to verify purchase</param> /// <returns></returns> public async Task <InAppBillingPurchase> PurchaseAsync(string productId, ItemType itemType, string payload, IInAppBillingVerifyPurchase verifyPurchase = null) { var p = await PurchaseAsync(productId); var reference = new DateTime(2001, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); var purchase = new InAppBillingPurchase { TransactionDateUtc = reference.AddSeconds(p.TransactionDate.SecondsSinceReferenceDate), Id = p.TransactionIdentifier, ProductId = p.Payment?.ProductIdentifier ?? string.Empty, State = p.GetPurchaseState() }; if (verifyPurchase == null) { return(purchase); } // Get the receipt data for (server-side) validation. // See: https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Introduction.html#//apple_ref/doc/uid/TP40010573 var receiptUrl = NSData.FromUrl(NSBundle.MainBundle.AppStoreReceiptUrl); string receipt = receiptUrl.GetBase64EncodedString(NSDataBase64EncodingOptions.None); var validated = await verifyPurchase.VerifyPurchase(receipt, string.Empty); return(validated ? purchase : null); }
/// <summary> /// Read purchase data out of the UWP Receipt XML /// </summary> /// <param name="xml">Receipt XML</param> /// <param name="status">Status of the purchase</param> /// <returns>A list of purchases, the user has done</returns> public static IEnumerable <InAppBillingPurchase> ToInAppBillingPurchase(this string xml, ProductPurchaseStatus status) { var purchases = new List <InAppBillingPurchase>(); var xmlDoc = new XmlDocument(); try { xmlDoc.LoadXml(xml); } catch { //Invalid XML, we haven't finished this transaction yet. } // Iterate through all ProductReceipt elements var xmlProductReceipts = xmlDoc.GetElementsByTagName("ProductReceipt"); for (var i = 0; i < xmlProductReceipts.Count; i++) { var xmlProductReceipt = xmlProductReceipts[i]; // Create new InAppBillingPurchase with values from the xml element var purchase = new InAppBillingPurchase() { Id = xmlProductReceipt.Attributes["Id"].Value, TransactionDateUtc = Convert.ToDateTime(xmlProductReceipt.Attributes["PurchaseDate"].Value), ProductId = xmlProductReceipt.Attributes["ProductId"].Value, AutoRenewing = false // Not supported by UWP yet }; purchase.PurchaseToken = purchase.Id; // Map native UWP status to PurchaseState switch (status) { case ProductPurchaseStatus.AlreadyPurchased: case ProductPurchaseStatus.Succeeded: purchase.State = PurchaseState.Purchased; break; case ProductPurchaseStatus.NotFulfilled: purchase.State = PurchaseState.Deferred; break; case ProductPurchaseStatus.NotPurchased: purchase.State = PurchaseState.Canceled; break; default: purchase.State = PurchaseState.Unknown; break; } // Add to list of purchases purchases.Add(purchase); } return(purchases); }
public async override Task <InAppBillingPurchase> PurchaseAsync(string productId, ItemType itemType, string payload, IInAppBillingVerifyPurchase verifyPurchase = null) { string mspid = await GetMSProductIDForPID(productId); if (mspid == null) { throw new InAppBillingPurchaseException(PurchaseError.InvalidProduct); } StorePurchaseResult result = await storeContext.RequestPurchaseAsync(mspid); if (result.ExtendedError != null) { Debug.WriteLine("Extended Error:" + result.ExtendedError.ToString() + " Result: " + result.Status.ToString()); throw new InAppBillingPurchaseException(PurchaseError.GeneralError, result.ExtendedError); } else { switch (result.Status) { case StorePurchaseStatus.AlreadyPurchased: throw new InAppBillingPurchaseException(PurchaseError.AlreadyOwned); case StorePurchaseStatus.Succeeded: var purchase = new InAppBillingPurchase() { Id = productId, ProductId = productId, AutoRenewing = false, // Not supported by UWP yet State = PurchaseState.Purchased, PurchaseToken = productId }; return(purchase); case StorePurchaseStatus.NotPurchased: throw new InAppBillingPurchaseException(PurchaseError.UserCancelled); case StorePurchaseStatus.NetworkError: throw new InAppBillingPurchaseException(PurchaseError.ServiceUnavailable); case StorePurchaseStatus.ServerError: throw new InAppBillingPurchaseException(PurchaseError.GeneralError); default: Debug.WriteLine("Product was not purchased due to an unknown error."); throw new InAppBillingPurchaseException(PurchaseError.GeneralError); } } return(null); }
//inapp:{Context.PackageName}:{productSku} /// <summary> /// Consume a purchase with a purchase token. /// </summary> /// <param name="productId">Id or Sku of product</param> /// <param name="purchaseToken">Original Purchase Token</param> /// <returns>If consumed successful</returns> public Task<InAppBillingPurchase> ConsumePurchaseAsync(string productId, string purchaseToken) { var response = serviceConnection.Service.ConsumePurchase(3, Context.PackageName, purchaseToken); var result = ParseConsumeResult(response); if (!result) return null; var purchase = new InAppBillingPurchase { Id = string.Empty, PurchaseToken = purchaseToken, State = PurchaseState.Purchased, AutoRenewing = false, Payload = string.Empty, ProductId = productId, TransactionDateUtc = DateTime.UtcNow }; return Task.FromResult(purchase); }
/// <summary> /// Purchase a specific product or subscription /// </summary> /// <param name="productId">Sku or ID of product</param> /// <param name="itemType">Type of product being requested</param> /// <param name="payload">Developer specific payload</param> /// <param name="verifyPurchase">Interface to verify purchase</param> /// <returns></returns> public async override Task <InAppBillingPurchase> PurchaseAsync(string productId, ItemType itemType, string payload, IInAppBillingVerifyPurchase verifyPurchase = null) { var p = await PurchaseAsync(productId); var reference = new DateTime(2001, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); var purchase = new InAppBillingPurchase { TransactionDateUtc = reference.AddSeconds(p.TransactionDate.SecondsSinceReferenceDate), Id = p.TransactionIdentifier, ProductId = p.Payment?.ProductIdentifier ?? string.Empty, State = p.GetPurchaseState() }; if (verifyPurchase == null) { return(purchase); } var validated = await ValidateReceipt(verifyPurchase, purchase.ProductId, purchase.Id); return(validated ? purchase : null); }
public static InAppBillingPurchase ToIABPurchase(this SKPaymentTransaction transaction) { var p = transaction.OriginalTransaction; if (p == null) { p = transaction; } if (p == null) { return(null); } var newP = new InAppBillingPurchase { TransactionDateUtc = NSDateToDateTimeUtc(p.TransactionDate), Id = p.TransactionIdentifier, ProductId = p.Payment?.ProductIdentifier ?? string.Empty, State = p.GetPurchaseState() }; return(newP); }
public override Task <bool> FinishTransaction(InAppBillingPurchase purchase) => FinishTransaction(purchase?.Id);
public virtual Task <bool> FinishTransaction(InAppBillingPurchase purchase) => Task.FromResult(true);