bizz84 / SwiftyStoreKit

Lightweight In App Purchases Swift framework for iOS 8.0+, tvOS 9.0+ and macOS 10.10+ ⛺
MIT License
6.57k stars 796 forks source link

Detect user already purchased the app(itself) #246

Closed Davtyanag closed 7 years ago

Davtyanag commented 7 years ago

Platform

Environment

Issue summary

I'm moving my app from paid applications to free with IAP. I would like to know if it's possible to detect if user bought an app before becoming free or not. Can I do that via SwiftyStoreKit? If so how can I test that?

apptekstudios commented 7 years ago

This solution has nothing to do with SwiftyStoreKit but the simplest way to do this, in my opinion, would be to: Release a version well-ahead of time (so people don't skip it) while the app is still paid that would set a value in iCloud keychain that says they had the app before it became free. You could then check for this value in future versions, and if set, act as though they've purchased the IAP.

Davtyanag commented 7 years ago

Thank you @whitepixelstudios for the answer. There is a solution via validating Appstore receipt and fetching original application version and comparing that to new app version. I did that via using and modifying another library, looks like SwiftyStoreKit doesn't support that.

robertodias180 commented 7 years ago

@Davtyanag what lib did you use? I am faced with the same issue.

Thanks

Davtyanag commented 7 years ago

@robertodias180 https://github.com/crashoverride777/SwiftyReceiptValidator

robertodias180 commented 7 years ago

@Davtyanag thanks for the info 👍 Also can you share the changes that you had to make?

Davtyanag commented 7 years ago

@robertodias180 https://github.com/Davtyanag/SwiftyReceiptValidator The library didn't have error callback. That's how I use changed library(fork), and the code on the bottom shows how I use it, "some text" in arguments doesn't matter, I don't use it.

SwiftyReceiptValidator.validate(forIdentifier: "some text", sharedSecret: nil) { (success, response,error) in
            if success {
                // example 2 (auto-renewable subscriptions)
                let receiptInfoFieldKey = SwiftyReceiptValidator.ResponseKey.receipt.rawValue
                if let receipt = response?[receiptInfoFieldKey]{
                    if let applicationVersion = receipt[SwiftyReceiptValidator.InfoKey.original_application_version.rawValue] as? String {
                        if applicationVersion <= "1.2" {
                            let alert = self.alertWithTitle("Purchases are restored".localized, message: "All purchases have been restored".localized)
                            self.showAlert(alert)
                            self.successfullyPurchased()
                            self.hideLoadingHUD()
                            NetworkActivityIndicatorManager.networkOperationFinished()
                            return
                        }
                    }
                }
                self.restoreAction()
            } else {
                if !(error?.domain == "SSErrorDomain" && error?.code == 16) {
                    self.restoreAction()
                } else {
                    self.hideLoadingHUD()
                    NetworkActivityIndicatorManager.networkOperationFinished()
                }
            }
        }
robertodias180 commented 7 years ago

@Davtyanag thanks 😃

Davtyanag commented 7 years ago

@robertodias180 finally formatted comment, u r welcome

ghost commented 6 years ago

@Davtyanag @robertodias180 Hi! Thanks for your code, but how can you check it on dev? I actually bought the app, then install new version from xcode over the AppStore version, but i have "Error Domain=SSErrorDomain Code=100" here

func request(_ request: SKRequest, didFailWithError error: Error) {

        print(error.localizedDescription)

        handler?(nil, error as NSError)

   }

How did you test it?

ghost commented 6 years ago

Well, it seems to me that there is no legal way to check it on development. Testflight / sandbox both always return the original_application_version = 1.0, its impossible to receive non fake receipt.

augie09 commented 5 years ago

Doesn't original_application_version return the build number? so its unlikely to look like the sandbox value of "1.0" and more likely to be something like 17. I think most build servers just increment the build number.

Also, checks like this if applicationVersion <= "1.2" would return true if applicationVersion = 1.10 even though 1.10 is > 1.2 semantically.

KyryloKuzyk commented 5 years ago

I tested only local receipt validation, and original_application_version contains only build number (one number), not a full version.

I will try to validate receipt via apple server. Maybe this way I will be able to retrieve full version (like 1.x.x.x)