in app purchase

Hello World,


I have a problem inserting in-app purchases into my app.

This is the first time I'm interested in this kind of code and I have some problems.

I would like to have a non-consumable purchase and a consumable purchase. But, I inserted a button for the non-consumable, and it always sends me back to the consumable purchase ...

In addition I coded a button to restore non-consumable purchases but when I click on it, he considers that I made my purchases while not ...

Here is the code I used. If you have an easier way to code a non-consumable purchase, I'm interested.



Thank you in advance for your help.




   let coins2_PRODUCT_ID = "com.company.Deri.PubsConso"
    let PREMIUM_PRODUCT_ID = "com.company.Deri.Pubs"
    var productID = ""
    var productsRequest = SKProductsRequest()
    var iapProducts = [SKProduct]()
    var nonConsumablePurchaseMade7 = UserDefaults.standard.bool(forKey: "nonConsumablePurchaseMade7")
    var coins2 = UserDefaults.standard.integer(forKey: "coins2")
    var AchatOK = false

    override func viewDidLoad() {
        super.viewDidLoad()
if nonConsumablePurchaseMade7 {
            premiumLabel.text = premiumLabelPourLangue.text
            AchatOK = true
        } else {
            premiumLabel.text = premiumLabelPourLangue.text
        }
}

    /
    @IBAction func UnlockPub(_ sender: UISwitch) {
        if AchatOK == true {
            Switch_Achat_PUB.isOn = true
        } else {
            if Switch_Achat_PUB.isOn == true {
                purchaseMyProduct(product: iapProducts[1])
            }
        }
        nonConsumablePurchaseMade7 = true
        UserDefaults.standard.set(nonConsumablePurchaseMade7, forKey: "nonConsumablePurchaseMade7")
    }
  
    /
    @IBAction func restorePurchaseButt(_ sender: Any) {
        SKPaymentQueue.default().add(self)
        SKPaymentQueue.default().restoreCompletedTransactions()
        /
    }
  
    func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
        nonConsumablePurchaseMade7 = true
        UserDefaults.standard.set(nonConsumablePurchaseMade7, forKey: "nonConsumablePurchaseMade7")
      
        UIAlertView(title: "DeriveesPRO",
                    message: "You've successfully restored your purchase! Restart your application!",
                    delegate: nil, cancelButtonTitle: "OK").show()
    }
    /
    func fetchAvailableProducts()  {
        /
        let productIdentifiers = NSSet(objects:
            coins2_PRODUCT_ID,
                                       PREMIUM_PRODUCT_ID
        )
        productsRequest = SKProductsRequest(productIdentifiers: productIdentifiers as! Set<String>)
        productsRequest.delegate = self
        productsRequest.start()
    }
    /
    func productsRequest (_ request:SKProductsRequest, didReceive response:SKProductsResponse) {
        if (response.products.count > 0) {
            iapProducts = response.products
          
            /
            let firstProduct = response.products[0] as SKProduct
          
            /
            let numberFormatter = NumberFormatter()
            numberFormatter.formatterBehavior = .behavior10_4
            numberFormatter.numberStyle = .currency
            numberFormatter.locale = firstProduct.priceLocale
            let price1Str = numberFormatter.string(from: firstProduct.price)
          
            /
            consumableLabel.text = firstProduct.localizedDescription + "\nfor just \(price1Str!)"
            /
          
          
          
            /
            let secondProd = response.products[1] as SKProduct
          
            /
            numberFormatter.locale = secondProd.priceLocale
            let price2Str = numberFormatter.string(from: secondProd.price)
          
            /
            nonConsumableLabel.text = secondProd.localizedDescription + "\nfor just \(price2Str!)"
            /
        }
    }
    /
    func canMakePurchases() -> Bool {
        return SKPaymentQueue.canMakePayments()
    }
    func purchaseMyProduct(product: SKProduct) {
        if self.canMakePurchases() {
            let payment = SKPayment(product: product)
            SKPaymentQueue.default().add(self)
            SKPaymentQueue.default().add(payment)
          
            print("PRODUCT TO PURCHASE: \(product.productIdentifier)")
            productID = product.productIdentifier
          
            /
        } else {
            UIAlertView(title: "Purchase completed",
                        message: "1: Purchases are disabled in your device! Restart your application",
                        delegate: nil, cancelButtonTitle: "OK").show()
        }
    }
    /
    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        for transaction:AnyObject in transactions {
            if let trans = transaction as? SKPaymentTransaction {
                switch trans.transactionState {
                  
                case .purchased:
                    SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
                  
                    /
                    if productID == coins2_PRODUCT_ID {
                      
                        /
                        coins2 += 10
                        UserDefaults.standard.set(coins2, forKey: "coins2")
                        coins2Label.text = "coins2: \(coins2)"
                      
                        UIAlertView(title: "DeriveesPRO",
                                    message: "2: Purchases are disabled in your device! Restart your application",
                                    delegate: nil,
                                    cancelButtonTitle: "OK").show()
                      
                      
                      
                        /
                    } else if productID == PREMIUM_PRODUCT_ID {
                      
                        /
                        nonConsumablePurchaseMade7 = true
                        UserDefaults.standard.set(nonConsumablePurchaseMade7, forKey: "nonConsumablePurchaseMade7")
                      
                        premiumLabel.text = premiumLabelPourLangue.text
                      
                        UIAlertView(title: "DeriveesPRO",
                                    message: "Restart your application! Purchases are now disabled in your device!",
                                    delegate: nil,
                                    cancelButtonTitle: "OK").show()
                    }
                  
                    break
                  
                case .failed:
                    SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
                    break
                case .restored:
                    SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
                    break
                  
                default: break
                }}}
    }

I believe your problem is the logic of coding, not the use of IAP methods. For example:

    @IBAction func UnlockPub(_ sender: UISwitch) { 
        if AchatOK == true { 
            Switch_Achat_PUB.isOn = true 
        } else { 
            if Switch_Achat_PUB.isOn == true { 
                purchaseMyProduct(product: iapProducts[1]) 
            } 
        } 
        nonConsumablePurchaseMade7 = true 
        UserDefaults.standard.set(nonConsumablePurchaseMade7, forKey: "nonConsumablePurchaseMade7") 
    }

will always result in nonConsumablePurchase7 being set to true and the UserDefaults set to true whether or not the purchase is made.

Many similar 'logic' errors are elsewhere throughout your code.

Thank you for your answer, indeed !

Now my question is, if I use this function to restore my purchases:


     @IBAction func restorePurchaseButt (_ sender: Any) {
         SKPaymentQueue.default (). Add (self)
         SKPaymentQueue.default (). RestoreCompletedTransactions ()
         /
     }
    func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) { 
        nonConsumablePurchaseMade7 = true 
        UserDefaults.standard.set(nonConsumablePurchaseMade7, forKey: "nonConsumablePurchaseMade7") 

        UIAlertView(title: "DeriveesPRO", 
                    message: "You've successfully restored your purchase! Restart your application!", 
                    delegate: nil, cancelButtonTitle: "OK").show() 
    }


How can I recognize that the user had already bought one purchase over another?

Because this function restores the purchases but does not allow me to know if this purchase is "com.company.Deri.PubsConso" or "com.company.Deri.Pubs"



Thanks for your help.

You want to add code to the updatedTransactions method for the case restored. In that method you can retrieve the transaction.productIdentifier.

Sorry I do not understand

I only program in Objective C so I can't identify all of your errors. You have identified a specific problem.


You asked:

"How can I recognize that the user had already bought one purchase over another?"


In the method which Swift calls "func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) " you have "case .purchased:" where you handle a new purchase. In that method you are able to tell which product the user purchased. In that same method you can add a "case .restored" that can handle a restored transaction the same as a purchased transaction. You do not want to handle the restored purchase in the method that Swift calls "func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue)"

thank you for your help ! but I still have the same problem. When I click restore when I did not buy, he thinks I bought it

Have you changed your code in response to this statement in my earlier post:

"You do not want to handle the restored purchase in the method that Swift calls "func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue)"

Yes, this function for a single purchase. but when I have two purchases, this one does not differentiate the first from the second. I do not know how to differentiate the one that was bought from the one that was not Thank for your help.

Have you read this in my earlier post:


"In the method which Swift calls "func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) " you have "case .purchased:" where you handle a new purchase. In that method you are able to tell which product the user purchased. In that same method you can add a "case .restored" that can handle a restored transaction the same as a purchased transaction. You do not want to handle the restored purchase in the method that Swift calls "func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue)"

in app purchase
 
 
Q