paymentQueueRestoreCompletedTransactionsFinished: vs updatedTransactions:
Solution 1
There is an excellent WWDC Video about using StoreKit, it is WWDC2012 Session 302.
To isolate each purchase, your updatedTransactions
method could look something like this:
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
for (SKPaymentTransaction *transaction in transactions) {
switch(transaction.transactionState) {
case SKPaymentTransactionStatePurchased:
// Unlock content
//... Don't forget to call `finishTransaction`!
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
case SKPaymentTransactionStatePurchasing:
// Maybe show a progress bar?
break;
case SKPaymentTransactionStateFailed:
// Handle error
// You must call finishTransaction here too!
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
case SKPaymentTransactionStateRestored:
// This is the one you want ;)
// ...Re-unlock content...
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
}
}
}
Once you've determined that the purchase is being restored, you can make content available as you see fit - preferably by calling a separate method from within that switch statement and passing the transaction as a parameter. The implementation is up to you of course.
Solution 2
- Call
[[SKPaymentQueue defaultQueue] addTransactionObserver:self]
in(void)viewDidLoad
or equivalent if applicable. - Then call
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions]
. (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
will be called accordingly through (2).
If you don't call the method in (1), the application will never reach (3) to restore transactions in the first place.
Solution 3
I had this same issue with paymentQueueRestoreCompletedTransactionsFinished never getting called. I fixed by going to iTunes & Aoo Stores in Settings and logged out of the sandbox test account and tried it again. Worked as expected the next time after being prompted to login again on a restore.
hzxu
Updated on July 24, 2022Comments
-
hzxu almost 2 years
I am restoring completed transactions (recurring) with
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
and in
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
I got a list of history transactions restored, made by the app, but the method:
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
is not even called once, so I wonder which one should I use? I did some research and found that
updatedTransactions:
method should be used with checking transaction state, but if I got a list of transactions restored, it is just meaningless to treat them all as transactions. Which one should I use? DoespaymentQueueRestoreCompletedTransactionsFinished
only gives me the latest one (ie sandbox subscription expires in several minutes and I got a full list of history transactions made when testing, inupdatedTransactions
). -
hzxu over 11 yearsYes I did do 1. the problem is the method in 3. gives me a list of all subscription the sandbox account has made. I only need the one which is successfully restored.
-
hzxu over 11 yearsYes, but what I got is more than 1 transactions restored for the same product ID, then do I use the transaction with most recent transactionDate?
-
Ephemera over 11 yearsHmm that shouldn't be happening... That possibly means, previously, the transaction wasn't completed with
finishTransaction:
. I'd reset your App (clean build and delete data from the iOS Simulator) to get rid of the queued transactions. Before you do that though, where are you setting up yourTransactionObserver
? -
Takagi almost 11 yearsMaybe missing break in the SKPaymentTransactionStatePurchasing case?
-
Chirag Shah over 7 years@hzxu i have same problem, Did you find any solution?
-
Henry Mueller about 3 yearsI am pretty sure I would never have tried this as a fix, but it was exactly my issue. Thank you very much! I certainly hope this is a "dev environment" issue... seems like a lot of apps would break if this happened in prod.