Skip to content

Instantly share code, notes, and snippets.

@jonathanpeppers
Last active February 16, 2017 22:56
Show Gist options
  • Save jonathanpeppers/be1687c289a60f589aa9c6cd701fd0fe to your computer and use it in GitHub Desktop.
Save jonathanpeppers/be1687c289a60f589aa9c6cd701fd0fe to your computer and use it in GitHub Desktop.
ApplePurchaseService - Buy
//NOTE: should be a singleton for your entire app
public class ApplePurchaseService : PurchaseService
{
private readonly ObserverDelegate _observer = new ObserverDelegate();
public ApplePurchaseService()
{
SKPaymentQueue.DefaultQueue.AddTransactionObserver(_observer);
}
protected async override Task<Receipt> BuyNative(Purchase purchase)
{
var product = (SKProduct)purchase.NativeObject;
var payment = SKPayment.CreateFrom(product);
var source = new TaskCompletionSource<Receipt>();
_observer.Sources[purchase.Id] = source;
SKPaymentQueue.DefaultQueue.AddPayment(payment);
return await source.Task;
}
private class ObserverDelegate : SKPaymentTransactionObserver
{
public readonly Dictionary<string, TaskCompletionSource<Receipt>> Sources = new Dictionary<string, TaskCompletionSource<Receipt>>();
public override void UpdatedTransactions(SKPaymentQueue queue, SKPaymentTransaction[] transactions)
{
foreach (var transaction in transactions)
{
//NOTE: you have to call "Finish" on every state
if (transaction.TransactionState != SKPaymentTransactionState.Purchasing)
{
SKPaymentQueue.DefaultQueue.FinishTransaction(transaction);
}
TaskCompletionSource<Receipt> source;
if (Sources.TryGetValue(transaction.Payment.ProductIdentifier, out source))
{
switch (transaction.TransactionState)
{
case SKPaymentTransactionState.Failed:
source.TrySetException(new Exception(transaction.Error?.LocalizedDescription ?? "Unknown Error"));
break;
case SKPaymentTransactionState.Purchased:
case SKPaymentTransactionState.Restored:
//First make sure the receipt exists
var url = NSBundle.MainBundle.AppStoreReceiptUrl;
if (!NSFileManager.DefaultManager.FileExists(url.Path))
{
source.TrySetException(new Exception("No app store receipt file found!"));
return;
}
//If the NSData is null
var data = NSData.FromUrl(url);
if (data == null)
{
source.TrySetException(new Exception("Could not load app store receipt!"));
return;
}
var receipt = new AppleReceipt
{
BundleId = NSBundle.MainBundle.BundleIdentifier,
Id = transaction.Payment.ProductIdentifier,
TransactionId = transaction.TransactionIdentifier,
Data = data.ToArray(),
};
source.TrySetResult(receipt);
break;
default:
break;
}
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment