Non-Renewing Subscription: turn back time - ios

I'm creating an app that will unlock features to users for a limited time. Premium features let's call them. They can buy a subscription for a month, 6 months or a year. These subscriptions would be non-renewing. After a lot of searching the web and finding very different "solutions", I turn to StackOverflow for what the best should be.
When a subscription is bought, the end date is stored locally on the device until synced via iCloud, because Apple wants you to have this subscription on all your devices. The app checks iCloud to see if the current subscription is still available, shows a nice countdown for the users with days left. But I'm currently encountering a problem. When the user has paid for a month, and changes the date of the device to a year earlier (or something else), it can use the subscription for a year. The countdown now doesn't show 23 days left, but 389.
How can I avoid this?
Should I check a certain server to check for the real time and date?
What if a user only uses the app in airplane mode?
Thx in advance!

You could check standard web-based time-servers to do this. Since I have my own server (as part my in-app purchase mechanisms), I just ask my server for the current time, at the server. I do this every time the app launches, and every time I make a server-call (usually when in-app purchases are done). I then store the time locally (either in the KeyChain or NSUserDefaults, can't remember which!), and use it (and the device time, which ever is later in time) to compute purchase expiries.
Of course, this assumes that the user has a network connection when they launch the app. You can only do so much though!

Actually what happening is after successful completion of your InAppPurchase apple will provide you a Transaction Reciept...this transaction reciept is stored in locally . When you want to check the subscription is in active or expired you need to request the storekit with this transaction reciept then the store kit will give you the status .. if the status is 0 then it is in active state . if the status is 21006 then your transaction is Expired. If you want to continue the subscription in antoher device then you need to Restore the transactions there .. after completion of the restoration you will get all the product ids and the transaction reciepts.. you need to store the transaction reciepts there and you need to pass this for the storekit whether it is in active or expired state .. sorry for my poor english..

Related

Best strategy to Get In-App Purchase Auto-Renewable Subscription end date

I have been reading a lot about auto-renewable subscriptions but so far I could not get a satisfactory answer to my questions.
Imagine a user subscribed to my app for 1 month and the very first view of the app has some content that only visible with subscription. Now imagine it's the first day of second's month subscription (after auto-renewed). If I don't query the expiry date from apple server, user can't see subscription items, because the expiry date of first month already passed and we need to get the new expiry date.
My questions are:
1- Is there a way to get the end date of the subscription offline and without disturbing the user (with password prompt etc.)? How user will get subscription content if it is the first day of auto-renewed subscription (second month and so on) and if user don't have internet? Will he see locked content if he has no internet? If so this is sounds weird to me.
2- If it is not possible to get expiry date of auto-renewed subscription offline, what is the best approach to get expiry date of auto-renewed subscription without asking or prompting something to user? Because we want to show the very first page of the app with subscription content smoothly. What comes to my mind is to make user wait during launching and check expiry date from server.
I am sure many developers are still concerned with those issues.
It's been a long time since the last time that I integrated an auto renewable subscription and it harder than I expected, but I can give you some general hints and some more specific for your question.
Starting from your question.
Not exactly, you can get the last updated receipt by asking getting the receipt from the receiptURL, here is where I've found a really gray area. I never had a chance to understand exactly when a receipt is updated automatically, probably this happen right after Apple charged you (of course this update needs a connection). This doesn't seems to happen when you have restored a purchase on another device.
Yes there are, when you have a chance to validate the receipt you can store the expire date somewhere (maybe in a secure way) and only before one or two days after that day try to validate it again. If you want you can apply also a grace period after.
Other tips:
you MUST create a way to restore the purchase or your app will be rejected
on sandbox at the first launch the receipt will not exist, but in production an app will always have a receipt, maybe without subscription info, but there is. Thus if you want to simulate some use case in sandbox environment is better if you restore the purchase right after the launch of the application.
restore purchase always requires username and pwd and refresh receipt seems too
Maybe some of this info are a little bit outdated, I made the integration with iOS7 and never had a chance to update it.

Cross-device In-AppPurchases

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

in-app purchase for auto-renewal subscriptions notifications

I've been reading the various threads on in-app purchases auto-renewal subscriptions, and I think I've pieced together most of the information I need, but there are a few missing pieces. I'm hoping someone can help me.
The situation:
I have various subscription packages the user can subscribe to (e.g., package A for £1 a month, package B for £2 a month, etc.). I store the user's subscription information in my database. When the user logs in, I check which package he's on and if it's expired or not. My website, android and iOS all use the same database, hence this approach seems to make sense.
Subscribing users via in-app purchase seems straight forward enough. I check paymentQueue and once the payment is cleared, I can update my database.
My questions:
1) My understanding is the user can use iTunes to manage their subscription. Say, they go in to iTunes and cancel their subscription, how can I be notified so I can update my database? Do I need a daemon that checks expired subscriptions to see if the user renewed?
2) If the user wants to upgrade their subscription from Package A to Package B, how do I handle the pricing? Say on Jan 1st, they buy Package A, I charge them £1.00 and set the expiry date to Jan. 31st. On Jan. 15th, they want to upgrade to package B via in-app purchase. Ideally, I would charge them £2 for Package B minus £0.50 of credit they have for Package A and set the new expiry date to feb 14th. However, Apple forces me to associate each package with a tier price. How can I handle this? I don't want the user to wait until the end of the month to put them on a higher tier package...if they upgraded mid-month, it means they want the new content package B will deliver to them immediately.
Any help appreciated!
Thanks!
1) Yes you'll have to reverify your receipt check out the Receipt Validation Programming Guide in the documentation. They mention some important keys:
status - 0 if receipt is valid, or an error code
receipt - JSON response of the receipt
latest_receipt (auto-renewable only) - base 64 encoded receipt for the most recent renewal
latest_receipt_info - JSON version of latest_receipt
With this information, when a purchase is made, send the receipt to your backend for validation, the backend will keep the receipt in the DB and verify with status = 0 that it's a valid receipt. From there, every x days you can validate that receipt with a chron job, daemon, etc. and reverify. The response back each time will have latest_receipt_info that you now need to save to your DB so you have an up-to-date receipt for the next check in x days. This way you will always have the latest receipt. There is no instant notification for telling when a user cancels a subscription, but with this you'll know every x days if they have the subscription still.
2) Pricing like this unfortunately can't be handled. It was not intended for a user to "upgrade" with subscriptions - each subscription is access to it's own exclusive content as of this writing. However, if a customer emails in and complains about it, you could ask for their user name and figure out in your DB if this user has indeed upgraded mid-month and reimburse them appropriately. Very old-school and not feasible for a big user base, but hopefully you won't have that many and can keep them happy.
EDITED
For the second question, Apple's auto-renewable subscription system does not technically offer upgradeable plans between different products.
Every subscription is a stand alone product and it's up to the user to turn on/off subscriptions manually using the Subscription Manager in the iTunes Store.
However if package A and package B offer the exact same content only different duration than what ajay_nasa said is correct, you can create an single auto-subscription product with different duration options. If the user is on 1 month subscription and then the user tries to change to 2-months subscription they will get the following error message asking them go to the App Store's subscriptions manager
So basically the ONLY place the user can actually change the subscription's length is in the App Store. Whether Apple decide to pro-rate the amount left on the old subscription or just append it to the current one is really up to Apple. You need to make sure the user have access to the subscription as long as it's active by reading the Original Purchase Date and Subscription Expiration Date field from each receipt entry and determining the start and end dates of the subscription.
Answering question 1, you can verify subscription receipts in the same way as other IAP, but you'll need to check it periodically to see if the subscription has expired (the verification will tell you if it's expired).
There is more info on the Apple docs here:
http://developer.apple.com/library/mac/#documentation/NetworkingInternet/Conceptual/StoreKitGuide/RenewableSubscriptions/RenewableSubscriptions.html
Actually, Apple's auto-renewable subscription system does offer upgradeable plans.
To achieve this we simply should add duration in existing Auto-Renewable Subscription. Every Auto-Renewable Subscription could be family of Subscriptions so whenever developer wants to achieve upgradation in subscription he should add duration in existing Auto-Renewable Subscription with different productID.
Whenever, user upgrade his plan in between the month then his upgrade plan will be automatically works from next month.
Answering to your question #1
Recently Apple launched a feature to enable server notification whenever the subscription is renewed. However, the subscription should be in-app.
See the links given below for your reference:
https://help.apple.com/itunes-connect/developer/#/dev0067a330b
&
https://itunespartner.apple.com/en/apps/news/45333106?sc_cid=ITC-AP-ENREC
We Need to Check Cancellation-Date provided in Receipt.

switching from auto-renewable to renewable subscription

My client has an app in the App Store that uses the auto-renew subscription type. Upon resubmitting the app it was rejected because they claimed they don't have periodic content (even though they do... but this problem seems to be ubiquitous currently). I was wondering what the best approach is to deal with non-renewing subscriptions. Specifically issues dealing with:
Losing your device and restoring your subscription
Restoring your subscription to multiple devices (as mandated by Apple)
Preventing users from abusing the system.
What I came up with so far is the following:
When a user purchases a 1 month subscription this information is stored locally (say in NSUserDefaults). Also, a unique ID is generated and sent to my clients server. When the subscription ends users are asked whether they want to be directed to the purchase screen. If users wishes to save the subscription in case they need to restore they device, or in case they lose their device, they can opt to have the unique identifier sent to their email address (which they are prompted to enter, indicating that this information will not be used). The app has an place to enter this ID. It will retrieve the subscription information from the server and again store this in the NSUserDefaults. Each time a restore is done, a counter is increased. When it has reached say 5, the user can no longer restore. The same principle described above works in the case of sharing subscriptions over multiple devices. Does this seem like a reasonable solution (and one that Apple will accept)?
Thanks for your time!
Why don't you want to use Apple's restoreCompletedTransactions? It just provides you with information about ALL the previous purchases, on any device, at any time.
http://developer.apple.com/library/mac/#documentation/StoreKit/Reference/SKPaymentQueue_Class/Reference/Reference.html#//apple_ref/occ/instm/SKPaymentQueue/restoreCompletedTransactions

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