Search code examples
iosswiftin-app-purchaserevenuecat

How to purchase consumables with RevenueCat?


I am having difficulty in the logic for making a consumable purchase. Basically I am not sure how to proceed with this function:

private var item: Purchases.Package? {
    Items.shared.item
}
Purchases.shared.products(["com.item.id"]) { products in
    guard let item = products.first else { return }
    Purchases.shared.purchaseProduct(item) { transaction, purchaserInfo, error, cancelled in
    // enable some stuff in the app
    }
}
public class Items: ObservableObject {
    public static let shared = Items()
    
    @Published public var item: Purchases.Package?
    
    init() {
        Purchases.shared.products(["com.item.id"]) { products in
            self.item = products.first
        }
    }
}

If I try to initialise like above, it complains that it is a SKProduct?, and cannot be assigned to Purchases.Package?.


Solution

  • It looks like you're fetching an Apple SKProduct and trying to assign it to a RevenueCat Package.

    You can call the .purchase() method directly with the SKProduct.

    // when your paywall is displayed (or earlier to preload)
    var consumableProduct : SKProduct?
    Purchases.shared.products(["com.item.id"]) { (products) in
        consumableProduct = products.first
    }
    
    // when the user taps the 'Buy' button
    guard let product = consumableProduct else {
        return print("Error: No product exists")
    }
    Purchases.shared.purchaseProduct(product) { (transaction, purchaserInfo, error, userCancelled) in
        // handle purchase
    }
    

    Recommended Approach

    It's recommended to use RevenueCat Offerings/Packages since you wouldn't need to hardcode specific product IDs (e.g. "com.item.id") in your app and you can update things remotely.

    // Offerings are automatically pre-loaded by RevenueCat so
    // this should read very quickly from cache
    var offering : Purchases.Offering?
    Purchases.shared.offerings { (offerings, error) in
        // Add any error handling here
        
        offering = offerings?.current
    }
    
    // when the user taps the 'Buy' button
    
    // this assumes your paywall only has one item to purchase.
    // you may have a dynamic tableview of items and use `indexPath.row` instead of `first`.
    guard let package = offering?.availablePackages.first else {
        print("No available package")
        return
    }
    Purchases.shared.purchasePackage(package) { (trans, info, error, cancelled) in
        // handle purchase
    }