Sandbox试图恢复耗材IAP

时间:2015-03-24 23:38:22

标签: ios objective-c in-app-purchase

我一直在尝试在iOS上测试一些耗材IAP,我收到一个奇怪的错误。弹出一个警告:

  

“此应用程序内购买已经被购买。它将被恢复   自由。 [环境:沙箱]“

我已经检查过了,我确定我的IAP可以在iTunesConnect中使用。似乎我的验证过程以某种方式失败,但我不希望这个错误消息。有没有人有这方面的经验?

3 个答案:

答案 0 :(得分:8)

我不确定这是否是正确的操作,但是请致电:

[[SKPaymentQueue defaultQueue] finishTransaction: transaction];

重复交易清除了它们。我怀疑,由于在调试器中停止了,我从未在成功案例中调用它。

答案 1 :(得分:6)

可能你已经解决了你的问题,但我遇到了同样的问题,并有一些额外的解决方案点:

抱歉,我使用Swift,但我认为这是可以理解的。

首先,您的代码中有两个重要时刻,您必须涵盖这些时刻:

class InAppPurchaseViewController: UIViewController ,  SKProductsRequestDelegate
, SKPaymentTransactionObserver //NOTE THIS!
{
 override func viewDidLoad() {
    super.viewDidLoad()
    //
    ...
    ...
    SKPaymentQueue.defaultQueue().addTransactionObserver(self)
    // here you create the observer
} 

//before you leave this ViewController you should delete this Observer.
//I had a bug which worked like this: when user leaved the IAPViewController without 
//buying something and then came back, viewDidLoad added one more Observer
// so App crashed on the attempt to buy
// for example:

@IBAction func exitTapped(sender: AnyObject) {    
    dismissViewControllerAnimated(true) { () -> Void in
        SKPaymentQueue.defaultQueue().removeTransactionObserver(self)
    }
}

添加观察者后,不要忘记完成交易:

func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
    for transaction in transactions {  
        switch transaction.transactionState {
        case .Restored:
            print("Restored")
            break
        case .Failed:
            print("Failed") 
        //FINISH TRANSACTION 
            SKPaymentQueue.defaultQueue().finishTransaction(transaction)
            break
        case .Purchasing:
            print("Purchasing")
            break
        case .Purchased:
        // DO your stuff here
        // ...
        // and FINISH TRANSACTION
           SKPaymentQueue.defaultQueue().finishTransaction(transaction)
            }
            break
        case .Deferred:
            print("Deferred")
            break
        }
    }
}

我在这里解决的另一个问题是:我忘了添加完成交易代码行,所以我使用耗材IAP打开了交易。

当我尝试再次使用此Sandbox用户购买时,我收到消息“此应用内购买已经被购买。它将免费恢复。[环境:沙箱]”即使我添加了FinishTransaction,这也一次又一次地发生。我更改了沙盒用户。应用程序每次运行应用程序时都会提示FirstSandBoxUser iTunes密码。灾难......非常烦人......

每当我尝试使用FirstSandBoxUser进行此次购买时,transaction.transactionState为.Purchasing,您无法在此状态下完成交易

我做了一个假设,即如果事务没有完成,StoreKit就像非消耗品一样,所以我应该开始恢复过程,然后抓紧时间完成交易。这是代码:

func paymentQueue // see above
//....
case .Purchasing:
    print("Purchasing")
    SKPaymentQueue.defaultQueue().restoreCompletedTransactions()
    break
//...
}

func paymentQueueRestoreCompletedTransactionsFinished(queue: SKPaymentQueue) {
    for transaction in queue.transactions {
        queue.finishTransaction(transaction)
    }
}

一旦运行此代码就足够了,我认为它将捕获所有“采购”事务,恢复它们并在完成之后。

当然,在解决问题后,请删除此附加代码。

祝你好运!

答案 2 :(得分:0)

当使用。

在客户端上未完成交易时,会发生这种情况
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];

您应该在应用启动阶段注册transactionObserver,以确保您收到任何未完成的交易的通知。您应该完成这些交易并执行将所购买的产品正确交付给用户所需的任何其他事项。

From apples programming guide(强调我的):

  

在启动应用程序时注册事务队列观察器,如清单5-1所示。确保观察者随时准备好处理事务,而不仅仅是在将事务添加到队列之后。例如,考虑用户在进入隧道之前在您的应用中购买商品的情况。您的应用无法提供已购买的内容,因为没有网络连接。 下次启动您的应用时,StoreKit会再次调用您的事务队列观察器,并在此时提供所购买的内容。同样,如果您的应用无法将交易标记为已完成,则StoreKit会在您的应用每次启动时调用观察者,直到交易正确完成

他们建议使用以下代码注册观察者:

- (BOOL)application:(UIApplication *)application
 didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    /* ... */

    [[SKPaymentQueue defaultQueue] addTransactionObserver:observer];
}