2015-03-24 3 views
4

Я пытаюсь протестировать некоторые расходные IAP на iOS, и я получаю странную ошибку. Появляется предупреждение с текстом: «Эта покупка в приложении уже куплена, она будет восстановлена ​​бесплатно. [Environment: Sandbox]».Песочница пытается восстановить расходуемые IAP

Я проверил, и я уверен, что мой IAP расходуется в iTunesConnect. Похоже, что мой процесс проверки как-то не работает, но я не ожидал бы этого сообщения об ошибке. У кого-нибудь есть опыт?

+0

Похоже, у меня такой же вопрос. Вы исправились? – Vladius

+0

Я тоже сталкиваюсь с той же проблемой. Вы нашли какие-либо решения для этого? –

ответ

7

Я не уверен, если это правильное действие, но называть:

[[SKPaymentQueue defaultQueue] finishTransaction: transaction]; 

на повторяющейся операции очистили их. Я подозреваю, что я никогда не называл это в случае успеха из-за остановки в отладчике или чем-то еще.

4

Вероятно, вы решили проблему уже, но я встретил тот же вопрос, и есть некоторые дополнительные пункты решения:

К сожалению, я использую 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, я получил сообщение «Эта покупка в приложении уже куплена, она будет восстановлена ​​бесплатно. [Environment: 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) 
    } 
} 

Этого достаточно, чтобы запустить этот код один раз, я думаю, он будет ловить все «Снабжение» сделки, их восстановление и после этого Finish.

Конечно, после устранения проблемы удалите этот дополнительный код.

Удачи вам!

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]; 
} 
Смежные вопросы