I am trying to perform an in-app purchase, but it fails, and i cannot figure out why. The weird thing is, that it fetches the SKProduct just fine and can print all the details, but when i actually try to buy it, it just fails.
Now, since i know the product gets fetched and logs to the console, the problem is not with that. The problem lies when i try to actually purchase the fetched product, so here is the code for that:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
// Setup notifaction to handle the successfull payment
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(succeedPayment)
name:@"kInAppPurchaseManagerTransactionSucceededNotification"
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(failedPayment)
name:@"kInAppPurchaseManagerTransactionFailedNotification"
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(cancelPayment)
name:@"userCancel"
object:nil];
}
- (IBAction)purchase10Crystals:(id)sender {
InAppPurchaseManager *p = [InAppPurchaseManager IAPManager];
if ([p canMakePurchases]) {
[p purchaseGoldCoins:10];
NSLog(@"Buying 10 crystals");
}
}
So there i have the View Controller listen to notifications regarding payment, and to actually make a payment. Here is what happens inside the InAppPurchaseManager:
SKPayment *payment = [SKPayment paymentWithProduct:gold10];
[[SKPaymentQueue defaultQueue] addPayment:payment];
Now the purchase is sent to the store. The manager waits for a respond, and these are the options:
//
// removes the transaction from the queue and posts a notification with the transaction result
//
- (void)finishTransaction:(SKPaymentTransaction *)transaction wasSuccessful:(BOOL)wasSuccessful
{
// remove the transaction from the payment queue.
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:transaction, @"transaction" , nil];
if (wasSuccessful)
{
// send out a notification that we’ve finished the transaction
[[NSNotificationCenter defaultCenter] postNotificationName:kInAppPurchaseManagerTransactionSucceededNotification object:self userInfo:userInfo];
NSLog(@"Success transaction!");
}
else
{
// send out a notification for the failed transaction
[[NSNotificationCenter defaultCenter] postNotificationName:kInAppPurchaseManagerTransactionFailedNotification object:self userInfo:userInfo];
}
}
//
// called when the transaction was successful
//
- (void)completeTransaction:(SKPaymentTransaction *)transaction
{
[self recordTransaction:transaction];
[self provideContent:transaction.payment.productIdentifier];
[self finishTransaction:transaction wasSuccessful:YES];
}
//
// called when a transaction has been restored and and successfully completed
//
- (void)restoreTransaction:(SKPaymentTransaction *)transaction
{
[self recordTransaction:transaction.originalTransaction];
[self provideContent:transaction.originalTransaction.payment.productIdentifier];
[self finishTransaction:transaction wasSuccessful:YES];
}
//
// called when a transaction has failed
//
- (void)failedTransaction:(SKPaymentTransaction *)transaction
{
if (transaction.error.code != SKErrorPaymentCancelled)
{
// error!
NSLog(@"Failed: %li", (long)transaction.error);
[self finishTransaction:transaction wasSuccessful:NO];
}
else
{
// this is fine, the user just cancelled, so don’t notify
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
[[NSNotificationCenter defaultCenter] postNotificationName:@"userCancel" object:self userInfo:nil];
}
}
The method that gets called is failedTransaction. I have no idea why. The sandbox account is working because it can play on game center for testing. The product gets fetched because it prints it all out. But when i try to purchase, it just fails, and doesn't tell me why. The code that gets logged out is just a lot of numbers.
Hope anyone can help me. Best Regards /JBJ
EDIT This is how i fetch the SKProducts.
First i call this to load it up
- (void)loadStore
{ // restarts any purchases if they were interrupted last time the app was open [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
// get the product description (defined in early sections) [self request10GoldData];
}
Fetch the Product from the store
-(void) request10GoldData
{ NSSet *productIdentifiers = [NSSet setWithObject:@"10crystals" ]; productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers]; productsRequest.delegate = self; [productsRequest start]; }
Print it out to verify it was fetched
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{ // Make a new SKProduct, identify which product it is, and add to proper instance variable
NSArray *products = response.products; SKProduct *theProduct = [products count] == 1 ? [products objectAtIndex:0] : nil; if (theProduct) { // Identify the product and assign to instance variable SKProducts if ([theProduct.productIdentifier isEqualToString:@"10crystals"]) { gold10 = theProduct; } // Debugging NSLog(@"Product title: %@" , theProduct.localizedTitle); NSLog(@"Product description: %@" , theProduct.localizedDescription); NSLog(@"Product price: %@" , theProduct.price); NSLog(@"Product id: %@" , theProduct.productIdentifier); } for (NSString *invalidProductId in response.invalidProductIdentifiers) { NSLog(@"Invalid product id: %@" , invalidProductId); } [[NSNotificationCenter defaultCenter] postNotificationName:kInAppPurchaseManagerProductsFetchedNotification object:self userInfo:nil];
}
This works, and in the above NSLog statements it prints out exactly what i created in iTunes connect.