Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added InAppBilling.VerifyPreviousPurchaseAsync() #210

Merged
merged 1 commit into from
Aug 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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