Goodmorning everyone ! I have a little question that I would like to ask you without going to waste an incident with Apple ...
In practice I am validating the receipt of payment for an in-app purchase, specifically a one-month subscription that unlocks some features of my app.
I parse the json correctly and apparently it seems to work fine but this does not always happen! In fact it often happens that the expiration date that I go to read from the json is not correct as if the subscription was not included in the receipt and I fished only those of the day before or in any case the previous ones.
This happens in sandbox and having checked the code and reviewed well, the parse of the document I could not find a solution because often the validation of the subscription is successful. I also searched online to see if it was a common problem but I did not find a solution or a discussion. My subscription does not include trial periods.
In the specific case this morning the first test was successful, but the validation was not valid. Checking the date shown was that of the previous day and then a previous subscription made yesterday. Once the subscription to the second test expired, the subscription was successful and also validated.
I am looking for some advice on how to go about checking the current status of a users auto renewable subscription.
At the minute I am using the following setup.
User registers and subscribes to the product.
The receipt is posted to my server.
Each night the server pulls all the users where the expiry date is in the past and then using the receipt check to see if the product has been renewed.
Now I think I have an issue with the above setup, it works ok for a small number of people but lets say I have a few thousand. I noticed that calling the Apple servers takes time and so I can't really run the above setup reliably.
I am thinking should I check the receipt locally every time the user opens the app and then post the latest info to my server each time and keep it updated that way? The only issue I have here is that if a user doesn't open for a while then I cant validate their status and my database isn't up to date.
Any advice on the proper approach to take would be great thanks.
This is a real problem.
At Elevate we would do exactly what you described, checking everyone's receipt every night. This was fine until the time it took to check all of our receipts exceeded 24 hours. At this point we implemented some smart pacing: Each time we checked a receipt and it wasn't subscribed and the user hadn't logged in, we would extend the date where we would check it.
This isn't bullet proof but is a decent balance of accuracy and efficiency.
I thought this was such a crappy problem I started a company to solve it. We do all the nasty receipt checking so you can just ask if a user is active or not.
I'm working on the app with monthly auto-renewable subscriptions. Right now I'm planning to check/validate the receipt every time on startup, but it seems that this approach is perceived as a bad practice, and some people are implementing the complex logic to calculate when user's subscription will expire to check the subscription receipt only one time per month.
Why?
If this will destroy the user experience (or, there is a chance for such turn of events), then how?
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..
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.