Upcoming changes to the App Store receipt signing certificate - in-app-purchase

I have recently got this news to the apple developer news channel,
https://developer.apple.com/news/?id=ytb7qj0x
So I want to know that will this affect my implementation to check the status of user purchase status.
I am currently using SwiftyStoreKit for IAP, and using this function to verify receipt, so that I can check the user's purchase status,
SwiftyStoreKit.verifyReceipt(using: AppleReceiptValidator)
Response on this will be very helpful to me.

Related

Check to see if user actually payed for in-app purchase [iOS, Swift]

Here is a strange one for you :)
I have an iOS app that has a non-consumable product as a in-app purchase that the users could buy. It's kind of a lifetime subscription if you'd like.
The thing is that i had a bug in my code which allowed users to "subscribe" to my app by tapping on Restore Purchases button.
I fixed the bug now but i have a problem. Roughly 50 users are now subscribed but never payed for this service.
Is there a way to see if the user actually payed for this somehow? I would like to unsubscribe them if they did not pay.
The system works this way:
The user taps on Purchase, Apple takes care of the purchase for me and when processing the payment queue, if the purchase was a success i subscribe the user by adding their iCloud ID to my database. So the only piece of data that i have is their iCloud id and nothing else. I don't know which iCloud ID is a "payed" one and which is "cheating" :)
You can obtain the receipt from the user's device and check with Apple's endpoint to see if the user has a valid purchase. Ideally you should take the receipt from the app and send it to your server to perform the verification in your backend.
Check this documentation to obtain receipt from the device - https://developer.apple.com/documentation/storekit/in-app_purchase/validating_receipts_with_the_app_store
Check this documentation to call verify the receipt with Apple's endpoint - https://developer.apple.com/documentation/appstorereceipts/verifyreceipt

Determining status of itunes subscription from webserver

I have some subscription-based content that should be accessible to the user from their iOS app and from the website as well. My understanding of in-app purchases (IAP) on iOS is that I have to set up some "products" in the App Store that the user then "subscribes to" from the app. Apple provides functionality (detailed here and here) on how to check subscription status from within the app in this case.
My question is :
What if i want to allow the user to access their subscription on the website ?
Is there a way to check the status of an IAP subscription in the App Store to see whether it is active or not from my web server ?
It's not clear from Apple's documentation whether this is the case.
Validating Receipts With the App Store
This is the documentation from apple on how to validate a receipt with iTunes. This does not necessarily have to be done from iOS. Once you send the receipt data to your web service you can make the same call directly to iTunes from there as well.
So to answer you questions:
1- Once you validate the receipt with iTunes from web, you can upgrade the user account to have a subscription.
2- You can validate the receipt data with iTunes whenever you like, in the response from iTunes one of the fields is the latest user receipt. This will allow you to check if the user still has an active subscription or not.

iTunes cross-platform IAP subscriptions - how does Netflix do it?

I'm creating a service which allows users to register on any number of devices (web, Android, Roku, iOS, Apple TV), and then purchase a monthly subscription to watch video content. The subscription provides access to the entire catalog. I have my own subscription management API running on a server which I'd like to leverage as the source of truth so users can purchase a subscription on their iPad, login to the app on Roku, and continue watching where they left off.
Basically, Netflix.
Here are my options as far as I can tell:
Auto-renewing subscriptions: this is what Netflix uses today, but Apple doesn't provide an API or any set of webhooks around their payment platform, so I don't know how this option could work. My back-end service will have no idea when Apple automatically renews the subscription each month or if a user cancels their subscriptions.
Non-renewing subscriptions: users purchase the subscription inside
the app though IAP. Once purchase is complete, the app sync’s the
subscription to my back-end system. The app interfaces with my
back-end any time an entitlement check is required. When a user’s
subscription is about to expire, the app must present purchase
workflow again.
Import iTunes reports: won't work because it's not realtime (pull, not push) and doesn't tell me anything about cancelled subscriptions. I can only generate reports of new subscribers.
Receipt validation & push receipts to my service: won't work because it depends on the user actually using my app. Users could theoretically subscribe in my app, switch to Roku, and never open it again.
Skip IAP altogether and require users to subscribe via web.
Am I missing something? I'm really curious how Netflix is pulling this off.
For the initial subscription purchase:
User initiates a purchase on the iDevice
Device contacts Apple, Apple issues a receipt and sends it back to the device
The device sends the receipt to my server
The server validates that the receipt is legit through Apple's receipt validation API
Once the receipt is validated, the server stores it in my DB
The server responds to the app saying it's all good
To keep the server in sync with the iTunes subscription:
Setup a cron job to retrieve expiring receipts from the DB on a daily basis or something
Validate each receipt with Apple
Apple will respond with an updated version of the receipt that contains details regarding whether or not the subscription was canceled/renewed/etc.
Server replaces the original receipt with this updated version in the DB
Now if someone logs into their account on a Roku or some other device, the subscription can be honored because my DB is the source of truth.
I know this is old, but Apple recently introduced Status Update Notifactions which accomplishes what the OP asked for via webhooks:
Configure Apple to send notifications to your specified endpoint. (Apple's small guide)
Handle the JSON object that's sent via HTTP POST from the App Store and validate latest receipt.
Update/save data to your database.
Respond with a 200 status code to report a success.
You'll be able to handle the following notification types: INITIAL_BUY, CANCEL, RENEWAL, INTERACTIVE_RENEWAL, DID_CHANGE_RENEWAL_PREFERENCE
The documentation in the link above explains implementation and types in more detail.

How do I know if a user cancels an auto renewing subscription with In-App Purchases on iOS?

I have been testing out Apple's In-App Purchases (sandbox mode) which is great for testing what happens when a user subscribes, but how do I tell if the user is still paying? How do I know if the subscription has been canceled? Apple doesn't appear to let me test that out?
I see that there is something about verifying receipts? How can I do this?
When you subscribe a auto-renewable subscription from app, you will get a receipt. Send that receipt to your server and your sever can use that receipt to verify if your purchase is valid from iTune store (check their doc)
You will get a JSON response and some field inside can show you the expired date.
As to user's cancel, sorry, you cannot know that until current period expire (actually you will know that 24 hours before expiration due to apple store's mechanism)
Hope this helps.
[Updated # 2017/11/5]
Now Auto-renewable subscription is allowed to notify your sever when new period begins. Please check latest document.

How does Apple notify iOS apps of refunds of in-app purchases (IAP)?

I have Apple iOS IAP successfully implemented in my app and tested in the sandbox. Works great.
I'm concerned that users could buy something with IAP, download it into my app, then complain to Apple and get a refund. There's no obvious way that refunds are reported to my app. Are they simply left out of the list of products I receive during a "restore" operation? Is there some undocumented transaction type that will asynchronously show up in my SKPaymentTransactionObserver when a refund occurs?
Right now I'm operating on the assumption that I need to delete the user's IAP transactions before doing a restore, and that anything refunded will just not be in the list of restored transactions. Is this the right way to do it? Is there any way to test this in the sandbox?
Has anyone seen refunds in a production environment and can explain how they work?
Update June 24, 2020:
At WWDC 2020, a new notification was introduced that informs you of refunds: https://developer.apple.com/documentation/storekit/in-app_purchase/handling_refund_notifications
Original answer:
I received a response from Apple Developer Relations today (Dec 6, 2018):
Hello Johannes,
In response to your question, unfortunately, there is no supported means to detect that the user has contacted Apple Care and received a refund for the In-App Purchase of a consumable item. The only option which I can refer you to is to submit an API enhancement request for an API to be made available for an app to detect that a refund was provided to a user of an In-App Purchase. Currently, this support is realistically only available to apps which offer auto-renewable subscription In-App Purchase.
You can submit the enhancement request using the Apple Developer Bug Report web page - http//bugreport.apple.com
As this is an enhancement request type issue, I'm going to arrange for this incident to be unbilled from your account for use on a future issue.
So there we have it.
The in-app purchasing guide discusses the concept of "cancellation" of subscriptions. This is the only place I've seen discussing the subject.
Further details about the cancellation date field can also be found in the App Store receipt validation documentation.
cancellation_date
After decoding a receipt, you can get the cancellation date which will tell you the following:
For a transaction that was canceled by Apple customer support, the time and date of the cancellation.
The strategy is:
You save the latest_receipt ("MIIUJgYJKoZIhvc..." base64) field in your DB, associated with the user account.
Every day you query apple to validate all the receipts, by sending them the base64 receipt from saved latest_receipt field.
In the receipt you check if there is a cancellation_date field. If you find it, treat it according to documentation:
Treat a canceled receipt the same as if no purchase had ever been made.
Same way you also checking subscription renewals (check expires_date_ms field).
Refunds are given, but your app gets no notification of them at all. Whether it's an In-App Purchase, an app download or any other iTunes content, the user can still use the content even if they have asked for a refund.
In iOS 14 a new method is added to the SKPaymentTransactionObserver protocol that is called when the user is no longer entitled to one or more in-app purchases 👉 https://developer.apple.com/documentation/storekit/skpaymenttransactionobserver/3564804-paymentqueue
Although the documentation doesn’t tell in which situation this method is called, Apple does tell this in this WWDC2020 video at 26:55 👉 https://developer.apple.com/videos/play/wwdc2020/10661/
According to latest documentation, server to server notification with type CANCEL is now handling cancel scenario by Apple customer support.
Starting October 21, 2021, App Store Server Notification Version 2 became available and the notificationType in the notification payload will be returned with REFUND when the App Store refund process is completed.
See below for more information.
https://developer.apple.com/documentation/appstoreservernotifications/app_store_server_notifications_v2

Resources