Refund the previously purchased non-renewing subscription, not the current one. Possible? - ios

I'm implementing an iOS app with non-renewing subscription. Not much relevant information was available online; so I seek your guidance.
A use case which worries me the most is when a user purchased the subscription once and then immediately after purchase it again to extend the duration of service (see such scenario here). What if that user were to refund the first purchase, leaving the second one intact? Is this even possible in practice, or am I just too paranoid?
Assuming the above case is possible, my app will run into a problem because, as far as I know, verifyReceipt only returns the latest, good receipt (watch Managing Subscriptions with In-App Purchase in WWDC'12).
I find nowhere Apple provides relevant information about refunding policies.
(Auto-renewable subscription seems to rule out this case as a renewing action is taken care by iTunes automagically and it seems not possible to extend this type of subscription until iTunes allows it.)

verifyReceipt will not only return the latest good receipt, it will also tell you if the receipt you submitted for verification is good. So if you're concerned that a user may have cancelled* a transaction, then submit every receipt you're questioning.
*But what do you mean by "cancel" the first purchase? Do you mean when they tap "cancel" instead of "buy?" Well then the transaction won't go through and you won't even get a receipt.
Or do you mean when they request a refund? I don't know any other way they can cancel a purchase.
Edit:
If you're referring to refunds, there's no way for a developer to tell if a user has been issued a refund. The assumption is that Apple expects you to continue to deliver services to that user regardless of the fact that they received a refund. Your receipts will probably all verify correctly regardless of the status of a refund.

Related

In-App Purchase Refund

I am wondering whether to implement in-app purchase refunds (in case a user refunds). None of the in-app purchase tutorials seem to show how to do it, so I am wondering if that is for a particular reason.
By the way, the in-app purchase is a non-consumable (PRO version).
A big problem I can see with refunds for example, is that you shouldn't remove the PRO features if they don't have connection, but then someone can just use no connection with the app to never get PRO revoke.
My question is: Is there a seamless way to integrate refunds for non-consumables, and do many other apps handle refunds or not?
Thanks.
I believe the only way for a user to get a refund is to request it from Apple. If granted, the onus is on you to determine this condition. You will have to check receipts actively.
https://developer.apple.com/library/archive/technotes/tn2413/_index.html#//apple_ref/doc/uid/DTS40016228-CH1-RECEIPT-HOW_DO_I_USE_THE_CANCELLATION_DATE_FIELD_
This states:
The Cancellation Date (cancellation_date) field is designed for use
with auto-renewable subscription, non-consumable and non-renewing
subscription products. This field is set when a customer contacts
Apple customer support for a refund and the transaction is canceled.
Depending on if your app has a backend or not will dictate a strategy to handle this. If you have a backend, a good method is to periodically check for receipt status (at some time interval of your liking). Note that if you have a large user base, you probably want to divide up the user pool piecewise to do this type of check.
If you don't have this as your option, then you need to make your app make this check.
Or ... you accept that this will happen. I've done work for a company that had a large subscription base and they never ran that check for cancellation/refund (I let them know about that weakness in the system).

Detect if a user refunded a 'consumable' in app purchase item (Apple app store in app purchase system)

I read so far online that the only way to detect if a user cancelled an in app purchase is by using the receipt data that I get from the user's iPhone and check if the cancellation_date exists in there for that item, but as far as I know, this field is only to be found on auto-renewable subscription items.
(At least to what I read online on every post I found that talks about in app purchase, no mention to consumables at all.)
Because they are always stored in the receipt data, while consumable items, are stored in the receipt data until the app itself finishes the transaction, once thats done, the purchase transaction for that item is gone forever from the receipt data after the finish process on the iPhone.
So my question is, if a user requested to cancel an in app purchase from Apple, which is a consumable item, do I also get back that same item transaction in the receipt data WITH the cancellation_date field in it?
I've never seen anyone confirm this.
It would be nice if someone can provide a receipt-data base64 string with cancellation_date example in it (if that's legal to do tho).
https://developer.apple.com/documentation/storekit/in-app_purchase/handling_refund_notifications
Apple has provided a solution finally in 2020!!
A year ago I had the same question as you and I have found this thread where author said that Apple has not added a way to detect canceled purchases. I'm still living with that as it is.
The best way to know it is contacting Apple technical support, each account has 2 request/year, so I recommend you to write there.
Hope you will find the answer and tell us about the result.

Is it necessary to validate / refresh an app store receipt on launch in iOS?

The Apple docs on receipt validation say to perform receipt validation immediately after launch. This amounts to checking for data at the path returned by [[NSBundle mainBundle] appStoreRecieptURL], refreshing via SKReceiptRefreshRequest if it's not there, and validating it. The aforelinked docs reference both iOS and macOS.
Is it actually necessary on iOS? If so, why? Is it to prevent users from using my app on a jailbroken device, or without having bought it from the app store (in which case I probably don't care if my app is free)? Or does it have implications for other operations like restoring or validating in-app purchases? For example, does the receipt data have to be there already in order to validate a transaction for an in-app purchase?
Note: I am not using in-app subscriptions. I have in-app purchases, but I don't use the receipts from them after verifying them and recording the purchase server-side.
you don't need to do so, that is optional only and could be done on iOS7+, if you interested in doing that.
briefly, implementing the validation is purely a financial decision, and even if you validate recipes you are recommended not to disable the content in case of failure as the validation could fail in standard environment as well anytime (e.g. in case of no connection), and such overreaction may ruin your consumers' experience.
altogether, doing the validation'd rather make sense on OSX in practice when you are allowed to disable the content in case of failure, regardless the reason; but if you feel you have more consumers than your income suggests or the amount of the stolen content is way beyond your margin, it may be worth to do it on iOS as well.
NOTE: in general you can read more about the technical details of receipt validation in Apple's Documentation.
The simple answer to your question is NO, It is not necessary.
Here is the detailed explanation for you.
According to Apple Documentation here, apple has given two methods of validating the receipts, they are given it as guidance only to prevent unauthorized copies of your application from running. For more guidance apple has pointed towards the apple review guidelines.
In the review guidelines here, Apple does not mention anything related to the verification of receipts as mandatory.
If at all the receipt validation is mandatory, Apple would have provided a simple API to validate it.
Titbit: You can see a lot of rejections when it comes to app store receipt validations. But all those issues are because the receipt validation is not done properly.
But my personal recommendations will differ from the above answer. First thing for you to consider is "Never underestimate hackers". Validate the receipts several times apart from the start of the app. Read this article for more information.
You would generally only validate the receipt to prevent piracy by users who haven't bought your app or if you are using auto renewing subscriptions.
Whilst you can interrogate the receipt for IAP information, its actually easier (and required by app review) to give a button somewhere to "restore previous purchases" and call
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
It is also a better UX for the user to possibly be prompted for their Apple ID and password having pressed a "restore purchases" button rather than unexplained at app startup.
The reasons I would give are:
The user can change their product if you are using subscription groups from outside of your app.
An auto-renewing subscription can renew outside of your app.
The app does not receive transactions initiated outside of the app until the app restarts.
The user can make purchases on another device using the same appleID whilst outside of your app on the current device.
Within our appDelegate:application didFinishLaunchingWithOptions we initialise a class that calls
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
to monitor for purchases initiated from within the app.
It's not necessary, but beneficial for the following reasons:
You'll always get the definite set of purchased products and not require the user to manually restore the products.
You have (limited) fraud protection, especially if you combine local and remote validation.
It's way more simple to compute the expiration date for automatically renewing subscriptions using the recipe.

How to track In-App Refund in ios app [duplicate]

Situation:
- User makes an IAP and is awarded some content, we store the users device id to ensure they can access this content whenever they want.
- User decided they do not like the content, so they call Apple and get a refund.
- User can still access the content, even though they have been refunded for their IAP
Problem:
We don't want the user to be able to access this content anymore. This could become a loophole that they would take advantage of. (unlock content, then get refunded and keep their access to said content)
Question:
Is there any way for us to check if a user has been refunded for an IAP with either their transactionId, transactionReceipt, or any other information we may have?
For Reference, I've read the StoreKitGuide, it did not mention this case.
No. There is no way to revoke access to content if they have been refunded. I believe this is by design. It is the same with App Store refunds; if someone buys an app and then asks Apple for a refund, Apple does not stop the user from continuing to use the app.
No. you cannot stop user to access. Apple does not stop user to use that feature after refund
Below a recent answer from the overbearing Apple!!!
At April 11
Hello Joe,
Thanks for your quick reply at first.
I think there were some misunderstandings. We understand that you must protect the user information. And we do not require any user info. We do not require any user's information---- iTunes account, User Name, email address and other information about himself/herself.
We require only one data----- transaction id (named "transactionIdentify" in your code), for example "1000000033409668" (this transaction id is a record at March 13).
A user buys a product from IAP, you will generate a "transaction id" and send it to us. This transaction id is stored in our database then. Now he/she gets refunds from you, so please send the transaction id to us. Let us know which one in the game canceled the IAP.
When a refund occurs, we think you should provide the transaction id to us. With these data, we could make a more fair service for all players. If you do not do it, more and more players will use your refund mechanism to get game items without real payment. You and we will lose money then. We think it is very important.
Regards,
Baibo
At April 12
Hello Baibo,
Thank you for following up with me regarding the refund transaction data.
We will not be able to provide you with the refund transaction data you have requested as it is not a feature or benefit provided to you per the contracts you have agreed to.
To view your paid applications contract and review your membership benefits, please access the contracts, tax and banking module within iTunes Connect:
http://itunesconnect.apple.com
If you are not happy with large refunds, you may want to consider adjusting the price of your in-app purchases as we will not be able to provide you with the refund transaction data in the future.
According to an answer one of my users received from Apple, refunding an app means they will no longer receive updates to the app, but doesn't remove the app from the device. IAP appears to work the same.
I am wondering if there is not a way by using restoreCompletedTransactions to check for the iAP purchase, but this would pop up a request for the user's iTunes password, so its use is limited.

Delivery of auto-renewing subscriptions for iOS

I am finding that the renewal of an expired auto-renewing subscription is never being delivered while the application is active and running, but rather when the application is woken up from background or on launch.
In other words if you are using the app, and the subscription expires, it won't be delivered to the app (assuming it is auto-renewing and valid etc) while the user continues to use the app.
This behaviour does not seem to be documented by Apple, can anyone else with experience of this confirm or otherwise?
Obviously one can detect that the sub has expired and then offer the user the chance to check their subscription status and restoreCompletedTransactions which will pull in the new subscription - but I'm just wondering if we're doing something wrong, or if this behaviour is normal.
Thanks.
Yes. That's what I experienced as well.
Before I continue, please see the following posts on why you might want to stay away from auto-renewing subscriptions:
Marco Arment's piece on The limited world of auto-renewable subscriptions, and
The Comments on this SO Question: Auto-renewing subscription – Differences to non-renewing subscription
When your app becomes active, that does seem to trigger the App Store to send any new auto-renewing subscription receipts to your app. But you shouldn't rely on that. And, you don't have to restoreCompletedTransactions to get the latest receipts.
You can see another one of my answers for more detail on this subject.
What you should be doing (based on Apple's documentation and some experimentation) is storing receipts on your server. Then when you want to check if a person's subscription has been auto-renewed, follow Apples procedure for verifying one of those receipts with iTunes. Apple will respond with info about that receipt as well as the latest receipt in that subscription. If it's different than the one you sent, then you know an auto-renewal has occured.

Resources