Search code examples
iosswiftin-app-purchasesandbox

In App Purchase not restoring transactions with sandbox user


This seems to be a common problem from my research

This is all done on a real device.

My app buys the In App Purchase, but when I come to restore the In App Purchase it does not react.

Following this,

    @IBAction func RestoreItem(_ sender: Any) {
            SKPaymentQueue.default().restoreCompletedTransactions()
    print("RESTORING PURCHASES")       
    }

it is supposed to call the products request then payment queue functions. I have read that if the iTunes Account does not contain the purchases that are not called. If I run the app and purchase each item the app purchases ok and says these have been purchased before so it knows the purchase history

What I can not understand is why, if it knows the items have been purchased it does not react after calling the function (as seen above).

If I log out of my iTunes Account completely on my device and trigger the action above it asks me to log in to my account. I do this (the same account where I previously purchased) and it does not trigger the product request (I have NSlog statements all over to see what state I am at)

Any thoughts as i have been struggling with this for days. thanks

I have included code below, this works for purchasing (just for reference).

    func productsRequest(_ request: SKProductsRequest, didReceive     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)
    }

   }


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

    for transaction: AnyObject in transactions {
        let trans = transaction as! SKPaymentTransaction
        print(trans.error as Any)

        switch trans.transactionState {
        case SKPaymentTransactionState.purchased:
            print("buy ok, unlock IAP HERE")
            print(p.productIdentifier)





            let prodID = p.productIdentifier

            switch prodID {
            case "com.clivedancey.social":
                print("Social Reality Unlocked")
                 outBuySocial.setTitle("Social Reality Enabled", for: UIControlState.normal)
                SocialReality()

            case "com.clivedancey.inapp":
                print("MAIN UPGRADE UNLOCKED")

                 outBuyMain.setTitle(" Main Upgrade Complete", for: UIControlState.normal)
                mainunlock()

            default:
                print("IAP not setup")
            }


            queue.finishTransaction(trans)

        case SKPaymentTransactionState.restored:
            print("buy ok, unlock IAP HERE")
            print(p.productIdentifier)


            let prodID = p.productIdentifier

            switch prodID {
            case "com.clivedancey.social":
                print("Social Reality Unlocked")
                outBuySocial.setTitle("Social Reality Enabled", for: UIControlState.normal)

                SocialReality()
                outTransactionLabel.text = " Purchases restored"


            case "com.clivedancey.inapp":
                print("MAIN UPGRADE UNLOCKED")

                outBuyMain.setTitle(" Main Upgrade Complete", for: UIControlState.normal)
                outTransactionLabel.text = " Purchases restored1"
                mainunlock()

            default:
                print("IAP not setup")
            }


            queue.finishTransaction(trans)


        case.failed:
            print("buy error")


            queue.finishTransaction(trans)
            break

        default:
            print("Default")
            break

        }
    }
}

Solution

  • A few things. First - hopefully not important - is your use of "react" in but when I come to restore the In App Purchase it does not react. I hope you don't mean that a breakpoint is never hit.

    My StoreKit code has two things I'm not seeing in the code you posted.

    (1) In viewDidLoad I check for purchases and store it:

    func fetchAvailableProducts()  {
        productsRequest = SKProductsRequest(productIdentifiers: productIdentifiers as! Set<String>)
        productsRequest.delegate = self
        productsRequest.start()
    }
    
    public func productsRequest (_ request:SKProductsRequest, didReceive response:SKProductsResponse) {
        if (response.products.count > 0) {
            iapProducts = response.products
        }
    }
    

    Of note is setting the view controller as a delegate - something I don't see in your code. (The logic sounds good though.)

    (2) My restore purchases has an extra line of code:

    func restorePurchases() {
        SKPaymentQueue.default().add(self)
        SKPaymentQueue.default().restoreCompletedTransactions()
    }