ios沙箱应用内购买无法正常工作

时间:2017-04-03 10:03:32

标签: ios swift in-app-purchase

请指教!我正在尝试测试沙盒用户的应用内购买。 我正在关注帖子底部的教程。

目前的问题是通过func productsRequest中的response.invalidProductIdentifiers.count!= 0接收无效的产品标识符(_ request:SKProductsRequest,didReceive response:SKProductsResponse)。

以下是购买信息 enter image description here

这是应用信息 enter image description here

以下是准备提交中的应用内购买方式,并添加到应用中: enter image description here enter image description here

以下是Xcode中的设置: enter image description here

我已查看设置 - >能力 - >应用程序内购买。

我在代码中使用的productId是: 让PREMIUM_PRODUCT_ID =" com.iaptutorial.premium"。 然后像这样调用它:     // MARK: - FETCH可用的IAP产品     func fetchAvailableProducts(){

    // Put here your IAP Products ID's
    let productIdentifiers = NSSet(objects: PREMIUM_PRODUCT_ID )

    productsRequest = SKProductsRequest(productIdentifiers: productIdentifiers as! Set<String>)
    productsRequest.delegate = self
    productsRequest.start()
}

我也无法在应用程序之前使用沙箱用户登录,但这不应该是一个问题:iTunes account creation not allowed when trying to test In-App Purchases

以下是教程: https://code.tutsplus.com/tutorials/in-app-purchase-tutorial-with-swift-3-ios-sdk--cms-27595 http://www.appcoda.com/in-app-purchase-tutorial/

我在真正的iPad 2 iOS 9.0上进行测试

我已阅读很多关于应用内购买问题的SO帖子,但没有任何效果。

如果需要,我可以在github上传项目。

问题是什么?谢谢

这是我的代码:

import UIKit
import StoreKit

class ViewController: UIViewController, SKProductsRequestDelegate,SKPaymentTransactionObserver {

    @IBAction func actionPurchase(_ sender: Any) {
        purchaseMyProduct(product: iapProducts[0])
    }
    @IBAction func actionRestore(_ sender: Any) {
    }

    @IBOutlet weak var premiumLabel: UILabel!
    @IBOutlet weak var nonconsumableLabel: UILabel!

    /* Variables */

    let PREMIUM_PRODUCT_ID = "com.iaptutorial.premium"

    var productID = ""
    var productsRequest = SKProductsRequest()
    var iapProducts = [SKProduct]()
    var nonConsumablePurchaseMade = UserDefaults.standard.bool(forKey: "nonConsumablePurchaseMade")



    override func viewDidLoad() {

        // Check your In-App Purchases
        print("NON CONSUMABLE PURCHASE MADE: \(nonConsumablePurchaseMade)")

        if nonConsumablePurchaseMade {
            premiumLabel.text = "Premium version PURCHASED!"
        }
        else {
            premiumLabel.text = "Premium version LOCKED!"
        }

        // Fetch IAP Products available
        fetchAvailableProducts()
    }

    // MARK: - FETCH AVAILABLE IAP PRODUCTS
    func fetchAvailableProducts()  {

        // Put here your IAP Products ID's
        let productIdentifiers = NSSet(objects: PREMIUM_PRODUCT_ID )

        productsRequest = SKProductsRequest(productIdentifiers: productIdentifiers as! Set<String>)
        productsRequest.delegate = self
        productsRequest.start()
    }





    // MARK: - RESTORE NON-CONSUMABLE PURCHASE BUTTON
    @IBAction func restorePurchaseButt(_ sender: Any) {
        SKPaymentQueue.default().add(self)
        SKPaymentQueue.default().restoreCompletedTransactions()
    }

    func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
        nonConsumablePurchaseMade = true
        UserDefaults.standard.set(nonConsumablePurchaseMade, forKey: "nonConsumablePurchaseMade")

        UIAlertView(title: "IAP Tutorial",
                    message: "You've successfully restored your purchase!",
                    delegate: nil, cancelButtonTitle: "OK").show()
    }

    // MARK: - REQUEST IAP PRODUCTS

    func productsRequest (_ request:SKProductsRequest, didReceive response:SKProductsResponse) {
        print("inside productsRequest")

        if (response.products.count > 0) {
            iapProducts = response.products

            /*
            // 1st IAP Product (Consumable) ------------------------------------
            let firstProduct = response.products[0] as SKProduct

            // Get its price from iTunes Connect
            let numberFormatter = NumberFormatter()
            numberFormatter.formatterBehavior = .behavior10_4
            numberFormatter.numberStyle = .currency
            numberFormatter.locale = firstProduct.priceLocale
            let price1Str = numberFormatter.string(from: firstProduct.price)

            // Show its description
            consumableLabel.text = firstProduct.localizedDescription + "\nfor just \(price1Str!)"
            // ------------------------------------------------
            */

            /*
            // 2nd IAP Product (Non-Consumable) ------------------------------
            if response.products.count > 0{
                print("inside")
                let secondProd = response.products[0] as SKProduct

                // Get its price from iTunes Connect
                let numberFormatter = NumberFormatter()
                numberFormatter.locale = secondProd.priceLocale
                let price2Str = numberFormatter.string(from: secondProd.price)

                nonconsumableLabel.text = secondProd.localizedDescription + " for just \(price2Str!)"
            }
            */

        }
        if response.invalidProductIdentifiers.count != 0 {
            print("invalid")
            print(response.invalidProductIdentifiers.description)
        }
    }



    // MARK: - MAKE PURCHASE OF A PRODUCT
    func canMakePurchases() -> Bool {  return SKPaymentQueue.canMakePayments()  }
    func purchaseMyProduct(product: SKProduct) {
        print("inside purchasemyproduct")
        if self.canMakePurchases() {
            let payment = SKPayment(product: product)
            SKPaymentQueue.default().add(self)
            SKPaymentQueue.default().add(payment)

            print("PRODUCT TO PURCHASE: \(product.productIdentifier)")
            productID = product.productIdentifier


            // IAP Purchases dsabled on the Device
        } else {
            UIAlertView(title: "IAP Tutorial",
                        message: "Purchases are disabled in your device!",
                        delegate: nil, cancelButtonTitle: "OK").show()
        }
    }

    // MARK:- IAP PAYMENT QUEUE
    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        print ("inside paymentqueue")
        for transaction:AnyObject in transactions {
            if let trans = transaction as? SKPaymentTransaction {
                switch trans.transactionState {

                case .purchased:
                    SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)

                    // The Consumable product (10 coins) has been purchased -> gain 10 extra coins!
                    if productID == PREMIUM_PRODUCT_ID {

                        // Save your purchase locally (needed only for Non-Consumable IAP)
                        nonConsumablePurchaseMade = true
                        UserDefaults.standard.set(nonConsumablePurchaseMade, forKey: "nonConsumablePurchaseMade")

                        premiumLabel.text = "Premium version PURCHASED!"

                        UIAlertView(title: "IAP Tutorial",
                                    message: "You've successfully unlocked the Premium version!",
                                    delegate: nil,
                                    cancelButtonTitle: "OK").show()
                    }

                    break

                case .failed:
                    SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
                    break
                case .restored:
                    SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
                    break

                default: break
                }}}
    }


}

0 个答案:

没有答案