Skip to content

Commit

Permalink
Added InAppBilling.VerifyPreviousPurchaseAsync()
Browse files Browse the repository at this point in the history
  • Loading branch information
David Riha committed Jan 25, 2019
1 parent 2370ce8 commit 052cbb7
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 54 deletions.
59 changes: 42 additions & 17 deletions src/Plugin.InAppBilling.Abstractions/BaseInAppBilling.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Plugin.InAppBilling.Abstractions
Expand Down Expand Up @@ -35,24 +36,48 @@ public abstract class BaseInAppBilling : IInAppBilling, IDisposable
public abstract Task<IEnumerable<InAppBillingProduct>> GetProductInfoAsync(ItemType itemType, params string[] productIds);


/// <summary>
/// Get all current purhcase for a specifiy product type.
/// </summary>
/// <param name="itemType">Type of product</param>
/// <summary>
/// Verifies a specific product type and product id. Use e.g. when product is already purchased but verification failed and needs to be called again.
/// </summary>
/// <param name="itemType">Type of product</param>
/// <param name="verifyPurchase">Interface to verify purchase</param>
/// <param name="productId">Id of product</param>
/// <returns>The current purchases</returns>
public async Task<bool> VerifyPreviousPurchaseAsync(ItemType itemType, IInAppBillingVerifyPurchase verifyPurchase, string productId)
{
return (await GetPurchasesAsync(itemType, verifyPurchase, productId))?.Any(p => productId.Equals(p?.ProductId)) ?? false;
}

/// <summary>
/// Get all current purchases for a specific product type. If verification fails for some purchase, it's not contained in the result.
/// </summary>
/// <param name="itemType">Type of product</param>
/// <param name="verifyPurchase">Interface to verify purchase</param>
/// <param name="verifyOnlyProductId">If you want to verify a specific purchase, provide its id. Other purchases will be returned without verification.</param>
/// <returns>The current purchases</returns>
protected abstract Task<IEnumerable<InAppBillingPurchase>> GetPurchasesAsync(ItemType itemType, IInAppBillingVerifyPurchase verifyPurchase, string verifyOnlyProductId);

/// <summary>
/// Get all current purchases for a specific product type. If you use verification and it fails for some purchase, it's not contained in the result.
/// </summary>
/// <param name="itemType">Type of product</param>
/// <param name="verifyPurchase">Verify purchase implementation</param>
/// <returns>The current purchases</returns>
public abstract Task<IEnumerable<InAppBillingPurchase>> GetPurchasesAsync(ItemType itemType, IInAppBillingVerifyPurchase verifyPurchase = null);
/// <returns>The current purchases</returns>
public async Task<IEnumerable<InAppBillingPurchase>> GetPurchasesAsync(ItemType itemType, IInAppBillingVerifyPurchase verifyPurchase = null)
{
return await GetPurchasesAsync(itemType, verifyPurchase, null);
}

/// <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">Verify Purchase implementation</param>
/// <returns>Purchase details</returns>
/// <exception cref="InAppBillingPurchaseException">If an error occures during processing</exception>
public abstract Task<InAppBillingPurchase> PurchaseAsync(string productId, ItemType itemType, string payload, IInAppBillingVerifyPurchase verifyPurchase = null);
/// <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">Verify Purchase implementation</param>
/// <returns>Purchase details</returns>
/// <exception cref="InAppBillingPurchaseException">If an error occures during processing</exception>
public abstract Task<InAppBillingPurchase> PurchaseAsync(string productId, ItemType itemType, string payload, IInAppBillingVerifyPurchase verifyPurchase = null);

/// <summary>
/// Consume a purchase with a purchase token.
Expand Down
24 changes: 16 additions & 8 deletions src/Plugin.InAppBilling.Abstractions/IInAppBilling.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@


using System;
using System.Collections.Generic;
using System.Threading.Tasks;
Expand Down Expand Up @@ -36,14 +36,22 @@ public interface IInAppBilling : IDisposable
/// <returns>List of products</returns>
Task<IEnumerable<InAppBillingProduct>> GetProductInfoAsync(ItemType itemType, params string[] productIds);


/// <summary>
/// Get all current purhcase for a specifiy product type.
/// </summary>
/// <param name="itemType">Type of product</param>
/// <summary>
/// Verifies a specific product type and product id. Use e.g. when product is already purchased but verification failed and needs to be called again.
/// </summary>
/// <param name="itemType">Type of product</param>
/// <param name="verifyPurchase">Interface to verify purchase</param>
/// <param name="productId">Id of product</param>
/// <returns>The current purchases</returns>
Task<bool> VerifyPreviousPurchaseAsync(ItemType itemType, IInAppBillingVerifyPurchase verifyPurchase, string productId);

/// <summary>
/// Get all current purchases for a specific product type. If you use verification and it fails for some purchase, it's not contained in the result.
/// </summary>
/// <param name="itemType">Type of product</param>
/// <param name="verifyPurchase">Verify purchase implementation</param>
/// <returns>The current purchases</returns>
Task<IEnumerable<InAppBillingPurchase>> GetPurchasesAsync(ItemType itemType, IInAppBillingVerifyPurchase verifyPurchase = null);
/// <returns>The current purchases</returns>
Task<IEnumerable<InAppBillingPurchase>> GetPurchasesAsync(ItemType itemType, IInAppBillingVerifyPurchase verifyPurchase = null);

/// <summary>
/// Purchase a specific product or subscription
Expand Down
23 changes: 10 additions & 13 deletions src/Plugin.InAppBilling.Android/InAppBillingImplementation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,7 @@ Task<IEnumerable<Product>> GetProductInfoAsync(string[] productIds, string itemT
return getSkuDetailsTask;
}

/// <summary>
/// Get all current purhcase for a specifiy product type.
/// </summary>
/// <param name="itemType">Type of product</param>
/// <param name="verifyPurchase">Interface to verify purchase</param>
/// <returns>The current purchases</returns>
public async override Task<IEnumerable<InAppBillingPurchase>> GetPurchasesAsync(ItemType itemType, IInAppBillingVerifyPurchase verifyPurchase = null)
protected async override Task<IEnumerable<InAppBillingPurchase>> GetPurchasesAsync(ItemType itemType, IInAppBillingVerifyPurchase verifyPurchase, string verifyOnlyProductId)
{
if (serviceConnection?.Service == null)
{
Expand All @@ -160,10 +154,10 @@ public async override Task<IEnumerable<InAppBillingPurchase>> GetPurchasesAsync(
switch (itemType)
{
case ItemType.InAppPurchase:
purchases = await GetPurchasesAsync(ITEM_TYPE_INAPP, verifyPurchase);
purchases = await GetPurchasesAsync(ITEM_TYPE_INAPP, verifyPurchase, verifyOnlyProductId);
break;
case ItemType.Subscription:
purchases = await GetPurchasesAsync(ITEM_TYPE_SUBSCRIPTION, verifyPurchase);
purchases = await GetPurchasesAsync(ITEM_TYPE_SUBSCRIPTION, verifyPurchase, verifyOnlyProductId);
break;
}

Expand All @@ -188,7 +182,7 @@ public async override Task<IEnumerable<InAppBillingPurchase>> GetPurchasesAsync(

}

Task<List<Purchase>> GetPurchasesAsync(string itemType, IInAppBillingVerifyPurchase verifyPurchase)
Task<List<Purchase>> GetPurchasesAsync(string itemType, IInAppBillingVerifyPurchase verifyPurchase, string verifyOnlyProductId = null)
{
var getPurchasesTask = Task.Run(async () =>
{
Expand Down Expand Up @@ -222,9 +216,12 @@ Task<List<Purchase>> GetPurchasesAsync(string itemType, IInAppBillingVerifyPurch
string sign = signatures[i];
var purchase = JsonConvert.DeserializeObject<Purchase>(data);
if (verifyPurchase == null || await verifyPurchase.VerifyPurchase(data, sign, purchase.ProductId, purchase.OrderId))
purchases.Add(purchase);
}
if (verifyPurchase == null || (verifyOnlyProductId != null && !verifyOnlyProductId.Equals(purchase.ProductId)))
purchases.Add(purchase);
else if (await verifyPurchase.VerifyPurchase(data, sign, purchase.ProductId, purchase.OrderId))
purchases.Add(purchase);
}
continuationToken = ownedItems.GetString(RESPONSE_IAP_CONTINUATION_TOKEN);
Expand Down
8 changes: 1 addition & 7 deletions src/Plugin.InAppBilling.UWP/InAppBillingImplementation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,7 @@ public async override Task<IEnumerable<InAppBillingProduct>> GetProductInfoAsync
return products;
}

/// <summary>
/// Get all current purchase for a specific product type.
/// </summary>
/// <param name="itemType">Type of product</param>
/// <param name="verifyPurchase">Verify purchase implementation</param>
/// <returns>The current purchases</returns>
public async override Task<IEnumerable<InAppBillingPurchase>> GetPurchasesAsync(ItemType itemType, IInAppBillingVerifyPurchase verifyPurchase = null)
protected async override Task<IEnumerable<InAppBillingPurchase>> GetPurchasesAsync(ItemType itemType, IInAppBillingVerifyPurchase verifyPurchase, string verifyOnlyProductId)
{
// Get list of product receipts from store or simulator
var xmlReceipt = await CurrentAppMock.GetAppReceiptAsync(InTestingMode);
Expand Down
11 changes: 2 additions & 9 deletions src/Plugin.InAppBilling.iOS/InAppBillingImplementation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,7 @@ Task<IEnumerable<SKProduct>> GetProductAsync(string[] productId)
return productRequestDelegate.WaitForResponse();
}


/// <summary>
/// Get all current purchase for a specifiy product type.
/// </summary>
/// <param name="itemType">Type of product</param>
/// <param name="verifyPurchase">Interface to verify purchase</param>
/// <returns>The current purchases</returns>
public async override Task<IEnumerable<InAppBillingPurchase>> GetPurchasesAsync(ItemType itemType, IInAppBillingVerifyPurchase verifyPurchase = null)
protected async override Task<IEnumerable<InAppBillingPurchase>> GetPurchasesAsync(ItemType itemType, IInAppBillingVerifyPurchase verifyPurchase, string verifyOnlyProductId)
{
var purchases = await RestoreAsync();

Expand All @@ -111,7 +104,7 @@ public async override Task<IEnumerable<InAppBillingPurchase>> GetPurchasesAsync(
var validPurchases = new List<InAppBillingPurchase>();
foreach (var purchase in converted)
{
if (await ValidateReceipt(verifyPurchase, purchase.ProductId, purchase.Id))
if ((verifyOnlyProductId != null && !verifyOnlyProductId.Equals(purchase.ProductId)) || await ValidateReceipt(verifyPurchase, purchase.ProductId, purchase.Id))
validPurchases.Add(purchase);
}

Expand Down

0 comments on commit 052cbb7

Please sign in to comment.