26

Sorry for the millionth question about iTunes subscriptions, but I still have a few doubts.

Basically I'm implementing auto-renewable subscriptions in my app and I want to make sure I got it right. Here's a list of steps to take that I came up with:

  • whenever an user buys a subscription, send the receipt to the server to validate it
    • if the receipt is valid, save it on the database
  • on application load, ask the server if a receipt for this UDID exists (this is to figure out if the user has a valid subscription)
    • if so, check if a new item has been added on the store in a date range from the subscription start date to the expire date
      • if any, notify the user about those items in some way and mark them as freely downloadable

Are these steps correct? And if so, why does the Apple doc say:

In most cases, your iOS client application should not need to change. In fact, your client application is now made simpler, as you can use the same code to recover auto-renewable subscriptions as you do to recover nonconsumable products. This is described in “Restoring Transactions.”Your application receives a separate transaction for each period of time where the subscription was renewed; your application should verify each receipt separately.

To me it looks like this needs some code to handle all the various cases I mentioned, instead. Or I'm totally wrong about it. Am I?

Plus, how do I know about the subscription expiration date? I can't find a way to get this information anywhere. Am I supposed to save this on my own database?

Update:

I've figured out a few things since I posted this question. Feel free to correct me if I'm wrong.

First of all I guess I'm supposed to store the length of the subscription somewhere on my own database, because as stated on Apple's docs, you cannot retrieve it in any way through Apple's web services. In fact, each subscription length has a different product identifier, so you should have a way to convert a product identifier to a subscription length.

Also, Sylvian has posted details about his implementation of auto-renewable subscriptions, so at least I know my thinking wasn't too much flawed.

Now the only problem is this: how do I know that an user has a valid subscription? I could store this information on my server, yeah, but how do I associate an user with a completed transaction? Should I save the device's UDID?

Community
  • 1
  • 1
ySgPjx
  • 10,165
  • 7
  • 61
  • 78
  • 1
    You should check out deforums.apple.com instead for is question. No one knows the answer yet, but developers are discussing about it there, – honcheng Mar 17 '11 at 00:35
  • @honcheng I posted here because I couldn't find an answer there. – ySgPjx Mar 23 '11 at 11:58
  • I'm struggling with exactly the same issues, foremost with the identification of 'same user - other device'. Did you get any further with this? – Kai Huppmann Apr 12 '11 at 11:38
  • This link https://stackoverflow.com/questions/22680059/auto-renewable-subscription-in-ios7/45220204#45220204 might help you. – Arun Jain Jul 27 '17 at 12:45

4 Answers4

30

Here is how we implemented In App Purchases and specifically the new auto-renewable products at my company.

The application transmits the transaction receipt to our webservice, we return OK to the application if we handled it correctly and Apple could verify it. In that case we updated the user account (i.e. the database) to say "yes he has paid and his subscription is valid till the receipt expiration date".

After the OK for this webservice, the application reloads the account info through another webservice, and see there is a valid subscription. That was it... Until auto-renewable products appeared.

We now had to implement some CRON jobs which runs every day: every day we make a list of passes which are supposed to expire, and we ask Apple if the original receipt is still valid: the magic thing is that in their answer, there is a field latest-receipt which embeds the latest receipt. If it is not the same as the one we have, we understand that the subscription has been renewed automatically, we store the latest receipt for the next cron check, and we update the user account to extend the expiration date.

Hope it helps.

ySgPjx
  • 10,165
  • 7
  • 61
  • 78
Sylvain
  • 1,553
  • 11
  • 15
  • Thanks. I have a question: you said you update the user's account on the database after the receipt has been verified. But what you really mean with "user account"? Is it a record on your database based on the device's udid? – ySgPjx Mar 30 '11 at 12:58
  • Our customers have to login so every webservice knows about the user calling them. We have a record in the database which says the account has a subscription. – Sylvain Mar 31 '11 at 09:29
  • I've seen lots of apps doing it without using another user management layer, but just the iTunes account. How do they do it? – ySgPjx Mar 31 '11 at 12:58
  • 4
    If the subscription has been expired, do you check for a possible resubscription (can be done outside of the app in AppStore) every day as long as the user has a account on your system? Resubscriptions wouldn't have imediate impact that way. – Rene Berlin Jul 26 '11 at 15:55
  • @p2ph8 -> Is it possible you can post any source code from your solution regarding how you approached auto renewable subscriptions? Thanks – zardon Oct 31 '11 at 09:04
  • 4
    @Sylvain - I think your solution breaks down when user B logs into your app on a device where user A has purchased your in-app product. So, imagine user A with iOS account A' bought an auto-renewing subscription. Now, A logs out of your app and user B logs in. She tried to purchase your product using the same A' iOS account. Apple says 'OK' and doesn't charge the user again, and your server now credits user B with the purchase. Result is two records in your DB of purchases, but only one payment. And the cron job marks both users as good when the subscription renews. Did you solve this problem? – psychotik Jan 04 '12 at 23:21
  • 2
    @psychotik, this problem that you mention can be countered by registering the original transactionid of the receipt upon receiving it. If you receive a new subscription which has the same transactionid that is already taken by someone, you won't perpetuate this subscription to person B. – Hallaghan Mar 28 '14 at 17:31
  • So how should I handle case when 2 users have actually bought 2 different subscriptions (and original transaction id is same)? Or is this not possible? – vlaku Mar 23 '16 at 09:27
  • How to cancel an auto renewable subscription and notify my server or phone so that I can call cancel subscription in my server.??I am stuck on this.Can anyone help?Thanks. – abhimuralidharan Jul 06 '16 at 09:31
8

I think I found a solution. It doesn't require an additional username/password and it seems to be working.

Note: If you think this is inappropriate, please explain why in the comments. Thanks.

Basically, whenever an user buys a subscription, I validate the receipt against my server and store the receipt data in the user defaults. Then, when the app is opened, or whenever I need to check if the subscription is still valid, I retrieve the previously saved receipt data from the user defaults and validate it against the server.

My webservice just returns whether the subscription is still valid or has expired, plus some other related information such as the subscription length. To do this, it just queries the iTunes server as usual, and checks if the status response is nonzero. 21006 means that the subscription has expired.

ySgPjx
  • 10,165
  • 7
  • 61
  • 78
  • How do you handle multiple-device-users? – Kai Huppmann Apr 12 '11 at 11:23
  • @Kai I have a 'restore' button which calls `restoreCompletedTransactions`, just like many other apps do. – ySgPjx Apr 12 '11 at 12:11
  • Isn't this a little bit of overhead for Apples servers? I normaly would save the expire-date from the verification process to the database, but i can't trust apple, because in the sandbox - mode a monthly subscription ends after 5 minutes!! Why? Is there a better way to verify the subscription length. I've read in Apples document, that the subscription lenght will have to be calculated by the app (or the server). – NicTesla Jul 07 '11 at 09:32
  • But when i calculate the subscription lenght for a monthly subscription and use 30 days for providing the content to the user, there will be one day missing, i guess, where my service won't provide content to the user. So to conclude, I'd suggest Apple provides a clearly way to get the expired date. – NicTesla Jul 07 '11 at 09:33
  • 3
    @NicTesla: in the sandbox subscription lengths are reduced to make testing easier. It's not documented though. Check this http://dev-ios.blogspot.com/2011/05/validity-time-auto-renewables-in.html – ySgPjx Jul 07 '11 at 10:06
  • @NicTesla: I think it is safe to use the subscription expiration date returned by Apple's servers. In production it returns the right date and it is working for me. – ySgPjx Jul 07 '11 at 10:08
  • Thank you very much!! This really helped me, getting on with my problem. But will the autorenewable subscription also be renewed after the subscription has been expired (e.g after 5 minutes)? – NicTesla Jul 07 '11 at 10:40
  • Yes, but from my tests I've found that it stops autorenewing after 5 times. After that, the test account becomes 'invalid', and you have to create another one. Still, this is not documented and it's just what I (and apparently others on Apple's devforums) have experienced. – ySgPjx Jul 07 '11 at 10:57
  • Thank you for your response. But from my point of view, it does seem to "trigger" the renewal process at all (Serverlogs say so). It normally should, because I've configured the product as an autorenewable product. – NicTesla Jul 08 '11 at 07:08
  • will the receipt data be updated during renewal? Or I can use the receipt data during the original purchase and call apple server to check for the 2nd, 3rd renewal? – Howard Feb 15 '12 at 09:40
  • @pt2ph8: I am sad you marked your own solution as accepted. My solution is the one recommended by Apple, and the most upvoted: you should consider accepting my solution if it helped you solve your own problem. Thanks – Sylvain Mar 24 '16 at 16:05
  • How to cancel an auto renewable subscription and notify my server or phone so that I can call cancel subscription in my server.??I am stuck on this.Can anyone help?Thanks – abhimuralidharan Jul 06 '16 at 09:31
  • @abhi1992 Do you got solution for auto renewable subscription cancellation process ? – Yohan Sep 14 '16 at 09:49
  • @Yohan As per my knowledge only the user can do the cancellation and our only option is to call the receipt validation api with the saved receipt.If cancelled you will get a specific error code.Or you should set a cron in backend server and call this api. – abhimuralidharan Sep 19 '16 at 09:23
  • @abhi1992 What will happen to the main receipt if activates again after cancellation? Whether new receipt will be generated or still be the old one? – Yohan Sep 19 '16 at 10:27
  • @Yohan New receipt should be generated. – abhimuralidharan Sep 30 '16 at 06:26
0

If your app has some user management i.e. you use username/password to use the app, then you have to maintain a server to record the purchase/validity of the currently logged in user. This is applicable for normal subscription and non-consumable purchase. But... if you use the new auto-renewable subscription, then it's NOT possible to maintain multiple user in that app, because : this kind of purchase can not be done multiple times within the subscription period using the same Apple ID from the same application and I found it really annoying and finding a better solution for this case i.e where I have multiple child account in the app but I want to use the same Apple-Id to purchase a auto-renewable subscription for each account. And I think I have to use the old subscription model. Any new thoughts ?

Tushar
  • 3,022
  • 2
  • 26
  • 26
  • Still fighting with renewable subscription in my multiuser app. Normal subscription was working fine, but we want to use new auto-renewable. Getting issues choosing different productId (of same kind & purpose) for each new user in the app. :( – Tushar Jul 27 '11 at 05:45
  • Did you get the auto-renew working for a multi-user app? – Merkidemis Oct 10 '14 at 19:26
  • Is there any solution regarding multi user app, for auto-renewable subscription ? – dip Mar 28 '18 at 06:21
-2

as far as I have understand it the apple server will contact you (or the customer with his iPhone) and tell "look here I have a valid purchase for you". Inside your App you read this message and unlock the regarding content for use. The next step is to tell the apple server that you have responded to the receipt and the apple server will not show the message again.

So with a renewable subscription you get for each period a new message. Correct me if I'm wrong, please.