我正在尝试进行IAP,但出于某种原因,我的SKProductsRequest返回0个产品。
- 测试产品已添加到iTunes正确连接
- 填写银行和征税信息
- 产品的套装ID与应用套装ID
相匹配- 我已经等了两天才能通过服务器进行处理
我使用这个youtube教程来构建应用程序: https://www.youtube.com/watch?v=zRrs7O5yjKI
以下是代码:
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.
}
}
当您运行应用程序时,它将打印“IAP已启用,正在加载”而不是“产品请求”,但没有其他内容。
如果我在productsRequest函数中打印response.invalidProductIdentifiers
,它将返回我的产品:["com.IAPTesters.RemoveAds", "com.IAPTesters.10Dolla"]
提前感谢您的帮助
答案 0 :(得分:1)
如果您参考SKProductsRequest
documentation,您会看到:
注意强>
确保对请求对象保持强引用;否则,系统可能会在请求完成之前解除分配请求。
您的SKProductsRequest
实例是viewDidLoad
中的本地常量。一旦viewDidLoad
退出,这将被解除分配,并且由于产品请求将异步完成,这将在请求完成之前完成,因此您将永远不会收到回电。
您应该将SKProductsRequest
保留在属性中,以便不会释放它。
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
}
仅供参考,您对paymentQueueRestoreCompletedTransactionsFinished
的实施不正确;您应该通过updatedTransactions
事务状态处理.restored
中已恢复的事务。 paymentQueueRestoreCompletedTransactionsFinished
方法仅应用于更新UI或执行还原过程完成时所需的任何其他任务。
答案 1 :(得分:0)
如果我理解正确,那么您的实施问题就是您在iTunes中使用错误的标识符创建了您的产品。据我所知,产品标识符应该类似于您的应用程序包标识符,后跟您的产品功能i.e, COM.COMPANYNAME.MYNEWAPPLICATION.REMOVEADS, COM.COMPANYNAME.MYNEWAPPLICATION.10DOLLA
示例代码如,
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)
}
}
您只需在viewDidLoad()
SSIAPHelper.shared.requestProducts(completionHandler: { (result, error) in
})
答案 2 :(得分:0)
事实证明我的银行和税务信息填写不正确。我补充了它,而且我不得不等待大约30分钟再次工作。现在一切正常!感谢所有帮助