应用程序内购买&恢复按钮:单个产品 - 非消耗品 [英] In-App Purchase & Restore Button : Single Product - Non-Consumable

查看:118
本文介绍了应用程序内购买&恢复按钮:单个产品 - 非消耗品的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题让我好几天了。

This issue has had me going for days.

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

I have a simple app, that displays banners and interstitial adverts.

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

I am using a single view application, have main view controller (ViewController.swift) and have set up another view controller (InAppViewController.swift) to handle a pop-up page that:


  1. 允许用户进行应用内购买以删除所有广告(AdBanners& InterstitialAds);或

  2. 恢复购买。

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

My code is error-free when I run it.

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

In-app purchases are running ok, but occasionally I get a sign-in request to iTunes twice.

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

But my restore button and associated functionality seem to be the problem.

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

I have set-up numerous sandbox tester accounts to test, and a new user that has not bought the app is able to restore purchases successfully. Which should not be possible, so I definitely have done something wrong here.

这是我的代码:

主视图控制器:

//  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
        }

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

This code seems to work perfectly. When the app loads, it is able to determine who has paid to remove ads and those who have not paid, and ad banners are shown appropriately.

它是在第二个查看控制器( InAppPViewController.swift )我遇到了问题。

It is in the second view controller (InAppPViewController.swift) That I am having problems.

这是我的代码:

第二视图控制器 - 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<String>);
        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. 我应该修改什么以及为什么?

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

Apologies in advance, I am new to this wonderful world of coding ... but loving every minute of it!

推荐答案

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

I have amended my code for the InAppPViewController.swift file as follows:

//  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<String>);
        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 文件。

产品购买现在似乎有效。

Product purchases seem to work now.

但是关于Restore Purchases,我可以在我的物理设备上运行代码,但不能测试恢复购买功能。

But regarding Restore Purchases, I can run the code on my physical device, but cannot test the Restore Purchases function.

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

I am caught with previous Restore Purchases that are still unresolved and looping in the system. I am unable to clear my SKPaymentsQueue manually. Thus my code refuses to entertain anymore new Restore Purchase requests.

这篇关于应用程序内购买&amp;恢复按钮:单个产品 - 非消耗品的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆