应用程序内购买和恢复按钮:单个产品 – 非消耗品

这个问题让我好几天了。

我有一个简单的应用程序,显示横幅广告和插页式广告。

我正在使用单个视图应用程序,具有主视图控制器( ViewController.swift )并设置了另一个视图控制器( InAppViewController.swift )来处理弹出页面:

  1. 允许用户进行应用内购买以移除所有广告(AdBanners和InterstitialAds); 要么
  2. 恢复购买。

我运行它时,我的代码没有错误。

应用内购买正常运行,但有时我会向iTunes收到两次登录请求。

但我的恢复按钮和相关function似乎是问题。

我已经设置了许多沙箱测试程序帐户进行测试,而未购买该应用程序的新用户可以成功恢复购买。 哪个不可能,所以我肯定在这里做错了。

这是我的代码:

主视图控制器:

 // ViewController.swift import UIKit import MessageUI import Social import iAd import StoreKit class ViewController: UIViewController, MFMailComposeViewControllerDelegate, MFMessageComposeViewControllerDelegate, ADBannerViewDelegate, ADInterstitialAdDelegate { let defaults = NSUserDefaults.standardUserDefaults() var product_id: NSString?; override func viewDidLoad() { product_id = "some.product.id"; super.viewDidLoad() //Check if product is purchased if (defaults.boolForKey("purchased")){ print("already purchased") // Hide or show banner ads is purchased/not purchased. // Advertising Banner: self.canDisplayBannerAds = false } else if (!defaults.boolForKey("stonerPurchased")){ print("not yet purchased") // Advertising Banner: self.canDisplayBannerAds = true } 

这段代码似乎完美无缺。 当应用加载时,它可以确定谁已经付费以删除广告和未付费的广告,并且广告横幅会正确显示。

它在第二个视图控制器( InAppPViewController.swift )中我遇到了问题。

这是我的代码:

第二个视图控制器 – InAppViewController.swift:

 // InAppPViewController.swift import UIKit import StoreKit import iAd class InAppPViewController: UIViewController, SKProductsRequestDelegate, SKPaymentTransactionObserver { let defaults = NSUserDefaults.standardUserDefaults() var product_id: NSString?; @IBOutlet weak var unlockAction: UIButton! @IBOutlet var adBannerView: ADBannerView? override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } @IBAction func restorePurchases(sender: UIButton) { SKPaymentQueue.defaultQueue().addTransactionObserver(self) SKPaymentQueue.defaultQueue().restoreCompletedTransactions() } func paymentQueueRestoreCompletedTransactionsFinished(queue: SKPaymentQueue) { print("Transactions Restored") let alert = UIAlertView(title: "Thank You", message: "Your purchase(s) were restored.", delegate: nil, cancelButtonTitle: "OK") alert.show() } @IBAction func unlockAction(sender: AnyObject) { product_id = "some.product.id"; SKPaymentQueue.defaultQueue().addTransactionObserver(self) //Check if product is purchased if (defaults.boolForKey("purchased")){ } else if (!defaults.boolForKey("stonerPurchased")){ print("false") } print("About to fetch the products"); // We check that we are allowed to make the purchase. if (SKPaymentQueue.canMakePayments()) { let productID:NSSet = NSSet(object: self.product_id!); let productsRequest:SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set); productsRequest.delegate = self; productsRequest.start(); print("Fething Products"); }else{ print("can't make purchases"); } } func buyProduct(product: SKProduct){ print("Sending the Payment Request to Apple"); let payment = SKPayment(product: product) SKPaymentQueue.defaultQueue().addPayment(payment); } //Delegate Methods for IAP func productsRequest (request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) { let count : Int = response.products.count if (count>0) { let validProduct: SKProduct = response.products[0] as SKProduct if (validProduct.productIdentifier == self.product_id) { print(validProduct.localizedTitle) print(validProduct.localizedDescription) print(validProduct.price) buyProduct(validProduct); } else { print(validProduct.productIdentifier) } } else { print("nothing") } } func request(request: SKRequest, didFailWithError error: NSError) { print("Error Fetching product information"); } func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { print("Received Payment Transaction Response from Apple"); for transaction:AnyObject in transactions { if let trans:SKPaymentTransaction = transaction as? SKPaymentTransaction{ switch trans.transactionState { case .Purchased: print("Product Purchased"); SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction) defaults.setBool(true , forKey: "purchased") break; case .Failed: print("Purchased Failed"); SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction) break; case .Restored: print("Already Purchased"); SKPaymentQueue.defaultQueue().restoreCompletedTransactions() default: break; } } } } 

}

我哪里错了?

问题:

  1. 我上面的代码是否正确?
  2. 我应该修改什么以及为什么?

提前道歉,我是这个奇妙的编码世界的新手……但是热爱它的每一分钟!

  1. SKPaymentQueue.defaultQueue().addTransactionObserver(self)应该在viewDidLoad()不在restore func中
  2. 您可以像这样override func viewWillDisappear(animated: Bool) { SKPaymentQueue.defaultQueue().removeTransactionObserver(self) } SKPaymentQueue.defaultQueue().restoreCompletedTransactions() override func viewWillDisappear(animated: Bool) { SKPaymentQueue.defaultQueue().removeTransactionObserver(self) }
  3. 在沙箱中登录两次是正常的。

希望我有所帮助。

我修改了InAppPViewController.swift文件的代码,如下所示:

 // InAppPViewController.swift import UIKit import StoreKit class InAppPViewController: UIViewController, SKProductsRequestDelegate, SKPaymentTransactionObserver { let defaults = NSUserDefaults.standardUserDefaults() var product_id: NSString?; override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } @IBAction func restorePurchases(sender: UIButton) { // Set up the observer SKPaymentQueue.defaultQueue().addTransactionObserver(self) //Check if user can make payments and then proceed to restore purchase if (SKPaymentQueue.canMakePayments()) { SKPaymentQueue.defaultQueue().restoreCompletedTransactions() } } @IBAction func unlockAction(sender: AnyObject) { product_id = "some.product.id"; // Adding the observer SKPaymentQueue.defaultQueue().addTransactionObserver(self) //Check if product is purchased if (defaults.boolForKey("purchased")){ print("User already purchased this") // Hide a view or show content depends on your requirement } else if (!defaults.boolForKey("Purchased")){ print("User has not yet pur hased this") } print("About to fetch the products"); // Check if user can make payments and then proceed to make the purchase. if (SKPaymentQueue.canMakePayments()) { let productID:NSSet = NSSet(object: self.product_id!); let productsRequest:SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set); productsRequest.delegate = self; productsRequest.start(); print("User can make purchases and will fetch products from Apple Store now"); }else{ print("User can't make purchases"); } } func buyProduct(product: SKProduct){ print("Sending the Payment Request to Apple"); let payment = SKPayment(product: product) SKPaymentQueue.defaultQueue().addPayment(payment); } func productsRequest (request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) { let count : Int = response.products.count if (count>0) { let validProduct: SKProduct = response.products[0] as SKProduct if (validProduct.productIdentifier == self.product_id) { print(validProduct.localizedTitle) print(validProduct.localizedDescription) print(validProduct.price) buyProduct(validProduct); } else { print(validProduct.productIdentifier) } } else { print("nothing") } } func request(request: SKRequest, didFailWithError error: NSError) { print("Error Fetching product information"); } // Allowing for all possible outcomes: func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { print("Received Payment Transaction Response from Apple"); for transaction:AnyObject in transactions { if let trans:SKPaymentTransaction = transaction as? SKPaymentTransaction { switch trans.transactionState { case .Purchased: print("Product Purchased") let alert = UIAlertView(title: "Thank You", message: "Thank you for your purchase!", delegate: nil, cancelButtonTitle: "OK") alert.show(); SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction) defaults.setBool(true , forKey: "purchased") break; case .Failed: print("Purchased Failed"); SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction) break; case .Restored: print("Already Purchased"); SKPaymentQueue.defaultQueue().restoreCompletedTransactions() break; default: break; } } } } 

}

我按原样离开了ViewController.swift文件。

产品购买似乎现在有效。

但是关于Restore Purchases,我可以在我的物理设备上运行代码,但无法测试Restore Purchasesfunction。

我遇到了之前尚未解决并在系统中循环的恢复购买。 我无法手动清除SKPaymentsQueue。 因此,我的代码拒绝接受新的恢复购买请求。