首页 文章

Sandbox试图恢复耗材IAP

提问于
浏览
5

我一直在尝试在iOS上测试一些可消耗的IAP,而且我遇到了一个奇怪的错误 . 弹出一个警告:

“此应用内购买已经被购买 . 它将免费恢复 . [环境:沙箱]”

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

3 回答

  • 7

    我不确定这是否是正确的操作,但是要求:

    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
    

    在重复交易清除了他们 . 我怀疑,由于停在调试器或其他东西,我从未在成功案例中调用它 .

  • 0

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

    对不起,我使用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用户时,我收到了消息 "This In-App Purchase has already been bought. It will be restored for free. [Environment: Sandbox]" 即使在我添加了FinishTransaction之后,这也一再发生 . 我更改了沙盒用户 . 应用程序每次运行应用程序时都会提示FirstSandBoxUser iTunes密码 . 灾难......非常烦人......

    每次我尝试使用FirstSandBoxUser进行此次购买时,transaction.transactionState都是.Purchasing和 you can't finish the transaction in this state

    我做了一个假设,如果事务没有完成,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)
        }
    }
    

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

    当然,修复问题后删除此附加代码 .

    祝好运!

  • 5

    在客户端使用时未完成事务时会发生这种情况 .

    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
    

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

    From apples programming guide(强调我的):

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

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

    - (BOOL)application:(UIApplication *)application
     didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        /* ... */
    
        [[SKPaymentQueue defaultQueue] addTransactionObserver:observer];
    }
    

相关问题