"this in-app purchase has already been bought"

Right.


So Im testing my code. I ran a test for what happens if the user interrupts the purchase before i've actually given it to them - in other wods "SKPaymentTransactionStatePurchased" has happened, but i havent given them their purchase yet (say the phone was turned off), so "[[SKPaymentQueue defaultQueue] finishTransaction:transaction];" Wasnt called.


Now when I try to make the same purchase i get a message box saying:


"this in-app purchase has already been bought"


Which is correct. HOWEVER, I dont receive ANY messages in my SKPaymentTransactionObserver after this? I would be hoping to receive a message saying "SKPaymentTransactionStateRestored" or similar? But I get nothing! So I cant now finish this transaction!


So my code is now stuck with no way to give this purchase!


Is there supposed to be another message when this happens? How am I supposed to handle this? The documentation says absolutely nothing that i can find.

Add a Comment

Accepted Reply

Either you do or do not have an active transaction observer.


If we assume that when "...the user interrupts the purchase" you caused the transaction observer to disappear then StoreKit never got to send a call to updatedTransactions. StoreKit is waiting to send the user the transaction in a call to updatedTransactions as soon as that user adds a transaction observer. In my flow for IAP I let the user select 'Get approved purchases' and, if selected, I add the transaction observer without generating any purchase requests. That covers the 'parental approval required' issue at the same time it covers errors like you describe. However 'Apple best (sic - IMHO) practice' is to add a transaction observer on launch and keep it alive at all times.


If, on the other hand, we assume you still have a transactionObserver and it got sent the transaction but you failed to process it for whatever reason then you will need to remove that transaction observer and re add it. See my method above - and in this case 'Apple's best practice' will have to wait for the app to close and get relaunched.


And if you did 'finishTransaction' then ask yourself why you didn't give the user the IAP credit....But anyway, isn't the full error message 'this in-app purchase has already been bought. Tap 'Buy' to download it again for free." - If the user taps 'Buy' then a new transaction will be sent to updatedTransactions and clear this purchase.

Replies

Either you do or do not have an active transaction observer.


If we assume that when "...the user interrupts the purchase" you caused the transaction observer to disappear then StoreKit never got to send a call to updatedTransactions. StoreKit is waiting to send the user the transaction in a call to updatedTransactions as soon as that user adds a transaction observer. In my flow for IAP I let the user select 'Get approved purchases' and, if selected, I add the transaction observer without generating any purchase requests. That covers the 'parental approval required' issue at the same time it covers errors like you describe. However 'Apple best (sic - IMHO) practice' is to add a transaction observer on launch and keep it alive at all times.


If, on the other hand, we assume you still have a transactionObserver and it got sent the transaction but you failed to process it for whatever reason then you will need to remove that transaction observer and re add it. See my method above - and in this case 'Apple's best practice' will have to wait for the app to close and get relaunched.


And if you did 'finishTransaction' then ask yourself why you didn't give the user the IAP credit....But anyway, isn't the full error message 'this in-app purchase has already been bought. Tap 'Buy' to download it again for free." - If the user taps 'Buy' then a new transaction will be sent to updatedTransactions and clear this purchase.

I didnt call 'finishTransaction' on purpose. This was a test to see what would happen if the use quit out of the app, before i had chance to save their credit on my server.


When I come back in, and try to now complete the purchase - you are correct the message reads as you stated..


If I click "Tap buy to download it again for free". The "updatedTransactions" is NEVER EVER called again. I have breakpoints to check. So there is NO WAY for me to dismiss this transaction and mark it as finished (or is there?)


"paymentQueueRestoreCompletedTransactionsFinished" is called, but Im not sure what to do with that message, but "updatedTransactions" is NOT called .. EVER.


Which is my problem.


My transactionObserver is valid the entire app, from the very start.

There are two unusual situations in your post:


1) If I click "Tap buy to download it again for free". The "updatedTransactions" is NEVER EVER called again.

Never Ever! If you have an active transaction observer that is unexpected. Perhaps the second purchase transaction is being blocked by the first transaction that was not finished but was already sent into updatedTransactions by the current transaction observer. Maybe what you need to do is remove the transaction observer and then add it again (I don't know if just adding it will work).

2) "paymentQueueRestoreCompletedTransactionsFinished" is called. This can only happen if you execute a restoreCompletedTransactions. Since you never finished the transaction for the original purchase, it is not unreasonable that there are no 'competed' purchases to be restored.

Did you ever figure this one out? I have the same problem.

In my case the problem was caused by adding the `SKPaymentTransactionObserver` to the `SKPaymentQueue` after another library had already registered its own observer. Switching the order of initialization so that my app registered its own observer first fixed the problem.



I've provided in more detail here: http://greensopinion.com/2017/03/22/This-In-App-Purchase-Has-Already-Been-Bought.html

i buy uc his not working. I don’t bro I want buy us.