We are implementing server side receipt validation for auto renewable subscription. Now when a user turn off the subscription or when it auto renew there is no notification send from apple server to our server. We want to poll apple server when the subscription is about to expire. So how can we do this?
Is there a way to schedule such polling at specific date ?
First when any in app purchase made you need to store receipt data after validating it. Also you need to store expire date of that particular purchase which you will get by receipt validation.
Now create a crone job in your server to validate auto renew purchase, crone job time interval is up to you as per your project need but let say for example take 1 hours. In the crone job you need to select only those record which expire time with in next 6 hours(You can change this time as per your need). Then again validate this receipt and if purchase get auto renew then you will get list of receipt. You will get always new receipt in the list whenever purchase auto renew. In this you will get new expire time. Suppose you are not getting any new receipt then it means user has cancel subscription
You would need Receipt validation.
If your app offers auto-renewable subscriptions, you can receive server notifications from the App Store about key events by setting up an optional URL that links to your server.
Before sending a notification to your server, the App Store will try to establish a secure network connection with your server by using App Transport Security (ATS) protocols. If a secure connection cannot be established, notifications will not be sent to your server. See Requirements for Connecting Using ATS to learn more about security requirements.
After a secure HTTPS connection has been established, the App Store will deliver JSON objects through an HTTP post to your server for key subscription events. See the In-App Purchase Programming Guide to learn more about the contents of this HTTP post.
Use server notifications together with Receipt Validation to validate a customer's current subscription status and provide them access to content or services from within your app.
For more info : Link
Not get notifications such as cancel as these notifications are only sent when a subscription is canceled by Apple directly.
The renewal notification, "Automatic renewal was successful for an expired subscription. Check Subscription Expiration Date to determine the next renewal date and time." In general, iTunes will attempt to charge the user account a day before an auto-renewing subscription is scheduled to expire. If the renewal is successful, there is no server-to-server notification because the auto-renewing subscription did not enter into an expired state. There is no support at present to simulate this event in the sandbox environment.“
Read more: https://forums.developer.apple.com/message/283579#283579
Related
I generally understand receipt validation on In App Purchases. Most libraries make this as simple as calling a method.
I'm not so clear on how subscriptions work though -- specifically, how can I detect if the subscription is cancelled?
Subscriptions are cancelled on Apple's iTunes interface only. How is my server supposed to know that a subscription was cancelled?
From the Apple docs:
The user can also cancel their subscription by disabling auto-renew and intentionally letting their subscription lapse. This action triggers the App Store to send your server a status update notification of type DID_CHANGE_RENEWAL_STATUS. Your server can parse the auto_renew_status and the auto_renew_status_change_date to determine the current renewal status of the subscription.
https://developer.apple.com/documentation/storekit/in-app_purchase/subscriptions_and_offers/handling_subscriptions_billing#3221914
The answer from Jacob is correct for the case that the user disables the auto-renewal of his subscription. If the user requested a refund from Apple and they cancel the subscription for him. Your server will receive a CANCEL notification and the receipt will contain a cancellation_date field.
You need to handle both of those cases, because when the user cancels (deactives the auto-renewal) his subscription, it is still valid (till it expires). When Apple customer support cancels the subscription, then it is from this point on invalid.
Note: the CANCEL notification is also triggered when a user up- or downgrades to a different subscription of the same subscription group. See this answer for more details on that.
We have a problem with Apple subscription callback on Sandbox environment. When I purchase an auto-renewable subscription on Sandbox env, apple sends first callback only after 1-2 min. It's ok. But when the first expiration period ends apple not always notify us about extending a subscription. But we should receive notification_type = RENEWAL always at the end of the expiration period. Sometimes we receive notifications sometimes we don't. Do you know how can we check where is the problem? Maybe Apple has some troubles because we couldn't find any problems on our side.
RENEWAL events are sent when a subscription has expired, then later, the user starts the subscription again.
See: Apple Subscription Notifications are Almost Useless
We have setup Apple’s Server notifications for auto-renewable subscriptions. Last month we still able to get all notification type(INITIAL_BUY, RENEWAL, INTERACTIVE_RENEWAL).
Recently when we tested with sandbox (1 year subscription), we receive only 'INITIAL_BUY' server notifications, we were expect to receive 'RENEWAL' server notifications after 1 hour, but we are not getting those notifications.
Question:
I just want to confirm that is it a new notifications service that only send us 'INITIAL_BUY' notifications? And there are no server-to server notification if the renewal is successful?
Note:**
We did validate receipt with verifyReceipt server to check latest_receipt_info.
Correct. 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.
You have to actively call Apple's receipt validation endpoint on or around the expiration date of each receipt (and possible for a few days after that) to fetch the renewal receipts. Apple will not notify your servers.
I would like to implement In-App purchase of consumable products for an iOS app I'm developing. I want to validate the receipt on the server side as indicated in the documentation:
App start transaction asking to the Apple Store
Apple Store return receipt to the app
The app send the receipt to a trusted server
Trusted server sends receipt (in base 64 format) to the Apple Store through an HTTP POST
Apple Store replies to the HTTP POST with the validation
If the validation response is ok, the purchase can be enabled
I'm concerning about the following situation: a user buys a product and the Apple Store sends back the receipt to the App (steps 1,2). Then, when the app tries to send the receipt to the trusted server (step 3) the connection goes down. In this case receipt validation has to be retried in a second moment, however, I have the following questions:
a) in this case, has the user already paid for the product?
b) Since receipts for consumable products compare only at the time of the purchase, how should the validation retry be managed? Should I save the receipt locally in order to retransmit it in the future?
Can I simply does not mark the transaction as "finished"? From what I understand reading the documentation, in this case StoreKit should call the transaction queue observer again (passing again the receipt?) until the transaction is marked as "finished", is it correct?
Thank you in advance
a) in this case, has the user already paid for the product?
The PaymentTransaction observer will tell you what state the user's purchase is .Purchased, .Purchasing, .Failed . e.t.c.
So we can assume from your question that the user's state is .Purchased and You would have received a payment.
Now since they have a receipt and it’s hopefully from a real purchase they will be waiting for you to validate on your server and unlock the purchase because they have received a receipt containing data about their purchase.
b) Since receipts for consumable products compare only at the time of the purchase, how should the validation retry be managed? Should I save the receipt locally in order to retransmit it in the future? Can I simply does not mark the transaction as "finished"? From what I understand reading the documentation, in this case StoreKit should call the transaction queue observer again (passing again the receipt?) until the transaction is marked as "finished", is it correct?
You don’t need to store it locally, with the information stored about the purchase in the receipt. This is kept until your paymentObserver finishes the transaction or the receipt is refreshed/ updated again.
Your app will keep trying to validate with your server until it receives a response about the receipt usually when the user launches the app again,
At that point if we assume it's valid, you enable your product and then after this finish the transaction on the SKPaymentQueue.
In the documentation it says’s
“The in-app purchase receipt for a consumable product is added to the receipt when the purchase is made. It is kept in the receipt until your app finishes that transaction. After that point, it is removed from the receipt the next time the receipt is updated “
https://developer.apple.com/library/archive/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html#//apple_ref/doc/uid/TP40010573-CH106-SW1
Also:
“For example, consider the case of a user buying something in your app right before going into a tunnel. Your app isn’t able to deliver the purchased content because there’s no network connection. The next time your app is launched, StoreKit calls your transaction queue observer again and delivers the purchased content at that time. Similarly, if your app fails to mark a transaction as finished, StoreKit calls the observer every time your app is launched until the transaction is properly finished.”
I hope this helps and I hope it answered your questions.
I created an API to be called by Apple webhook to work with subscription. I've set the API url in Itunes to be called by the webhook.
According to Apple help site https://help.apple.com/app-store-connect/#/dev7e89e149d in regards to the Testing Auto-Renewable Subscription, when testing auto renewable subscriptions in the test environment, the Apple webhook will make a call to the API after 5 minutes if I select 1 month subscription duration.
But the thing is, after making first purchase, apple webhook doesn't follow up call to the API that I created to renew the subs. Even after I waited for more than 5 minutes. So I can't do any processing from the API to renew user subs in the database.
Is there some configuration that I had to make in order to test the auto renew and make apple webhook call the API to renew the sub?
We've found that Apple's subscription update webook calls are rather unreliable.
Based on experience:
Don't count on Apple to notify you of renewals. The notification may arrive arbitrarily late (often leaving a "gap" in time), or not at all. We've resorted to retaining and retrying the original iTunes-provided receipt to revalidate renewals at the end of subscription periods --the expiration dates will change to account for the renewal.
Don't count on Apple to notify you of cancellations, either. Same as above, calculate subscription duration, and retry receipts at the end of a period (the expiration date will NOT be updated if the subscription is cancelled).
Generally, this involves mapping the additional transactions/in_apps that are returned with the retried receipt to the original_transaction_id --and updating the expires_at accordingly on your end.
Hope this helps!
Update: In WWDC2020 Apple announced that they add a new notification type called DID_RENEW which will be sent after any successful auto-renew. More info on that in this video, starting at around 16:00.
Original answer:
I can't find the page you linked to, however this page may shed light on the subject (emphasis by me):
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. However, in the few cases that iTunes is unable to renew the subscription (generally there was a connection problem with the credit card server) and the auto-renewing subscription is not renewed before the expiration_date passes, the auto-renewing subscription is technically considered expired. iTunes may continue to attempt to renew the subscription. If iTunes is successful, then the RENEWAL event is sent.
Meaning, you're not supposed to receive notifications for renewals, but only for cases where the subscription became expired and only then renewed. This might be the case for sandbox renewals as well.