I am trying to implement an auto-renewable subscription in an app, it works like this:
The user buys a subscription.
The app gets the receipt and sends it to my webService.
My webService verifies the receipt, changes the role of the user from Free to VIP and also records the receipt.
Now the question: When the expiration date comes, should I verify the receipt at my webService or in the app?
If it is on the webService, should I attempt to verify the old receipt (stored) and Apple returns to me the latest one if renewed or cancelled?
If it is on the app how should I proceed? Is there some kind of notification from storeKit when the subscription is renewed or cancelled?
If the right approach is the second (App), since my webService controls whether the role of the user is Free or VIP, every time a renewal happens I will have to send the latest receipt to my webService, so, it can manage the user's role properly. That's why I need to know how and when to get the latest receipt to send.
The more useful approach is the first one - through your web Service.
When you will attempt to verify the old receipt (stored) and Apple may respond in one of the following two ways:
If user has not cancelled the subscription, you will get the latest receipt with the expiration date extended.
If user has cancelled the subscription, you will get the receipt with the old expiration date only.
So based on the expiration date you can create your logic to whether extend the VIP membership or not.
Additionally, you can configure your authentication call on app side to re-authenticate user every 12 hours or 24 hours so you will get the updated membership status as well.
Related
So our ios app has issue of not updating the expiry date.
Now we want to update all users expiry date from directly our php backend using the verify apple receipt code of node js
But the problem is data base has no purchase id, installion id.. so how do we identify and get the receipt of X user
we are looking at https://www.npmjs.com/package/node-apple-receipt-verify
So User1 emails us he purchased the auto renewal but it did not renew, now we want to update User1's expiry date before he opens the app
You have the send the receipt from the iOS app to your server. Ideally you should do this when the user makes a purchase, but it can be done at anytime. You should store this on the backend with that users info. This is the receipt you need to send when making the validate and verify calls to apple.
I haven't used this library before but the general idea is that you can send this same receipt every time and apple will return you the latest receipt info. You can use the latest receipt info to update/cancel the user subscription.
This is the documentation from apple:
https://developer.apple.com/library/archive/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html#//apple_ref/doc/uid/TP40010573-CH104-SW1
We are trying to use Apple's subscription status url.
We have setup our server to accept the url we provided in the app page and made sure the server is compatible with ATS requirements.
A post test with Postman works. (we see the request and a test json received on our end)
However we are still not receiving any notifications updates from Apple upon renewal (not even initial_buy).
Seen some questions from last year but no valid solution. Does anyone had this problem lately and solved it?
I can't make a comment, and it's hard to see if this is the case here without knowing if you are actually receiving NOTHING at your script, or just receiving no data in $_POST.
If the latter, this should work:
$data = file_get_contents('php://input');
Then you should be able to work with the data by calling json_decode or doing whatever you want with it.
I ran into the same problem. I thought that Apple would call our webhook whenever a new subscription charge is processed (similar to how Paypal, Stripe, Android etc work). But that's a mistake. According to this technical note:
https://developer.apple.com/library/archive/technotes/tn2413/_index.html#//apple_ref/doc/uid/DTS40016228-CH1-SUBSCRIPTIONS-MY_SERVER_PROCESS_RARELY_RECEIVES_RENEWAL_NOTICES_WHEN_THE_AUTO_RENEWING_SUBSCRIPTION_RENEWS_
The App Store attempts to charge the user account 24 hours before an auto-renewing subscription expires. If the renewal is successful, there is no server-to server notification because the auto-renewing subscription did not enter into the expired state.
So Apple will only notify this endpoint when
a new subscription is created (at least that's the case for us, but we have a trial offer)
the subscription status changes from active to expired, or vice-versa.
So you have to keep track of the subscription receipts when the customer signs up. When the subscription is about to expire/has expired, call Apple's receipt validation endpoint to fetch the new receipt. If the receipt says the subscription expired, your webhook should be notified when the user reactivates it.
I am a little confused about the process involved in the validation of receipts from users who have subscribed to my app.
At the minute a user joins and then purchases the subscription, the receipt is then base64 encoded and sent to my server. At midnight each night the server sends off the receipt stored in my db to Apple to be validated and the expiry date updated.
Now i'm a bit confused about how a receipt is updated each month. Please take a look at the following flow and let me know if this is correct.
The user registers and subscribes to my app.( Lets say January).
The original receipt is sent to my server and then validated with Apple, the expiry date is returned and set on my server.
A month later in February on the expiry date I send the original (January) receipt to Apple again to see if the subscription has been renewed and then I can set the new expiry date.
Is this flow correct? Because I am sending the original (January) receipt each month will it still contain the latest renewal information or do I somehow have to refresh the receipt each month when the user logs in or opens the app?
Yes, your understanding is more or less correct. When a user's first renewal occurs a couple of things will happen:
The next time the user launches the app, your SKPaymentQueue delegate will receive a new SKPaymentTransaction for the new transaction. You need to be ready to observe this transaction with your delegate and finish it. If you don't, transactions will just continue to pile up over the months.
The verifyReceipt response received from Apple for the first receipt will update the latest_receipt_info key to include the most update version of the receipt data. latest_receipt_info will originally just be a copy of the receipt.in_app field, but after the first renewal it will contain the most up to date transactions. You should use these latest_receipt_info transactions to update the expiration date.
My suggested behavior is that when you receive the new SKPaymentTransaction you send it to your server anyway (although you technically don't need to) and you use it to verify and update the expiration date before finishing the transaction. You can overwrite the old receipt with the new one.
You can have a look at the RevenueCat iOS framework source code to see how I handle it. (You should also make sure you trigger a fetch receipt request if the receipt data is missing, which I do in the code.)
If you are interested in an out of the box solution, RevenueCat is a service I started to handle all these and many more edge cases automatically.
I want to offer a renewable subscription in my iOS application. The user subscribed and the receipt is stored. Now i wonder how i need to make sure that the receipt is valid and not cancelled:
If the user cancels the subscription and it is not renewed, how would i know it? If the subscription is renewed, when a new receipt will be created?
If the user cancels the subscription through apple support (because, for example, he bought it my mistake), how can i know it? The receipt on the device will be valid. Should i refresh the receipt every time the user logs in?
EDIT:
I forgot to mention it, but the receipt is checked in the client side.
Generally you need to check the expiration date of the subscription. To do that you need to get the receipt list and find the most recent record. It could be done using several ways (iOS Restore in App purchases with receipts)
If user cancels the subscription, I believe it means that receipt list simply will updated and you can find this by reading the 'cancellation date' field. To get track the expiration date I'd recommend to use UILocalNotification. If user continues to use subscription and you doubt whether he prolonged it or not, you should update the receipt list and send request to Apple [[SKPaymentQueue defaultQueue] restoreCompletedTransactions]
If user cancel the subscription through apple support , you can find the corresponding record (aka "Cancellation Date") in the receipt data. Please read (https://developer.apple.com/library/ios/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html).
I'd recommend to check the receipt from time to time or use a notification mechanism.
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.