Emm
Emm

Reputation: 1603

How to fix Restore 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 submited it to iTunes Connect, Apple rejected it and they sent me a message, they said that the problem is with Restore Purchase, but I put it in same button with purchase so I made a button that have two functions: 1. To make Purchase, 2. To Restore Purchase.

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

The message is:

From Apple

Missing restore mechanism

We found that your app offers In-App Purchase(s) that can be restored but does not include a “Restore Purchases" feature to allow users to restore the previously purchased In-App Purchase(s), as specified in the “Restoring Purchase Products” section of the In-App Purchase Programming Guide

"Users restore transactions to maintain access to content they’ve already purchased. For example, when they upgrade to a new phone, they don’t lose all of the items they purchased on the old phone. Include some mechanism in your app to let the user restore their purchases, such as a Restore Purchases button."

To restore previously purchased In-App Purchase products, it would be appropriate to provide a "Restore" button and initiate the restore process when the "Restore" button is tapped by the user. Including restore in the purchase button is not a sufficient restore mechanism.

And code that I used is:

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

I hope your contribution will help me.

Upvotes: 4

Views: 1885

Answers (1)

Dave Kozikowski
Dave Kozikowski

Reputation: 651

You may just need to put a button on a screen for the user to press then wire it up to the @IBAction func RestorePurchases

I have included my default IAP for Xcode 7.0, iOS 9.0, and Swift 2.0 Change "com.dname.YourApp.removeAds" with the correct string :)

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

}

Upvotes: 5

Related Questions