Reputation:
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];
}
Upvotes: 6
Views: 3731
Reputation: 941
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.
Upvotes: 1
Reputation: 4383
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.
Upvotes: 8