I have created an app which has auto-renewable subscriptions.
The following is the logic that I use to know if the user has an active subscription.
paymentQueue(_:updatedTransactions:)
of SKPaymentQueue
is called, I try to perform receipt validation using following stepsSKReceiptRefreshRequest
to refresh the receipt.verifyReceipt
endpoint of the App Store server.The App Store review has rejected my app multiple times because the SKReceiptRefreshRequest
errors out. I am unable to reproduce the error faced by the App Store review board.
While searching the internet to solve the problem, I got to know the following facts about the local receipt-
From the above 2 pieces of information, I deduce that there is no need to ever call SKReceiptRefreshRequest
in production because the App Store server will provide the latest details even if the local receipt is old and the local receipt is always present in production.
In order to get my app through the App Store review, I have decided to remove the SKReceiptRefreshRequest
as it gives errors in the Testflight builds and is not required in the production.
Can anyone confirm if I am correct to do this?
Your logic has multiple flaws:
1) paymentQueue(_:updatedTransactions:)
is called in the background and (as far as I know) updates already the local receipt. Also an app downloaded from the App Store always contains the receipt. So there is no need to call SKReceiptRefreshRequest
in that method.
2) SKReceiptRefreshRequest
requires the users to input his password to allow the receipt refresh. Since you triggered the method within paymentQueue(_:updatedTransactions:)
, which was called in the background, I reckon this is the problem why the refresh request failed and Apple rejected your app. Nevertheless this method has its reason for being: in production you need it to allow users to restore purchases after reinstalling the app or on other devices and for debug and TestFlight builds you need it to get the latest receipt.
3) You shouldn't send the receipt from your app to Apple's endpoint
Warning
Do not call the App Store server verifyReceipt endpoint from your app. You can't build a trusted connection between a user’s device and the App Store directly, because you don’t control either end of that connection, which makes it susceptible to a man-in-the-middle attack.
How to proceed?
I would recommend to do the following things:
1) Do not trigger SKReceiptRefreshRequest
in paymentQueue(_:updatedTransactions:)
2) If not already done provide a "restore purchases" button in your app (which calls SKReceiptRefreshRequest
)
3) Implement local or server-to-server receipt validation