StoreKit: Catch failed restore? - iphone

I'm implementing In-App purchase feature with Restore button.
I have a brand new test user set up, without any payments made.
When I hit the restore button, and log in with the new test user, I cannot catch any delegated methods that tell me that the restoring transaction has failed (since there is nothing to restore).
The only method that get invoked is -(void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue*)queue, but this method gets called in the case when restoring was successful too.
What can I do now? How can I catch such a case?
Addition: I have a progress indicator that says "Contacting App Store", and I need an invocation where I can hide it in failed cases too.

Noah: here's a code snippet for you:
-(void)restore {
[self.delegate showLoadingScreen];
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
}
And the following method:
-(void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue {
if (!queue.transactions || [queue.transactions count] == 0) {
[self showAlertScreenWithTitle:#"Error Restoring Subscription" message:#"No subscription was found to restore."];
} else {
BOOL didRestore = NO;
for (SKPaymentTransaction *t in queue.transactions) {
if (t.transactionState == SKPaymentTransactionStateRestored || t.transactionState == SKPaymentTransactionStatePurchased) {
NSTimeInterval now = [[NSDate date] timeIntervalSince1970] - _timeOffset;
NSTimeInterval expire = [t.transactionDate timeIntervalSince1970] + kExplorerSubscriptionSecondLength;
NSTimeInterval purchase = [t.transactionDate timeIntervalSince1970];
if (purchase <= now && now <= expire) {
didRestore = YES;
}
}
}
if (!didRestore)
[self showAlertScreenWithTitle:#"Error Restoring Subscription" message:#"No subscription was found to restore."];
}
[self.delegate dismissLoadingScreen];
}
Let me know if that helps you....

When you restore a transactions, there're two delegated methods:
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error
The first one (paymentQueueRestoreCompletedTransactionsFinished) is called when all the transactions are restored. If you don't have any previous purchase it also calls this method because the restored worked fine but there's nothing to restore.
The other method (restoreCompletedTransactionsFailedWithError) is called when there's an error restoring the transaction.
If you need to show a message to the user telling him he doesn't have any transaction to restore you can use:
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
Here you have a small snippet for this delegate:
//
// called when the transaction status is updated
//
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
for (SKPaymentTransaction *transaction in transactions)
{
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchased:
[self completeTransaction:transaction];
break;
case SKPaymentTransactionStateFailed:
[self failedTransaction:transaction];
break;
case SKPaymentTransactionStateRestored:
[self restoreTransaction:transaction];
restoredTransaction++;
break;
default:
break;
}
}
}
Then you can use the restoredTransaction variable to know if any transaction has been restored on paymentQueueRestoreCompletedTransactionsFinished

You can use following delegate method for Restore Transaction.
-(void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error{
NSLog(#"Error when purchasing: %#",error);
}

Related

IOS INAPP Purchase restore transaction

I AM a Beginner in ios, implementing in app purchase fo the first time
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
SKPaymentTransaction *temp;
SKPaymentTransaction *transaction;
for (transaction in transactions)
{
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchased:
[self completeTransaction:transaction];
break;
case SKPaymentTransactionStateFailed:
[self failedTransaction:transaction];
break;
case SKPaymentTransactionStateRestored:
[self restoreTransaction:transaction];
break;
default:
break;
}
};
}
the parameter "transactions" has 6 Objects while restoring hence while testing in sandbox enviorment the restoreTransaction function is called six times and the pop up message i.e UIALertView is shown six times .
i want to show the POP UP only once.
Please Suggest me some solution Friends.

Restoring an in app purchase

When an in app purchase is restored, the following delegate method is called:
-(void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue {
NSLog(#"%#", queue.transactions);
for (SKPaymentTransaction *transaction in queue.transactions) {
//restore
}
}
There are a lot of transactions in queue.transactions while only one product was restored (in this example there were over twenty transactions written to the log). Why? Shouldn't there be just one transaction? Were I to start downloading the product from my server, it would be doing twenty downloads since there are too many transactions in the array!
You are supposed to process the transaction in the paymentQueue:updatedTransactions: method. The paymentQueueRestoreCompletedTransactionsFinished: is there to tell you that it is done.
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
for (SKPaymentTransaction *transaction in transactions)
{
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchased:
// process purchase
break;
case SKPaymentTransactionStateFailed:
// process error
break;
case SKPaymentTransactionStateRestored:
// process restored IAP
break;
}
}
}

Consumable In-App Purchase

Hi I'm trying to make an in-app store in my game for players to buy virtual currencies, which is consumables. But I am a bit unsure if my approach is correct or not. So I think it might be good to ask for help here.
After pressing the Buy Button, buyProductIdentifier is called
- (void)buyProductIdentifier:(NSString *)productIdentifier {
NSLog(#"Buying %#...", productIdentifier);
SKPayment *payment = [SKPayment paymentWithProductIdentifier: productIdentifier];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
and then followed up by paymentQueue
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
CCLOG(#"PAYMENT QUEUE CALLED!");
for (SKPaymentTransaction *transaction in transactions)
{
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchased:
[self completeTransaction:transaction];
break;
case SKPaymentTransactionStateFailed:
[self failedTransaction:transaction];
break;
// case SKPaymentTransactionStateRestored:
// [self restoreTransaction:transaction];
default:
break;
}
}
}
I tried by commenting out the SKPaymentTransactionStateRestored case in order to make the player complete a purchase every time instead of popping up a message saying that "You've already purchased this but it hasn't been downloaded".
Is this approach correct? if not, can you guys give me some hints?
Many thanks.
I don't think it is a code problem.
Are you sure that you you have created the In-App Purchases in iTunes Connect as "Consumable" ?
If you have chosen "Non-Consumable" it is only possible to buy the item once.

Clicking the IAP and taking a use to new view

Hey guys I am trying to figure out this IAP tutorial I would like to just make one simple app with my content instead of flooding the app store with a lot of smaller apps.
http://www.raywenderlich.com/2797/introduction-to-in-app-purchases
I have been going through this tutorial, I just need someone to help me after the person clicks the check to purchase and the transaction goes through I want it to take them to a new view controller could anyone help me with this?
Thanks in advance :)
Based on your comment i believe once the content is purchased then you want to show a new view
So here is the code for that
1) This is The Main Code for the transaction
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
for (SKPaymentTransaction *transaction in transactions)
{
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchased:
[self completeTransaction:transaction];
break;
case SKPaymentTransactionStateFailed:
[self failedTransaction:transaction];
break;
case SKPaymentTransactionStateRestored:
[self restoreTransaction:transaction];
break;
default:
break;
}
}
}
2) Since you are checking for successful payment : your case is SKPaymentTransactionStatePurchased:
The following method will be called
- (void)completeTransaction:(SKPaymentTransaction *)transaction
{
[self provideContent:transaction.payment.productIdentifier];
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
3) In the Provide Content Method you have to show your view :
- (void)provideContent:(NSString *)productId
{
if ([productId isEqualToString:kInAppPurchaseProUpgradeProductId])//kInAppPurchaseProUpgradeProductId is your IAP id in iTunes Connect
{
//Your code goes here;
}
}

In App Purchase Problem - Where Am I Going Wrong ? iPhone

I am trying to test my in app purchase (in sandbox) and have the following problem :
The app retrieves the available products successfully and displays them in a table.
The user clicks on "Buy"
The user is asked to enter user name and password (this is my test user).
A confirmation comes back saying on screen that the transcation was succesful.
The problem is that the content is then not downloaded and that the following method doesn't seem to be called :
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
for (SKPaymentTransaction *transaction in transactions)
{
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchased:
[self completeTransaction:transaction];
break;
case SKPaymentTransactionStateFailed:
[self failedTransaction:transaction];
break;
case SKPaymentTransactionStateRestored:
[self restoreTransaction:transaction];
default:
break;
}
}
}
Can anyone help ?
Check whether you added transaction observer
[[SKPaymentQueue defaultQueue]addTransactionObserver:mObserverObject];
Where mObserverObject is the object of class where you have implemented updatedTransactions method.