// called when the transaction status is updated public override void UpdatedTransactions(SKPaymentQueue queue, SKPaymentTransaction[] transactions) { SystemLog.Debug("UpdatedTransactions - {0}", transactions.Length); foreach (var transaction in transactions) { // ISSUE: The transaction (and any dangling ones) are marked as finished straight away. Apple recommends we finish after app has done // what it needs to. What happens if user's phone turns off right after finish? The app may not // have registered purchase and the user will have to re-buy again! // // Solution is to to return a scope in the "PurchaseMethod" that // finishes the transaction on dispose // // using(inAppPurchaseManager.Purchase("productid")) { // UpgradeApp(); // } <-- dispose will finish transaction // if (transaction.TransactionState != SKPaymentTransactionState.Purchasing) { SKPaymentQueue.DefaultQueue.FinishTransaction(transaction); } } if (transactions.Any(p => p.TransactionState.IsIn(SKPaymentTransactionState.Purchased, SKPaymentTransactionState.Restored))) { var paymentTransaction = transactions.First(t => t.TransactionState.IsIn(SKPaymentTransactionState.Purchased, SKPaymentTransactionState.Restored)); switch (paymentTransaction.TransactionState) { case SKPaymentTransactionState.Purchased: SystemLog.Info("PURCHASED"); _result = new PurchaseResult { AppStoreProductID = paymentTransaction.Payment.ProductIdentifier, Result = TransactionResult.Purchased, PurchaseDate = paymentTransaction.TransactionDate.ToNullableDateTime() }; break; case SKPaymentTransactionState.Restored: SystemLog.Info("RESTORED"); _result = new PurchaseResult { AppStoreProductID = paymentTransaction.Payment.ProductIdentifier, Result = TransactionResult.Restored, PurchaseDate = paymentTransaction.OriginalTransaction.TransactionDate.ToNullableDateTime() }; break; } _waiter.Set(); } else if (transactions.All(t => t.TransactionState == SKPaymentTransactionState.Failed)) { SystemLog.Info("FAILED"); var paymentTransaction = transactions.First(t => t.TransactionState == SKPaymentTransactionState.Failed); SystemLog.Info("WITH ERROR {0}", paymentTransaction.Error); _result = new PurchaseResult { AppStoreProductID = paymentTransaction.Payment.ProductIdentifier, Result = TransactionResult.Failed, Error = paymentTransaction.Error, PurchaseDate = null }; _waiter.Set(); } else { // still waiting for response (this was just dangling response from prior requests) } }
public ProductPurchaser() { _waiter = new ManualResetEventSlim(false); _result = null; }