如何更新已在应用商店中的应用以包含应用内购买

时间:2017-07-05 03:16:38

标签: ios swift xcode

现在我在应用程序商店上有一个应用程序。我知道我会迟到更新它,但我只是想确保在我做之前把它放好。所以现在我想实现应用内购买。但是,出于某种原因,它无法正常工作:

这是在ViewDidLoad()

    let productIdentifiers: Set<String> = ["1000Coins"]

    let productsRequest = SKProductsRequest(productIdentifiers: productIdentifiers)

    productsRequest.delegate = self

    productsRequest.start()

这是另一个功能。由于某种原因,它不打印这个

print("Product: \(product.productIdentifier), \(product.localizedTitle),\(product.price.floatValue)")

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

    print("Loaded Products")

    for product in response.products {

        print("Product: \(product.productIdentifier), \(product.localizedTitle),\(product.price.floatValue)")

    }

}

我使用iTunes连接创建了应用内购买但由于某种原因它无法正常工作。有什么建议??谢谢!

1 个答案:

答案 0 :(得分:0)

不要不必要地混乱ViewDidLoad。创建一个应用内购买帮助程序来处理与IAP相关的所有功能,例如获取产品标识符,验证收据,恢复等。

Ron Buencamino写的好帮手就是:

import StoreKit
protocol IAPManagerDelegate {
func managerDidRestorePurchases()
}

class IAPManager: NSObject, SKProductsRequestDelegate, SKPaymentTransactionObserver, SKRequestDelegate {

static let sharedInstance = IAPManager()

var request:SKProductsRequest!
var products:NSArray!

var delegate:IAPManagerDelegate?

//Load product identifiers for store usage
func setupInAppPurchases(){
    self.validateProductIdentifiers(self.getProductIdentifiersFromMainBundle())

    SKPaymentQueue.default().add(self)
}

//Get product identifiers
func getProductIdentifiersFromMainBundle() -> NSArray {
    var identifiers = NSArray()
    if let url = Bundle.main.url(forResource: "iap_products", withExtension: "plist"){
        identifiers = NSArray(contentsOf: url)!
    }

    return identifiers
}

//Retrieve product information
func validateProductIdentifiers(_ identifiers:NSArray) {
    let productIdentifiers = NSSet(array: identifiers as [AnyObject])
    let productRequest = SKProductsRequest(productIdentifiers: productIdentifiers as! Set<String>)
    self.request = productRequest
    productRequest.delegate = self
    productRequest.start()

}

func createPaymentRequestForProduct(_ product:SKProduct){

    let payment = SKMutablePayment(product: product)
    payment.quantity = 1

    SKPaymentQueue.default().add(payment)

}

func verifyReceipt(_ transaction:SKPaymentTransaction?){
    let receiptURL = Bundle.main.appStoreReceiptURL!
    if let receipt = try? Data(contentsOf: receiptURL){
        //Receipt exists
        let requestContents = ["receipt-data" : receipt.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))]

        //Perform request
        do {
            let requestData = try JSONSerialization.data(withJSONObject: requestContents, options: JSONSerialization.WritingOptions(rawValue: 0))

            //Build URL Request

            //change the storeURL before you submit to the app store
            let storeURL = URL(string: "https:/sandbox.itunes.apple.com/verifyReceipt")
            var request = URLRequest(url: storeURL!)
            request.httpMethod = "Post"
            request.httpBody = requestData

            let session = URLSession.shared
            let task = session.dataTask(with: request , completionHandler: { (responseData, response , error) -> Void in

                do {
                    let json = try JSONSerialization.jsonObject(with: responseData! as Data, options: .mutableLeaves) as! NSDictionary

                    print(json)

                    if (json.object(forKey: "status") as! NSNumber) == 0 {
                        //
                        let receipt_dict = json["receipt"] as! NSDictionary

                        if let purchases = receipt_dict["in_app"] as? NSArray  {
                            self.validatePurchaseArray(purchases)
                        }

                        // you can add more statements to check different parts of the receipt

                        if transaction != nil {
                            SKPaymentQueue.default().finishTransaction(transaction!)
                        }
                        DispatchQueue.main.sync(execute: { () -> Void in self.delegate?.managerDidRestorePurchases() } )                       }
                    else {
                        //Debug the receipt
                        print(json.object(forKey: "status") as! NSNumber)
                    }

                }
                catch {
                    print(error)
                }
            } )


            task.resume()

        }
        catch {
            print(error)
        }

    }
    else {
        //Receipt does not exist
        print("No Receipt")
    }
}
func validatePurchaseArray(_ purchases:NSArray){

    for purchase in purchases as! [NSDictionary]{


        self.unlockPurchasedFunctionalityForProductIdentifier(purchase["product_id"] as! String)



    }
}


func unlockPurchasedFunctionalityForProductIdentifier(_ productIdentifier:String){

    ///here you put the functionality that you want to unlock for the user
    UIApplication.shared.isNetworkActivityIndicatorVisible = false
}



func isDateExpired(_ expires_date:Double) -> Bool{
    var isExpired:Bool = false
    let currentDate = (Date().timeIntervalSince1970 * 1000) as TimeInterval

    if currentDate > expires_date{
        isExpired = true
    }

    return isExpired
}

//MARK: SKProductsRequestDelegate
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
    //
    self.products = response.products as NSArray!
    print(self.products)

}

//MARK: SKPaymentTransactionObserver Delegate Protocol
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
    //
    for transaction in transactions as [SKPaymentTransaction]{
        switch transaction.transactionState{
        case .purchasing:
            print("Purchasing")
            UIApplication.shared.isNetworkActivityIndicatorVisible = true
        case .deferred:
            print("Deferrred")
            UIApplication.shared.isNetworkActivityIndicatorVisible = false
        case .failed:
            print("Failed")
            print(transaction.error?.localizedDescription)
            UIApplication.shared.isNetworkActivityIndicatorVisible = false
            SKPaymentQueue.default().finishTransaction(transaction)
        case.purchased:
            print("Purchased")
            //
            self.verifyReceipt(transaction)
        case .restored:
            print("Restored")

        }
    }
}

func restorePurchases(){
    let request = SKReceiptRefreshRequest()
    request.delegate = self
    request.start()
}

func requestDidFinish(_ request: SKRequest) {
    self.verifyReceipt(nil)
}

}

将名为iap_products.plist的plist文件添加到Xcode中并包含产品ID。在所述文件中包括:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"     "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
 <array>
<string>product1Id</string>
<string>product2Id</string>
    so on....
</array>
</plist>