Cross-device In-AppPurchases - ios

due to the fact that Apple requires at least one auto-renewable subscription or one free subscription for a newsstand app, we changed all monthly subscriptions of our news app to auto-renewable ones while adding newsstand functionality.
When I try to buy one of these subscriptions on device #1 (e.g. my iPad) everything works fine. When I try to buy the same subscription on device #2 (e.g. my iPhone), I get a message from the Store Kit telling me that I am already a subscriber of this certain issue (which is ok as well) but afterwards the process is finished without having bought anything.
Checking the log shows, that the SKPaymentTransactionObserver delegate method paymentQueue:updatedTransactions: first gets a transaction for that product in the state 'SKPaymentTransactionStatePurchasing' (ok so far) followed by transaction in the state 'SKPaymentTransactionStateFailed'. Having a closer look on the transaction error code and message of the last transaction, the transaction error description says "Cannot connect to iTunes Store'. A second purchase of another product (bought the first time on the second device) works perfectly. Both purchases are done against the sandbox, does anybody has a hint how to address this problem.
Thanks for your help in advance
Michael

It shouldn't be possible to to purchase the same auto-renewing subscription on multiple devices, instead you should implement restore functionality, and restore on the second device. It's worth noting that the sandbox uses time compression for testing, so a 1 month subscription, will actually auto-renew every 5 minutes or so, and will only renew 5 times in a day. it's possible the original subscription has expired by the time you try to repurchase for the second time.
Often the sandbox error messages are not useful, the "Couldn't connect to iTunes" is not relevant.
I would suggest reading the whole of this page very carefully, as there are a lot of important details it's easy to miss. The bit about restoring purchases is here:
https://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/StoreKitGuide/MakingaPurchase/MakingaPurchase.html#//apple_ref/doc/uid/TP40008267-CH3-SW1
Best of luck

Related

iOS Manage my Subscription with Sandbox Account

Background
I have an application that supports in-app purchase with Apple subscription (in particular auto-renewable plans).
Using the WWDC 2016 slides material, in the Manage Subscription page, (inside iTunes & App Store -> View my Apple ID), we have this:
in which the user is allowed to change the current subscription plan (and also to cancel it). So far, so good.
Case scenario
I would like to simulate the scenario of a user changing account (or cancelling the current subscription) from the Manage Subscriptions page.
My issue (and possible solutions)
Thus, I am now facing the issue of testing the reported scenario.
It seems to conflict with Sandbox Account for testing purposes. In particular: if I try to login with the sandbox Apple ID into the iTunes Store & App Store page, I of course receive the message: iTunes Account creation not allowed (as reported in this question).
The most straight-forward solution seems the one reported in this thread (shortly: let the subscription plan auto-renew for 5 times with 5 minutes period, after which we should receive the 21006 error). Anyway, I am not sure that it could be applied to this case, since it seems only including the cancel my subscription case.
Another thread comes directly from the apple forum (this thread) but: (1) something is strange, i.e. the iTunes account creation not allowed error seems not to appear when logging into iTunes with sandbox accounts - while it happens to me systematically) and (2) even after logging in, the subscriptions are reported not to be shown.
I expect that everything works using a real Apple ID, but this is something I don't really want to do.
Conclusion (?) and question
So, finally :), my question. Is there a way to test the reported case scenario (or an equivalent one) without using a real apple ID, thus without triggering a real transaction? I don't really want to believe that the current sandbox testing mechanism does not include it.
Thanks in avance to all!
An iTunesConnect Sandbox test user account can test auto-renewing subscriptions but that account cannot login to iTunes and utilize the Manage Subscriptions.
Only Option
The only option I have seen being utilized is to essentially get your app fully approved for the app store (do not auto-release). Once approved, use a promo code to download and live test the Manage Subscription scenarios. If it all checks out, release the app. (I cant seem to find the link for this but will add it here if I come across it.)
Other Notes Testing Auto-Renewing Subscriptions
Duration times are shortened when test your auto-renewable subscriptions. Additionally, test subscriptions only auto-renew a maximum of six times.
Reference Link
~Emphasis is mine
1 week = 3 minutes
1 month = 5 minutes
2 months = 10 minutes
3 months = 15 minutes
6 months = 30 minutes
1 year = 1 hour
This thread has a response posted from an Apple Developer in regards to this situation. Link

Testing IAP subscription when renewed from iTunes or App Store app

I've been implementing auto-renewing In App Purchases and, using the info found here, have had little trouble the purchasing, renewing, & restoring transaction flows.
The problem I am having is finding a way to test when a user renews (after, presumably, canceling some time in the past) from their account page in either iTunes or the App Store app (Detailed here). I'm assuming, since those exist outside of the sandbox and when you log into one of them using a sandbox account that account is invalidated as a test account, there is no way to actually test this use case so I'm just looking for more information on the expected behavior to try and account for it.
I know that keeping a copy of the receipt around to validate will give the latest receipt as part of the JSON payload, I'm more curious for information on how StoreKit will handle this renewal. Will paymentQueue: updatedTransaction: fire with a new SKPaymentTransaction as soon as I add a TransactionObserver or will it stay silent until calling restoreCompletedTransactions and then the new SKPaymentTransaction will be part of that?
Yes, you are correct; paymentQueue:updatedTransactions: will fire, just as if you were making the initial subscription purchase.
You can actually test this since renewals within the sandbox kick in at a much faster pace (up to six times a day) as explained here (scroll down to the bottom under "The Test Environment").
Also when you verify the transaction with Apple's verification service right after you made a test subscription purchase, look for the expires_date field in the response, it will tell you when the next renewal will be triggered.

Apple In App Purchase & Apple "Store Credit"

We recently had a purchase on one of our apps. However, to our knowledge or the apps knowledge, the purchase never came through.
This only came to our attention when our user alerted us that they never received their virtual good. After looking into this, we saw the app sent the call off to itunes to process the payment, but never received the call back.
We asked the user to forward on the receipt to confirm the payment. The iTunes receipt read:
In App Purchase $15.99
Store Credit Total: $0.13
Payment Card Total: $15.86
Order Total: $15.99
"Store Credit"?! Would this have had some effect on the call back process to our app? Meaning we missed this sale totally? Is there a way around this issue?
I don't know if the 'Store credit' have any effect but we are experiencing a similar situation:
Sometimes our customers complain that they have purchased an IAP item and never received the credit in the app.
When we check their log (we keep a special log for that) we see that we got SKPaymentTransactionStateFailed response with 'Cannot connect to iTunes store' and later on, after 1-3 minutes we get SKPaymentTransactionStatePurchased.
We tried to ask Apple about it but couldn't get any explanation. I hope more people are having the same problem and can help us understand the situation.

Issues on testing In-App-purchase in iOS with Sandbox

I am facing a strange behavior with In-App-Purchase in iOS while testing with sandbox. Few things I observed, Please make your comments where I am wrong.
I know sandbox has small time interval for subscriptions like 30 minutes for 6 month subscription. I am using subscription model, when I am trying to purchase same item multiple time, it allows. Is that OK ? As per my understanding, it should allow only once to purchase and in subsequent call, it should say "Already purchased".
When I am restoring my previous purchase. Storekit is calling updateTransations with large number of previous transactions. Don't know why it is returning these large amount like 100, 200 ,245, 360, 650 seems like Random in every restore.
Please make your comments. Thanks in advance.
Regards,
OP
Dear All,
As I did not get reply on this thread. We have done testing an make the app live, app is working fine. Here are my comments that might be helpful to others.
When testing with sandbox, since time interval is not same as live app. You get 5 minutes for 3 month subscription and so on, so once your subscription expire your subscription will be renewed. If you will make one more payment request if subscription is live, you will get popup for already purchased.
Apple sends a large number of transactions, we need to add condition by our own, so that we will identify the current transaction and will process that only, rest will be ignored.
Hope this will help you all.
Thanks,
Om

Differentiating between initial buy and free "re-buy" in StoreKit/In-App Purchase

From the StoreKit guide:
If the user attempts to purchase a nonconsumable product or a renewable subscription they have already purchased, your application receives a regular transaction for that item, not a restore transaction. However, the user is not charged again for that product. Your application should treat these transactions identically to those of the original transaction.
This presents a huge problem in an app I am working on. We have licensed a large body of content from a publisher for sale through in-app purchase. They require that every time we sell a piece of this content (i.e. user pays us), our server calls an API on their servers to report the transaction. This is for accounting purposes and ultimately used to determine how much we pay them at the end of the month, per our agreement with them.
I have read several suggestions on SO and elsewhere about calling restoreCompletedTransactions rather frequently and maintaining a local understanding, on the device, of what the user has already purchased so they cannot be allowed to purchase it again. This to me seems like something that should be able to be implemented on the server side. However, the receipts that we are getting back from the Apple servers are exactly the same for a buy and a re-buy, as promised by the StoreKit guide.
If payment callbacks from StoreKit cannot be trusted as a valid accounting mechanism in this kind of situation ("you got paid" vs. "you didn't get paid"), what other real-time insights into transaction traffic are available? I don't think the publisher we are working with is going to be happy if we tell them we have to wait 45 days after the end of the month to get the REAL paid dollar amount out of iTunes Connect.
I have recently looked into the same problem. In my case, I wanted to implement accurate revenue tracking using Mobile App Tracking to track revenue generated from different customer acquisition campaigns.
Fortunately enough, there is a way to do it. It should be noted that SKPaymentTransactionStatePurchased vs. SKPaymentTransactionStateRestored solely depends on the initating action, e.g. whether you initiated a restore or a (re-)purchase, so that doesn't work.
What does work instead is checking for SKPaymentTransaction.originalTransaction which will be != nil for restores and re-purchases. The latter is unfortunately undefined behavior (docs). I'd consider a null check fair enough though.
Another option is to validate the transaction-receipt of transactions with SKPaymentTransactionStatePurchased and check that the original_transaction_id property in the returned, validated receipt matches the transaction_id.
The bad news is: In the current iOS version (4.3.x) there's no way to distinguish between a buy and a re-buy of non-consumable products.
To ease the situation I would recommend two things:
First
After a successful purchase, store the product identifier of the purchased product in the NSUserDefaults on the device. You can then hide the already purchased products from the user and thus handle a re-buy situation.
The NSUserDefaults are backed up by iTunes when the user synchronizes his device. So your stored purchase information is not lost when the user gets a new device.
Second
Store the receipt data together with the device ID on your server. Analyze the receipt's product identifier and the device ID.
If you receive another receipt with the same product identifier and device ID combination, then assume a re-buy. At least this would allow you to cover most of the re-buy cases.
Assuming that an ordinary iPhone user switches his device every 1-2 years, you will at least cover most of the re-buy cases and maybe apple will fix this in the future.
I have one solution,
Configure the product as consumable.
this will solve the problem - (They require that every time we sell a piece of this content (i.e. user pays us)).
Next you need to implement a logic in product buy option. It is in a way that once the user purchase a product the buy option need to remove otherwise the user may happendly go purchase and lost is cash once again for same product in same device.
you can use NSUserdefaults for this purpose.
thanks,

Resources