I am facing an issue with validating user subscription in production environment only, in development environment with sandbox user was and is working fine.
Here is the code snippet where I validate the finished transaction.
#if DEBUG
private let verificationUrl = "https://sandbox.itunes.apple.com/verifyReceipt"
#else
private let verificationUrl = "https://buy.itunes.apple.com/verifyReceipt"
#endif
if let appStoreReceiptURL = Bundle.main.appStoreReceiptURL,
FileManager.default.fileExists(atPath: appStoreReceiptURL.path) {
do {
print("begin")
let receiptData = try Data(contentsOf: appStoreReceiptURL, options: .alwaysMapped)
let receiptString = receiptData.base64EncodedString(options: [])
let requestData = ["receipt-data": receiptString, "password": "########", "exclude-old-transactions": true] as [String: Any]
var request = URLRequest(url: URL(string: verificationUrl)!)
request.httpMethod = "POST"
request.setValue("Application/json", forHTTPHeaderField: "Content-Type")
let httpBody = try? JSONSerialization.data(withJSONObject: requestData, options: [])
request.httpBody = httpBody
URLSession.shared.dataTask(with: request) { data, _, error in
DispatchQueue.main.async {
if data != nil {
if let json = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) {
self.parseReceipt(json as! Dictionary<String, Any>)
return
}
} else {
print("error validating receipt: \(error?.localizedDescription ?? "")")
}
}
}.resume()
// Read receiptData
} catch { print("Couldn't read receipt data with error: " + error.localizedDescription) }
}
The problem is in the first condition
FileManager.default.fileExists(atPath: appStoreReceiptURL.path) {
In development env with sandbox user, it works fine and the file exists, printing the Bundle.main.appStoreReceiptURL?.path
yields: Optional("/private/var/mobile/Containers/Data/Application/BE5EB9FD-3704-488D-96E8-ADB805300ED7/StoreKit/sandboxReceipt")
In both cases! which is strange, I expected that in production env I would not find sandboxReceipt in the url, but something else. but maybe I am wrong
So the issue is that in production, the FileManager.default.fileExists condition fails as file is not found (I made an else and printed this value which was false) which creates the problem that now if an actual user downloaded the app and payed for the subscription, the transaction will succeed and money will be payed but then the app will not verify and the features will not be unlocked - which is terrible!
I tested with my device and with a friend's device in production mode after 48 hours of releasing the app and the problem happened, I immediately removed the app from sale and now I am trying to find the root cause of the issue. Please help.
Note: I know that local validation is not recommended and I will very soon refactor the code to integrate server side validation (once I have the time and money) so please do not reply back mentioning this point as I am already aware of it.
Tech details:
minimum IOS 13.3
Xcode: Version 11.5 (11E608c)
macOS Catalina: 10.15.5 (19F101)