Search code examples
swiftxcodein-app-purchase

How can I give rewards only after successful completion of IAP


I will try and explain my issue as clearly as i can. I have IAP in my app, i am trying to use boolean values to determine if the player should receive rewards or not. I am using this code

self.purchaseExtraRounds = true
self.purchaseRemoveAds = true

but i am not sure where to place it to enable the user to get the rewards only after the purchase has been completed. At the moment wherever i seem to place it, i can click on a IAP and then click cancel and the rewards have been enabled without actually purchasing it. Here is my IAP manager file.

class IAPManager: NSObject {
  static let shared = IAPManager()
    var purchaseExtraRounds = false
    var purchaseRemoveAds = false
    
  private override init() {
    super.init()
  }
  
  func getProducts() {
    let request = SKProductsRequest(productIdentifiers: allInAppPurchases)
    request.delegate = self
    request.start()
  }
  
  func purchase(product: SKProduct) -> Bool {
    if !IAPManager.shared.canMakePayments() {
        return false
    } else {
      let payment = SKPayment(product: product)
        SKPaymentQueue.default().add(payment)
    }
    return true
  }

  func canMakePayments() -> Bool {
    return SKPaymentQueue.canMakePayments()
  }
}

extension IAPManager: SKProductsRequestDelegate, SKRequestDelegate {

  func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
    let badProducts = response.invalidProductIdentifiers
    let goodProducts = response.products
    
    if !goodProducts.isEmpty {
      ProductsDB.shared.items = response.products
        print("Good", ProductsDB.shared.items)
    }
    
    print("Bad", badProducts)
  }
  
  func request(_ request: SKRequest, didFailWithError error: Error) {
    print("didFailWithError ", error)
    DispatchQueue.main.async {
      print("purchase failed")
    }
  }
  
    func requestDidFinish(_ request: SKRequest) {
    DispatchQueue.main.async {
      print("request did finish ")
    }
  }
}

final class ProductsDB: ObservableObject, Identifiable {
  static let shared = ProductsDB()
  var items: [SKProduct] = [] {
    willSet {
      DispatchQueue.main.async {
        self.objectWillChange.send()
      }
    }
  }
}

I have tired placing the code in several places in this file but i’m hitting a wall.


Solution

  • So i solved the issue like this; implement this function

    private func handlePurchase(_ id: String) {
            if id == "remove ads product id" {
                removeAds(id: "remove ads product id")}
    }
    

    call at this point

    case .purchased:
                   handlePurchase(transaction.payment.productIdentifier)
    

    which will call another function i created to give the reward like so

    func removeAds(id: String) {
            UserDefaults.standard.set(true, forKey: "RemoveAdsPurchased")
        }