I have an in-app purchase which is Apple hosted. However I can't figure out how to download the content associated with it.
I could get the downloadable objects and request the download start:
[[SKPaymentQueue defaultQueue] startDownloads:currentTransaction.downloads];
that's when I get lost: what should I do after that?
I have taken a look at Apple doc and didn't find anything that could possibly help me.
Thx
Implement an SKPaymentTransactionObserver. The observer will be notified when the payment queue changes status. For example, paymentQueue:updatedDownloads: will be called with an array of SKDownloads whose downloadState indicates the status change for a download. If you want to know about completed downloads, look for downloadState == SKDownloadStateFinished.
See http://developer.apple.com/library/ios/#documentation/StoreKit/Reference/SKPaymentTransactionObserver_Protocol/Reference/Reference.html
I could solve my problem. Calling the
[[SKPaymentQueue defaultQueue] startDownloads:currentTransaction.downloads];
then
(void)paymentQueue:(SKPaymentQueue *)queue updatedDownloads:(NSArray *)downloads
is constantly called back. I guess I had forgotten some delegates or something like that. Besides that, I deleted the app from my device and re-compiled it again from Xcode. Then it worked like a charm =) Thanks
Related
I am currently having issues with my SKPaymentQueue and the observer, right now I cannot say exactly what the issue is, but it is not working.
When debugging I have noticed that my default SKPaymentQueue has multiple observers added to it, one being the class FBSDKPaymentObserver and it is listening to - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions. The thing is that it is working perfectly and observing all failed transactions.
Why does the FB-SDK do that?
How do i disable that?
Actually a pretty simple answer. I had forgotten I had set [FBSDKAppEvents activateApp];.
This sets a SKPaymentObserver at app startup which "swallows" the events which means that your own app observer does not get the messages from Apple with the same timing. Facebook gets it first and I am not sure how long after it will be sent by apple again.
I have been testing In App Purchases and can only assume that there are transactions stuck in the queue.
I have called [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; but every time I start the app it asks me to login to iTunes.
I have checked within -(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{ but even if I place an NSLog in the first line, this is NOT being called. Thus I don't believe this is being called.
I have also called NSLog(#"PAYMENTQUEUE:%#",[[SKPaymentQueue defaultQueue] transactions]); which shows null.
Can someone advise why I would constantly be asked to login to iTunes every time I start the app all of a sudden? As I say, I can only assume it is a transaction, but how can I track it down?
Your device has been infected with the "endless loop" for failing to have called finishTransaction. It will reoccur every week like clockwork. Check out the IAP Developer's Forum for more info. The queue is empty because you need to log in as the 'infected' user.
Just in case anyone comes across this later on with the same issue. I left the device and stopped trying to sort it out. I deleted the app too.
Around half an hour later I was prompted to logon to the iTunes sandbox store (remember there was no app on anymore).
I logged in, and this scenario occurred another time.
After that all seemed to go quiet.
I have tried installing the app again today (12 hours later) and the issue has gone away.
I can only assume something got jammed up?
In-app purchases are working correctly with my app. I'm even using my own server to validate transaction receipts.
However, I seem to be having an issue with the SKPaymentQueue TransactionObserver and/or DefaultQueue.
An iTunes prompt, for an old test account, will appear whenever I make the following call -
SKPaymentQueue *currentQueue = [SKPaymentQueue defaultQueue];
I cannot figure out how to stop this old test account from appearing whenever I need to make a purchase or restore transactions.
Someone has recommended the following code, which would appear to finish all old transactions, but it doesn't resolve my issue.
SKPaymentQueue* currentQueue = [SKPaymentQueue defaultQueue];
[currentQueue.transactions enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[currentQueue finishTransaction:(SKPaymentTransaction *)obj];
}];
I've also tried removing the app, deleting the old test account from the device and also iTunesConnect. The old user prompt still appears!
Any help would be greatly appreciated, thanks.
are they sandbox transactions or production transactions?
sandbox transactions are a big mess, sometime i find old transactions in the queue, and the lifecycle of sandbox transactions is not totally coherent with production transactions's lifecycle
I just solved the same problem in my code. The issue was because I was not removing the transaction observer when the app would quit.
add this to your app delegate:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self.storeManager];
}
- (void)applicationWillTerminate:(UIApplication *)application
{
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self.storeManager];
}
I also needed to restart my devices to make sure they were completely clear. Then when you do a restore all purchases the system should be back to normal.
I'm developing an ios Application with IAP feature. It works well. But I encountered a strange issue today. It always show me a message to ask me to "Sign In to iTunes Store" for some reasons. Here is the screenshot:
It always shows this every time when I start the application or resume from background. It even still shows this after I delete and reinstall the application. When I setup breakpoints in my source code. There is no any transaction,payment delegate callbacks. Can anybody tell me what the reason is ? Could it be the problem of Apple IAP Sandbox? (I run the same application in other devices without any problem. I can purchase, restore in Sandbox.)
I've had this problem too a couple of times, it turned out I was stopping processing of transactions before calling finishTransaction on all queued transactions. I was forgetting to finish failed transactions in the particular case.
So, you could try letting your application run once and call finishTransaction for each and every one in your observer delegate like this:
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
foreach(SKPaymentTransaction *tr in transactions) [queue finishTransaction:tr];
}
i.e. finish every transaction irrespective of transaction state.
After the test run revert to your original handling code.
Hope this helps.
I tried multiple things :
call finishTransaction for all queued transactions as explained by mpramat (in my case, the array was empty)
Reboot the iDevice
Delete the test account in iTunes Connect.
Finally, the only thing that surprisingly worked for me was to delete the app in the iDevice then re-install it via XCode.
I have an issue with a live app where incomplete purchases are being mishandled. I am trying to test my new code to make sure that this will be taken care of, so I download the live app, cause the problem, then load my development app (or Ad-Hoc app) hoping that the StoreKit Observer will catch the incomplete purchase notification. No matter how I do this (development or Ad-Hoc) the observer does not fire a notification.
My general question is: How can I simulate incomplete and interrupted purchases in the App Store testing environment?
My more specific question is: Can I simulate the specific issue where the user must leave the app to confirm their current credit card pin number on the app store?
According to this helpful page:
Test an Interrupted Transaction
Set a breakpoint in your transaction queue observer’s
paymentQueue:updatedTransactions: method so you can control whether it
delivers the product. Then make a purchase as usual in the test
environment, and use the breakpoint to temporarily ignore the
transaction—for example, by returning from the method immediately
using the thread return command in LLDB. Terminate and relaunch your
app. Store Kit calls the paymentQueue:updatedTransactions: method
again shortly after launch; this time, let your app respond normally.
Verify that your app correctly delivers the product and completes the
transaction.
Hope this helps someone.
To your general question:
SKPaymentTransaction provides several transaction states like SKPaymentTransactionStateFailed
According to the Documentation you can check out the error property to see what happened.
For example you can check it in -(void)paymentQueue:(SKPaymentQueue *)updatedTransactions:(NSArray *)transactions callback like so
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{
for (SKPaymentTransaction * transaction in transactions) {
switch (transaction.transactionState)
{
case SKPaymentTransactionStateFailed:
...
break;
default:
break;
}
};
}
Hope this helps.