How to fix recovery of purchase in iOS application using Xcode 7 and SpriteKit in Swift?

I made a game using Xcode 7 and SpriteKit in Swift, and I finished it. After I sent it to iTunes Connect, Apple rejected it and they sent me a message, they said that the problem is related Restore Purchase, but I put it in the same purchase button, so I made a button that has two functions: 1. Make a purchase, 2. Restore the purchase.

When I tested it, it worked perfectly, and when users have to restore the purchase, they no longer pay. I don't know if this is acceptable from Apple. Or check my code if I forgot to put something!

Message:

From Apple

Missing recovery mechanism

We have found that your application offers an In-App Purchase (s) that can be restored, but does not include the “Restore Purchases” function to allow users to restore previously purchased purchases (s) in the application, as indicated in the “Restoring Purchasing Products” Section "Programming Guides for App Purchases

"Users restore transactions in order to maintain access to already purchased content. For example, when upgrading to a new phone, they don’t lose all the items they purchased on the old phone. Turn on some mechanism in your mechanism so that the user restores his purchases, for example, a button "Restore purchases."

In-App Purchase, " " , " "" ". .

, , :

override func viewDidLoad() {
    super.viewDidLoad()

func addTransactionObserver() {
    SKPaymentQueue.defaultQueue().addTransactionObserver(self)
}

func removeTransactionObserver() {
    SKPaymentQueue.defaultQueue().removeTransactionObserver(self)
}

}

@IBAction func removeAds(sender: UIButton) {
    print("Remove Ads Button pressed")
    for product in list {
        let prodID = product.productIdentifier
        if(prodID == "Squares.RemoveAds") {
            p = product
            buyProduct()
            break;
        }
    }
    ////SKPaymentQueue.defaultQueue().addTransactionObserver(self)
    SKPaymentQueue.defaultQueue().restoreCompletedTransactions()
}



override func prefersStatusBarHidden() -> Bool {
    return true
}

//Remove Ads Payment
var list = [SKProduct]()
var p = SKProduct()


//Squares.RemoveAds


func buyProduct() {
    print("Buy" + p.productIdentifier)
    let pay = SKPayment(product: p)
    ////SKPaymentQueue.defaultQueue().addTransactionObserver(self)
    SKPaymentQueue.defaultQueue().addPayment(pay as SKPayment)
}

func productsRequest(request: SKProductsRequest, didReceiveResponse 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 as SKProduct)
    }
    removeAdsButton.enabled = true
    removeAdsIPhone6Plus.enabled = true
}

func paymentQueueRestoreCompletedTransactionsFinished(queue: SKPaymentQueue) {
    print("Transactions Restored")

    var purchasedItemIDS = []
    for transaction in queue.transactions {
        let t: SKPaymentTransaction = transaction as SKPaymentTransaction

        let prodID = t.payment.productIdentifier as String

        switch prodID {
        case ProductID.removeAds:
            print("Remove Ads")
            Ads.removeAllAds()
        case ProductID.removeAds:
            print("Remove Ads for iPhone 6 Plus")
            Ads.removeAllAds()
        default:
            print("IAP not setup")
        }

    }
}

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 Squares here")
            print(p.productIdentifier)

            let prodID = p.productIdentifier as String
            switch prodID {
            case ProductID.removeAds:
                print("Remove Ads")
                Ads.removeAllAds()
            case ProductID.removeAds:
                print("Remove Ads for iPhone 6 Plus")
                Ads.removeAllAds()
            default:
                print("IAP not Setup")
            }

            queue.finishTransaction(trans)
            break;
        case .Failed:
            print("Buy Error")
            queue.finishTransaction(trans)
            break;
        default:
            print("Default")
            break;

        }
    }
}

func finishTransaction(trans:SKPaymentTransaction){
    print("Finish Transaction")
}

func paymentQueue(queue: SKPaymentQueue, removedTransactions transactions: [SKPaymentTransaction]) {
    print("Remove Transaction")
 }
}

, .

+4
1

, , @IBAction RestorePurchases

IAP Xcode 7.0, iOS 9.0 Swift 2.0. "com.dname.YourApp.removeAds" :)

//
//  IAPViewController.swift
//  

import UIKit
import StoreKit

class IAPViewController: UIViewController, SKProductsRequestDelegate, SKPaymentTransactionObserver{

    let userDefaults = NSUserDefaults.standardUserDefaults()

    //@IBOutlet var lblAd: UILabel!
   // @IBOutlet var lblCoinAmount: UILabel!

    @IBOutlet var removeAds: UIButton!
    //@IBOutlet var outAddCoins: UIButton!
    //var coins = 50

    // 1
    override func viewDidLoad() {
        super.viewDidLoad()
        removeAds.enabled = false
       // outAddCoins.enabled = false

        // Set IAPS
        if(SKPaymentQueue.canMakePayments()) {
            print("IAP is enabled, loading")
            let productID:NSSet = NSSet(objects: "com.dname.YourApp.removeAds")
            let request: SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set<String>)
            request.delegate = self
            request.start()
        } else {
            print("please enable IAPS")
        }

    }

    // 2
    @IBAction func btnRemoveAds(sender: UIButton) {
        for product in list {
            let prodID = product.productIdentifier
            if(prodID == "com.dname.YourApp.removeAds") {
                p = product
                buyProduct()
                break;
            }
        }

    }

/*
// 3
@IBAction func btnAddCoins(sender: UIButton) {
    for product in list {
        var prodID = product.productIdentifier
        if(prodID == "com.dname.YourApp.addcoins") {
            p = product
            buyProduct()
            break;
        }
    }

}
*/

/*
// 4
func removeAds() {
    lblAd.removeFromSuperview()
}
*/

/*
// 5
func addCoins() {
    coins = coins + 50
    lblCoinAmount.text = "\(coins)"
}
*/


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()
}




var list = [SKProduct]()
var p = SKProduct()


func productsRequest(request: SKProductsRequest, didReceiveResponse 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)
        //println(product.price)

        list.append(product )
    }

    removeAds.enabled = true
    //outAddCoins.enabled = true
}

func buyProduct() {
    print("buy " + p.productIdentifier)
    let pay = SKPayment(product: p)
    SKPaymentQueue.defaultQueue().addTransactionObserver(self)
    SKPaymentQueue.defaultQueue().addPayment(pay as SKPayment)
}

func paymentQueueRestoreCompletedTransactionsFinished(queue: SKPaymentQueue) {
    print("transactions restored")

   // var purchasedItemIDS = []
    for transaction in queue.transactions {
        let t: SKPaymentTransaction = transaction 

        let prodID = t.payment.productIdentifier as String

        switch prodID {
        case "com.dname.YourApp.removeAds":

            //Set the user default to not show ads
            userDefaults.setObject(1, forKey: "noAds")
            userDefaults.synchronize()

            print("remove ads")
            //removeAds()
        case "com.dname.YourApp.addcoins":
            print("add coins to account")
            //addCoins()
        default:
            print("IAP not setup")
        }

    }
}


func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
    print("add paymnet")

    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 as String
            switch prodID {
            case "com.dname.YourApp.removeAds":
                print("remove ads")
                //Set the user default to not show ads
                userDefaults.setObject(1, forKey: "noAds")
                userDefaults.synchronize()

                //removeAds()`enter code here`
            case "com.dname.YourApp.addcoins":
                print("add coins to account")
                //addCoins()
            default:
                print("IAP not setup")
            }

            queue.finishTransaction(trans)
            break;
        case .Failed:
            print("buy error")
            queue.finishTransaction(trans)
            break;
        default:
            print("default")
            break;

        }
    }
}

func finishTransaction(trans:SKPaymentTransaction)
{
    print("finish trans")
    SKPaymentQueue.defaultQueue().finishTransaction(trans)
}


func paymentQueue(queue: SKPaymentQueue, removedTransactions transactions: [SKPaymentTransaction]) {
    print("Remove Transaction")
}

}

+5

Source: https://habr.com/ru/post/1607757/


All Articles