6

I got serious problem i am working on In app purchase and when i try to purchase first time it works fine and for the second time my completeTransaction called two times.. I dont know why i got this issue.

After i got receipt i call my verification method and if verify Okay than server send me audio file in http responce and i downlaod that and when i successfully download file i call finishtransaction.

Here is my code

- (void)startPurchase {
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
if([SKPaymentQueue canMakePayments]) {
    NSLog(@"IN-APP:can make payments");
    SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers: [NSSet setWithObject:myIdentifier]];
    request.delegate = self;
      NSLog(@"** Productdata is ** %@",myIdentifier);
    [request start];

}
else {
    NSLog(@"IN-APP:can't make payments");
    loadingHUD.hidden=YES;
}
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {

NSLog(@"IN productsRequest END %d",[response.products count]);

@try {
    SKProduct *product = [response.products objectAtIndex:0];
    SKPayment *newPayment = [SKPayment paymentWithProduct:product];
    [[SKPaymentQueue defaultQueue] addPayment:newPayment];
    NSLog(@"IN-APP:productsRequest END");

    loadingHUD.hidden=YES; // Hide the Loading progress bar 

}

@catch (NSException *exception) {

    // Failed to purchase Hide the progress bar and Display Error Dialog
    loadingHUD.hidden=YES;
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"error" message:@"Errror " delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alertView show];

}
}

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
 {
for (SKPaymentTransaction *transaction in transactions)
{
    switch (transaction.transactionState)
    {
        case SKPaymentTransactionStatePurchased:
            [self completeTransaction:transaction];
            break;
        case SKPaymentTransactionStateFailed:
            [self failedTransaction:transaction];
            break;
        case SKPaymentTransactionStateRestored:
            [self restoreTransaction:transaction];
        default:
            break;
    }
  }
  }
 - (void) completeTransaction: (SKPaymentTransaction *)transaction
   {
  NSLog(@"Transaction Completed");
// Finally, remove the transaction from the payment queue.
 [self verifyReceipt:transaction]; // Call the verifyReceipt method to send transaction.bytes
// [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
 NSLog(@"Purchase Transaction finish");

 }

In VerifyTransaction method in download success block i call finish transaction

[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
 {

      [[SKPaymentQueue defaultQueue] finishTransaction: transaction]; // Finish the transaction

    // NSLog(@"Successfully downloaded file to %@",[[NSString alloc] initWithData:operation.responseData encoding:NSASCIIStringEncoding]);

     // Give alert that downloading successful.
     NSLog(@"Successfully downloaded file to %@", destPath);

    // NSLog(@"response: %@", operation.responseString);  // Give alert that downloading successful.

     // [self.target parserDidDownloadItem:destPath];

     //loadingHUD.detailsLabelText = [NSString stringWithFormat:@"%@ %i%%",@"Downloading",100];
     [loadingHUD hide:TRUE];

     [DBHelper savePurchaseId:fileName]; // save the purchase itune id into local database to populate hover image of play button on main List
     [self movieReceived];

 }

2 Answers2

8

its Look like your Observer queue still contain Older product id

- (void)paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray *)transactions
{
    NSLog(@"Purchase removedTransactions");

    // Release the transaction observer since transaction is finished/removed.
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}

To remove product id once you finish your transaction.

Natan R.
  • 5,141
  • 1
  • 31
  • 48
Swap-IOS-Android
  • 4,363
  • 6
  • 49
  • 77
  • this delegate is not calling for me – dineshprasanna Nov 21 '14 at 13:03
  • How does this work with processing subsequent transactions? My understanding is that when you reinstate the transaction observer for any following purchases it will update with the existing queue for the user in the App Store. Therefore, this seems like it's only a temporary fix. – Max Phillips Apr 13 '16 at 16:09
  • It's strange to remove transaction observer when any random transaction can be removed off the queue.. – pronebird Dec 11 '17 at 12:37
1

I ended up doing the following:

if(contains(self.transactions, trans.transactionIdentifier) == false) {
    self.transactions.append(trans.transactionIdentifier)
    //Give the user the purchased product
}

Removing the observers somewhat relieved the problem but I still had occasional double-calls going through when I "spammed" the purchase button in the app. The solution above completely resolved it though and seems very robust in my testing.

beetree
  • 871
  • 2
  • 8
  • 18