Jason
Jason

Reputation: 21

Check If a user has already purchased a product in SwiftyStoreKit

I implemented in-app Purchases and I am using SwiftyStoreKit. Everything works fine but want to check if the user has already purchased the product. I want when the user goes in the inappropriate page to show a button. If its bought then to shows "Open" if not "theprice". I can't quite understand how I can achieve that.

The viewDidLoad() :


let inAppPurchaseId = "iD"
    let sharedSecret = "shared secret"

override func viewDidLoad() {
        super.viewDidLoad()

        SwiftyStoreKit.retrieveProductsInfo([inAppPurchaseId]) { result in
            if let product = result.retrievedProducts.first {
                let priceString = product.localizedPrice!
                print("Product: \(product.localizedDescription), price: \(priceString)")
                self.buyBtn.setTitle("Buy guides for "+"\(priceString)", for: .normal)


                self.verifyPurchase(with: self.inAppPurchaseId, sharedSecret: self.sharedSecret)

            }
            else if let invalidProductId = result.invalidProductIDs.first {
                print("Invalid product identifier: \(invalidProductId)")
            }
            else {
                print("Error: \(String(describing: result.error))")
            }
        }

    }

Here is the receipt verification and thee purchaseProduct function.

func purchaseProduct(with id: String) {
        SwiftyStoreKit.retrieveProductsInfo([id]) { result in
            if let product = result.retrievedProducts.first {
                SwiftyStoreKit.purchaseProduct(product, quantity: 1, atomically: true) { result in
                    switch result {
                    case .success(let product):
                        // fetch content from your server, then:
                        if product.needsFinishTransaction {
                            SwiftyStoreKit.finishTransaction(product.transaction)
                        }
                        self.buyBtn.setTitle("Open", for: .normal)
                        print("Purchase Success: \(product.productId)")
                    case .error(let error):
                        switch error.code {
                        case .unknown: print("Unknown error. Please contact support")
                        case .clientInvalid: print("Not allowed to make the payment")
                        case .paymentCancelled: break
                        case .paymentInvalid: print("The purchase identifier was invalid")
                        case .paymentNotAllowed: print("The device is not allowed to make the payment")
                        case .storeProductNotAvailable: print("The product is not available in the current storefront")
                        case .cloudServicePermissionDenied: print("Access to cloud service information is not allowed")
                        case .cloudServiceNetworkConnectionFailed: print("Could not connect to the network")
                        case .cloudServiceRevoked: print("User has revoked permission to use this cloud service")
                        default: print((error as NSError).localizedDescription)
                        }
                    }
                }
            }
        }
    }

    func verifyPurchase(with id: String, sharedSecret: String) {
        let appleValidator = AppleReceiptValidator(service: .production, sharedSecret: sharedSecret)
        SwiftyStoreKit.verifyReceipt(using: appleValidator) { result in
            switch result {
            case .success(let receipt):
                let productId = id
                // Verify the purchase of Consumable or NonConsumable
                let purchaseResult = SwiftyStoreKit.verifyPurchase(
                    productId: productId,
                    inReceipt: receipt)

                switch purchaseResult {
                case .purchased(let receiptItem):
                    print("\(productId) is purchased: \(receiptItem)")
                case .notPurchased:
                    self.purchaseProduct(with: self.inAppPurchaseId)
                    print("The user has never purchased \(productId)")
                }
            case .error(let error):
                print("Receipt verification failed: \(error)")
            }
        }
    }

I want check when the view loads what title the button should have and if the product has been bought.

Upvotes: 2

Views: 2632

Answers (1)

zdravko zdravkin
zdravko zdravkin

Reputation: 2386

You need to save that the product is purchased or not. Example UserDefaults (not encrypted) but you can use KeychainWrapper. Try with UserDefaults.standard.bool first instead of KeychainWrapper.

For the price/open Button use fullPurchase and change the title and logic.

You have 2 cases:

  1. case .purchased(let receiptItem):

  2. case .notPurchased:

    var fullPurchase: Bool? { get { if let fullPurchasedFromKeychain = KeychainWrapper.standard.bool(forKey: FullAccessOlder) { return fullPurchasedFromKeychain } } return false } set { KeychainWrapper.standard.set(newValue!, forKey: FullAccessOlder) }

    func verifyPurchase(with id: String, sharedSecret: String) {
            let appleValidator = AppleReceiptValidator(service: .production, sharedSecret: sharedSecret)
            SwiftyStoreKit.verifyReceipt(using: appleValidator) { result in
                switch result {
                case .success(let receipt):
                    let productId = id
                    // Verify the purchase of Consumable or NonConsumable
                    let purchaseResult = SwiftyStoreKit.verifyPurchase(
                        productId: productId,
                        inReceipt: receipt)
    
                    switch purchaseResult {
                    case .purchased(let receiptItem):
                        print("\(productId) is purchased: \(receiptItem)")
                        self.fullPurchase = true
                    case .notPurchased:
                        self.purchaseProduct(with: self.inAppPurchaseId)
                        print("The user has never purchased \(productId)")
                        self.fullPurchase = false
                    }
                case .error(let error):
                    print("Receipt verification failed: \(error)")
                }
            }
        }
    

Information about consumable products is added to the receipt when they’re paid for and remains in the receipt until you finish the transaction. After you finish the transaction, this information is removed the next time the receipt is updated—for example, the next time the user makes a purchase.

Upvotes: 2

Related Questions