应用内购买还原按钮可还原未购买的应用内

时间:2020-03-11 17:35:44

标签: arrays objective-c swift xcode in-app-purchase

在应用程序购买方面,我很失落。我发现有关堆栈溢出的非常可靠的帖子很有帮助。 [Stack Post] [1]但是在此之后我仍然遇到问题。如果我以前从未购买过应用程序内购买商品,而我点击了“恢复”按钮,它将以任何方式解锁。任何帮助都会令人惊讶。

    class ViewController: UIViewController, SKProductsRequestDelegate, SKPaymentTransactionObserver {

    @IBOutlet weak var nonConsumableLabel: UILabel!

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


override func viewDidLoad() {
    super.viewDidLoad()

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

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

    // Fetch IAP Products available
    fetchAvailableProducts()
}


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

@IBAction func printer(_ sender: Any) {
    print(iapProducts)
}


// 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")


    let alert = UIAlertController(title: "IAP Tutorial", message: "You've successfully restored your purchase!", preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "Close", style: .cancel, handler: nil))
    self.present(alert, animated: true)

    func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
        for transaction in queue.transactions {
            let t: SKPaymentTransaction = transaction
            let prodID = t.payment.productIdentifier as String

            switch prodID {
            case "id_sold":
                // implement the given in-app purchase as if it were bought
                print("Second IAP restored")
            default:
                print("iap not found")
            }
        }
    }
}


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

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

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


// MARK: - REQUEST IAP PRODUCTS
func productsRequest (_ request:SKProductsRequest, didReceive response:SKProductsResponse) {
    if (response.products.count > 0) {
        iapProducts = response.products

        // Get its price from iTunes Connect
        let numberFormatter = NumberFormatter()
        numberFormatter.formatterBehavior = .behavior10_4
        numberFormatter.numberStyle = .currency

        // 2nd IAP Product (Non-Consumable) ------------------------------
        let secondProd = response.products[0] as SKProduct

        // Get its price from iTunes Connect
        numberFormatter.locale = secondProd.priceLocale
    }
}




// MARK: - MAKE PURCHASE OF A PRODUCT
func canMakePurchases() -> Bool {  return SKPaymentQueue.canMakePayments()  }
func purchaseMyProduct(product: SKProduct) {
    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 {

        let alert = UIAlertController(title: "IAP Tutorial", message: "You've successfully restored your purchase!", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "Close", style: .cancel, handler: nil))
        self.present(alert, animated: true)
    }
}



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

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

                    if productID == id_sold {

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

                        nonConsumableLabel.text = "Premium version PURCHASED!"



                        let alert = UIAlertController(title: "IAP Tutorial", message: "You've successfully unlocked the Premium version!", preferredStyle: .alert)
                        alert.addAction(UIAlertAction(title: "Close", style: .cancel, handler: nil))
                        self.present(alert, animated: true)
                    }

                    break

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

1 个答案:

答案 0 :(得分:0)

你在说

divmod

但是即使没有任何恢复,该方法也会被调用。它的全部意思是恢复交互是 over ,而不是成功。但是您要继续前进,就好像它成功了一样,并向您的用户授予神奇的用户默认密钥。