Transaction comes back after finishTransaction: has been called on it

后端 未结 10 1117
一个人的身影
一个人的身影 2020-12-08 15:06

I am using in-app purchase for an iPhone app. I have a class that acts as SKProductsRequestDelegate and SKPaymentTransactionObserver, and it\'s all

相关标签:
10条回答
  • 2020-12-08 15:42

    I have not delved deeply into this, but I was seeing my calls to finishTransaction reliably failing in iOS 4. On a hunch I put the call to finishTransaction in a dispatch_async call and the problem went away.

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
      [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
    });
    

    Perhaps a salient point is I was calling finishTransaction from within a block which ultimately ran after a network call to my server.

    0 讨论(0)
  • 2020-12-08 15:42

    It's possibly caused by multiple observers. Don't think you're safe by just removing observer in dealloc.

    You called [[SKPaymentQueue defaultQueue] addTransactionObserver:self] in viewDidLoad and [[SKPaymentQueue defaultQueue] removeTransactionObserver:self] in dealloc. You think you're safe like I did but you're not.

    Actually, if you purchase something, finish transaction, remove it from payment queue, pop out this view controller from navigation view controller, then you enter the view controller again, you're probably have multiple transaction observers.

    Every time you push this view controller you're adding the view controller itself as transactionObserver but every time you pop this view controller doesn't guarantee that you're removing the view controller itself from transactionObservers.

    Somehow a view controller's dealloc not get called even if you pop the view controller. So the view controller is still observing in the dark.

    I think the best solution for this situation is detecting if this view controller is visible when you process the transaction.

    Simply add this before you process the transaction, it works for me:

    if ( !self.view.window) {
        return;
    }
    

    visible detection is referenced from here.


    ps. Maybe put/remove transactionObserver in viewWillAppear/viewWillDisappear is another way to solve that, but you have to carefully handle the keyboard show/hide events in case the user needs type password.

    0 讨论(0)
  • 2020-12-08 15:49

    I was having the EXACT same issue.

    Based on the answers, I did some experiments and found that if I hold a reference to the Queue, the problem went away.

    For example:

    // myStoreManagerClass.h
    ...
    SKPaymentQueue *_myQueue;
    ...

    //myStoreManagerClass.m
    ...
    if(_myQueue == nil) {
    _myQueue = [[SKPaymentQueue defaultQueue];
    }
    ...

    I then made sure that all my methods used my instance variable reference. Since doing that, the issue has cleared up.

    0 讨论(0)
  • 2020-12-08 15:50

    That problem happened to me as well, I found the a solution. That may help you in similar cases.

    I was calling finishTransaction immediately but next time when I try to buy something, the previous product was coming as well! So at first time, I was buying one product. But at second time, I was buying the second product and the first product too.

    I found out that I'm adding SKPaymentTransactionObserver multiple times! That was causing the problem, making multiple buys.

    When the process ends, I mean when you call finishTransaction, right after that, call: [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];

    That will clear out transactions and remove the observer. So next time, you won't make multiple buys.

    0 讨论(0)
提交回复
热议问题