SKProductsRequest returns 0 Products

I am trying to do IAP, however for some reason my SKProductsRequest returns 0 products.

-Test products were added to iTunes properly connected

- Information about the bank and taxation is filled

- product identifier matches application package identifier

-I waited up to two days for it to be processed through servers

I used this youtube tutorial to create an application: https://www.youtube.com/watch?v=zRrs7O5yjKI

And here is the code:

import UIKit import StoreKit class ViewController: UIViewController, SKProductsRequestDelegate, SKPaymentTransactionObserver { @IBOutlet weak var lblAd: UILabel! @IBOutlet weak var lblCoinAmount: UILabel! @IBOutlet weak var outRemoveAds: UIButton! @IBOutlet weak var outAddCoins: UIButton! @IBOutlet weak var outRestorePurchases: UIButton! var coins = 50 override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. outRemoveAds.isEnabled = false outAddCoins.isEnabled = false outRestorePurchases.isEnabled = false if(SKPaymentQueue.canMakePayments()) { print("IAP is enabled, loading") let productID: NSSet = NSSet(objects: "com.IAPTesters.10Dolla", "com.IAPTesters.RemoveAds") let request: SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set<String>) request.delegate = self request.start() } else { print("please enable IAPS") } } @IBAction func btnRemoveAds(_ sender: Any) { print("rem ads") for product in list { let prodID = product.productIdentifier if(prodID == "com.IAPTesters.RemoveAds") { p = product buyProduct() } } } @IBAction func btnAddCoins(_ sender: Any) { for product in list { let prodID = product.productIdentifier if(prodID == "com.IAPTesters.10Dolla") { p = product buyProduct() } } } @IBAction func btnRestorePurchases(_ sender: Any) { SKPaymentQueue.default().add(self) SKPaymentQueue.default().restoreCompletedTransactions() } func buyProduct() { print("buy " + p.productIdentifier) let pay = SKPayment(product: p) SKPaymentQueue.default().add(self) SKPaymentQueue.default().add(pay as SKPayment) } func removeAds() { lblAd.removeFromSuperview() } func addCoins() { coins += 50 lblCoinAmount.text = "\(coins)" } var list = [SKProduct]() var p = SKProduct() func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) { print("product request") let myProduct = response.products for product in myProduct { print("product added") print(product.productIdentifier) print(product.localizedTitle) print(product.localizedDescription) print(product.price) list.append(product) } outRemoveAds.isEnabled = true outAddCoins.isEnabled = true outRestorePurchases.isEnabled = true } func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) { print("transactions restored") for transaction in queue.transactions { let t: SKPaymentTransaction = transaction let prodID = t.payment.productIdentifier as String switch prodID { case "com.IAPTesters.RemoveAds": print("remove ads") removeAds() case "com.IAPTesters.10Dolla": print("add coins to account") addCoins() default: print("IAP not found") } } } func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { print("add payment") for transaction: AnyObject in transactions { let trans = transaction as! SKPaymentTransaction print(trans.error) switch trans.transactionState { case .purchased: print("buy ok, unlock IAP HERE") print(p.productIdentifier) let prodID = p.productIdentifier switch prodID { case "com.IAPTesters.RemoveAds": print("remove ads") removeAds() case "com.IAPTesters.10Dolla": print("add coins to account") addCoins() default: print("IAP not found") } queue.finishTransaction(trans) case .failed: print("buy error") queue.finishTransaction(trans) break default: print("Default") break } } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } } 

When the application starts, it will print “IAP enabled, loaded” and “product request”, but nothing else.

If I type response.invalidProductIdentifiers in the productsRequest function, it will return my products: ["com.IAPTesters.RemoveAds", "com.IAPTesters.10Dolla"]

Thank you in advance

+7
ios itunesconnect in-app-purchase
source share
3 answers

It turns out that my banking and tax information was filled in incorrectly. I replenished it, and I had to wait about 30 minutes for it to work again. Now everything works correctly! thanks for the help

0
source share

If you refer to the SKProductsRequest documentation , you will see:

Note

Be sure to keep a strong link to the request object; otherwise, the system may release the request before it is completed.

Your SKProductsRequest instance is a local constant in viewDidLoad . This will be canceled as soon as viewDidLoad comes out, and since the product request is completed asynchronously, it will be before the request is completed, and therefore you will never receive a callback.

You must keep your SKProductsRequest in the property so that it is not released.

 class ViewController: UIViewController, SKProductsRequestDelegate, SKPaymentTransactionObserver { @IBOutlet weak var lblAd: UILabel! @IBOutlet weak var lblCoinAmount: UILabel! @IBOutlet weak var outRemoveAds: UIButton! @IBOutlet weak var outAddCoins: UIButton! @IBOutlet weak var outRestorePurchases: UIButton! var productsRequest: SKProductsRequest? var coins = 50 override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. outRemoveAds.isEnabled = false outAddCoins.isEnabled = false outRestorePurchases.isEnabled = false if(SKPaymentQueue.canMakePayments()) { print("IAP is enabled, loading") let productID: NSSet = NSSet(objects: "com.IAPTesters.10Dolla", "com.IAPTesters.RemoveAds") self.productsRequest = SKProductsRequest(productIdentifiers: productID as! Set<String>) request?.delegate = self request?.start() } else { print("please enable IAPS") } } func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) { print("product request") let myProduct = response.products for product in myProduct { print("product added") print(product.productIdentifier) print(product.localizedTitle) print(product.localizedDescription) print(product.price) list.append(product) } outRemoveAds.isEnabled = true outAddCoins.isEnabled = true outRestorePurchases.isEnabled = true self.productsRequest = nil } 

FYI, your implementation of paymentQueueRestoreCompletedTransactionsFinished is incorrect; You must process the recovered transactions in updatedTransactions through the transaction status .restored . The paymentQueueRestoreCompletedTransactionsFinished method should only be used to update your user interface or to perform any other tasks that are required when the recovery process is complete.

0
source share

If I understand correctly, then the problem with your implementation is that you created your products in iTunes with the wrong identifiers. Since I know that product identifiers should be similar to the identifier of your application, and then your product functionality ie, COM.COMPANYNAME.MYNEWAPPLICATION.REMOVEADS, COM.COMPANYNAME.MYNEWAPPLICATION.10DOLLA

An example code would be

 typealias SSIAPHelperCompletion = (_ result: [SKProduct]?, _ error: Error?) ->Void class SSIAPHelper: NSObject { fileprivate let productsRequest = SKProductsRequest(productIdentifiers: Set(arrayLiteral: "com.companyname.appname.removeads","com.companyname.appname.10dolla")) fileprivate var completion: SSIAPHelperCompletion? static let shared = SSIAPHelper() func requestProducts(completionHandler: @escaping SSIAPHelperCompletion) { self.completion = completionHandler self.productsRequest.delegate = SSIAPHelper.shared self.productsRequest.start() } } extension SSIAPHelper: SKProductsRequestDelegate{ func requestDidFinish(_ request: SKRequest) { print(#function) } func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) { print(#function, response.products) if let lCompletion = self.completion{ lCompletion(response.products, nil) } } func request(_ request: SKRequest, didFailWithError error: Error) { print(#function) } } 

You can get the products simply by calling the function below from viewDidLoad()

 SSIAPHelper.shared.requestProducts(completionHandler: { (result, error) in }) 
0
source share

All Articles