InApp Purchase SKPaymentQueue finish Transaction doesn't work

13,230

Solution 1

i got solution your problem is addTransaction server duplicate to your issue,

try below code it's must working:

static bool hasAddObserver=NO;

- (void)purchase {
    if (!hasAddObserver) {//flag to fix this bug
        /*=====================================*/
        [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
        hasAddObserver=YES;
    }
    SKPayment *payment = [SKPayment paymentWithProductIdentifier:@"com.test"];
    //[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    [[SKPaymentQueue defaultQueue] addPayment:payment];

}


- (void)provideContent:(NSString *)productIdentifier {

    NSLog(@"Toggling flag for: %@", productIdentifier);
    [[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:productIdentifier];
    [[NSUserDefaults standardUserDefaults] synchronize];
    //[_purchasedProducts addObject:productIdentifier];

    [[NSNotificationCenter defaultCenter] postNotificationName:kProductPurchasedNotification object:productIdentifier];

}

- (void)completeTransaction:(SKPaymentTransaction *)transaction {

    NSLog(@"completeTransaction...");

    //[self recordTransaction: transaction];
    [self provideContent: transaction.payment.productIdentifier];
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];

}

- (void)restoreTransaction:(SKPaymentTransaction *)transaction {

    NSLog(@"restoreTransaction...");

    //[self recordTransaction: transaction];
    [self provideContent: transaction.originalTransaction.payment.productIdentifier];
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];

}

- (void)failedTransaction:(SKPaymentTransaction *)transaction {

    if (transaction.error.code != SKErrorPaymentCancelled)
    {
        NSLog(@"Transaction error: %@", transaction.error.localizedDescription);
    }




    [[NSNotificationCenter defaultCenter] postNotificationName:kProductPurchaseFailedNotification object:transaction];


    //[[NSNotificationCenter defaultCenter] postNotificationName:@"NotificationName" object:transaction];

    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];

}



- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {

    for (SKPaymentTransaction *transaction in transactions) {

        switch (transaction.transactionState) {

            case SKPaymentTransactionStatePurchasing:

                break;

            case SKPaymentTransactionStatePurchased:
                //[self completeTransaction:transaction];
                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];

                break;

            case SKPaymentTransactionStateRestored:
                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                //[self restoreTransaction:transaction];

                break;

            case SKPaymentTransactionStateFailed:
                if (transaction.error.code != SKErrorPaymentCancelled) {
                    NSLog(@"An error encounterd");
                }
                else {
                    NSLog(@"Cancelled!");
                }
                //[[SKPaymentQueue defaultQueue] finishTransaction:transaction];

                [self failedTransaction:transaction];

                break;

        }

    }

}

- (void)dealloc
{
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];

    [request release];
    [super dealloc];

}

Welcome!

Solution 2

To fix this problem just add [[SKPaymentQueue defaultQueue]removeTransactionObserver:self]; right after [[SKPaymentQueue defaultQueue] finishTransaction:transaction];

Share:
13,230
Dinesh
Author by

Dinesh

Updated on June 15, 2022

Comments

  • Dinesh
    Dinesh almost 2 years

    i am working inapp purchase project in iOS sdk.i have prepared inapp purchase class for purchasing app from appstore with enable inner contents of the project.but, my problem is SKPaymentQueue doesn't finish working on my class.here's code of my inapp purchase class:

    - (void)purchase {
        [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
        SKPayment *payment = [SKPayment paymentWithProductIdentifier:@"com.test"];
        [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
        [[SKPaymentQueue defaultQueue] addPayment:payment];
    
    }
    
    - (void)provideContent:(NSString *)productIdentifier {
    
        NSLog(@"Toggling flag for: %@", productIdentifier);
        [[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:productIdentifier];
        [[NSUserDefaults standardUserDefaults] synchronize];
        //[_purchasedProducts addObject:productIdentifier];
    
        [[NSNotificationCenter defaultCenter] postNotificationName:kProductPurchasedNotification object:productIdentifier];
    
    }
    
    - (void)completeTransaction:(SKPaymentTransaction *)transaction {
    
        NSLog(@"completeTransaction...");
    
        //[self recordTransaction: transaction];
        [self provideContent: transaction.payment.productIdentifier];
        [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
    
    }
    
    - (void)restoreTransaction:(SKPaymentTransaction *)transaction {
    
        NSLog(@"restoreTransaction...");
    
        //[self recordTransaction: transaction];
        [self provideContent: transaction.originalTransaction.payment.productIdentifier];
        [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
    
    }
    
    - (void)failedTransaction:(SKPaymentTransaction *)transaction {
    
        if (transaction.error.code != SKErrorPaymentCancelled)
        {
            NSLog(@"Transaction error: %@", transaction.error.localizedDescription);
        }
    
    
        [[NSNotificationCenter defaultCenter] removeObserver:self name:kProductPurchaseFailedNotification object:transaction];
    
    
        [[NSNotificationCenter defaultCenter] postNotificationName:kProductPurchaseFailedNotification object:transaction];
    
    
        //[[NSNotificationCenter defaultCenter] postNotificationName:@"NotificationName" object:transaction];
    
        [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
    
    }
    
    
    
    - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
    
        for (SKPaymentTransaction *transaction in transactions) {
    
            switch (transaction.transactionState) {
    
                case SKPaymentTransactionStatePurchasing:
    
                    break;
    
                case SKPaymentTransactionStatePurchased:
                    [self completeTransaction:transaction];
                    //[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
    
                    break;
    
                case SKPaymentTransactionStateRestored:
                    //[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                    [self restoreTransaction:transaction];
    
                    break;
    
                case SKPaymentTransactionStateFailed:
                    if (transaction.error.code != SKErrorPaymentCancelled) {
                        NSLog(@"An error encounterd");
                    }
                    else {
                        NSLog(@"Cancelled!");
                    }
                    //[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
    
                    [self failedTransaction:transaction];
    
                    break;
    
            }
    
        }
    
    }
    
    - (void)dealloc
    {
        [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
    
        [request release];
        [super dealloc];
    
    }
    

    that's line doesn't work on my class [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; transaction doesn't finish. and my another problem is nsnotificationcenter calls multiple times like if i click first time it's call only one time no problem,another time it's nsnotificationcenter calls 3 times.