This is a follow-up question to "In app purchases with MKStoreKit failing: “Problem in iTunes connect configuration for product: xxx"
I am having a similar issue and have tried to do both with and without MKStoreKit and get a similar message.
Check-list
With thanks to: http://troybrant.net/blog/2010/01/invalid-product-ids/
Have you enabled In-App Purchases for your App ID?
YES
Have you checked Cleared for Sale for your product?
YES
Have you submitted (and optionally rejected) your application binary?
YES
Does your project’s .plist Bundle ID match your App ID?
YES
Have you generated and installed a new provisioning profile for the new App ID?
YES
Have you configured your project to code sign using this new provisioning profile?
YES
Are you building for iPhone OS 3.0 or above?
YES. iOS4.2 and up.
Are you using the full product ID when when making an SKProductRequest?
YES. Also just the product ID itself without the reverse domain
Have you waited several hours since adding your product to iTunes Connect?
YES. It says "Waiting for review" and has done for the past 4-5 days
Are your bank details active on iTunes Connect?
NO. It is a client project and am only testing to see if it is working. Do I need bank details to test it?
EDIT: I have changed this now. But I do not see why I need to do this just to test sandboxing.
Have you tried deleting the app from your device and reinstalling?
YES
Is your device jailbroken?
NO
App notation is correct
Some examples I have seen use this notation: com.domain.APP_ID.PRODUCT_TO_BUY
But others use com.domain.PRODUCT_TO_BUY
Which is right?
In my code I have attempted using the full notation and just the product ID itself but still get the same problem of "Invalid product id".
Developer rejected
App Bundle (Release) is on iTunes Connect and I have "developer rejected" the bundle.
Picture:
Waiting for review?
In my in-app purchases I have the 1 product, an auto-renewable subscription. It is cleared for sale; it is however "Waiting for review" and is not green-lit.
Picture:
I created this almost 4-5 days ago and its still flagged as "Waiting for review"??
I am wondering if my app has been "developer rejected" whether this has an impact on "Waiting for review" on an auto-renewable subscription?
I have not changed anything in this item.
According to the various articles I have to wait 24-48 hours before I can use it?
But do I need to wait for this to be accepted or green-lit before I can use it in my testing?
Bank details
I have not filled in any bank details because this is an app for a client -- Do I need to fill in bank details before I can continue testing it?
According to these docs: http://developer.apple.com/library/ios/#technotes/tn2259/_index.html bank details are required?
Do I need to be logged into iTunes on my device under a test account before running the app?
I am wondering if someone can clarify these issues? Maybe its just as simple as waiting for the in-app purchase to be "green lit", or perhaps I've missed a step?
Note: This happens regardless of whether I use MKStoreKit or use the code that follows.
Thanks.
My code (this is the non MKStoreKit version)
#define kMySubscriptionFeature @"uk.co.samplewebsite.myappproject.sub1"
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.title = @"Manage Subscriptions";
if ([SKPaymentQueue canMakePayments])
{
// Display a store to the user.
//[MKStoreManager sharedManager];
//NSLog(@"purhcasable = %@", [[MKStoreManager sharedManager] purchasableObjectsDescription] );
[self requestProUpgradeProductData];
}
else
{
// Warn the user that purchases are disabled.
NSString *message = @"In-app purchases are disabled. Please review your settings";
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error" message:message delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
[alertView release];
} // end if
}
#pragma mark - StoreKit Delegate
- (void) requestProductData
{
SKProductsRequest *request= [[SKProductsRequest alloc] initWithProductIdentifiers: [NSSet setWithObject:kMySubscriptionFeature]];
request.delegate = self;
[request start];
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSArray *myProduct = [[NSArray alloc] initWithArray:response.products];
for(SKProduct *item in myProduct)
{
NSLog(@"Product title: %@" , item.localizedTitle);
NSLog(@"Product description: %@" , item.localizedDescription);
NSLog(@"Product price: %@" , item.price);
NSLog(@"Product id: %@" , item.productIdentifier);
}
for (NSString *invalidProductId in response.invalidProductIdentifiers)
{
NSLog(@"Problem in iTunes connect configuration for product: %@" , invalidProductId);
}
[myProduct release];
// populate UI
[request autorelease];
}
Edit:
As a failsafe, I've added bank details just in case, but I don't see why this would cause an issue.
I've also made sure I uploaded and rejected the app release bundle and not the adhoc one; though I do not know if this makes any difference.
After 2 days of waiting, new app ids, profiles, etc. this fixed it for me..
Why do the docs say to use the full com.iap.isrubbish syntax?
Thanks for your help
I replaced:
define kMySubscriptionFeature @"uk.co.somesite.someapp.sub1"
with:
define kMySubscriptionFeature @"sub1"
I think I've done it now. I'm going to run some tests just to make sure.
This is not going to be accepted just yet; I am running some tests with different storekit frameworks.
My output:
2011-10-27 15:17:49.297 My Simple App[7376:707] productsRequest
2011-10-27 15:17:49.298 My Simple App[7376:707] Product title: Simple subscription
2011-10-27 15:17:49.299 My Simple App[7376:707] Product description: Subscribe and get the latest content to your iPhone or iPod Touch device
2011-10-27 15:17:49.299 My Simple App[7376:707] Product price: 2.99
2011-10-27 15:17:49.300 My Simple App[7376:707] Product id: sub1
Here's what I did.
I added my bank details. I still do not think this has anything to do with it though.
Note. The app's in-app purchase is still "Waiting for review" and I got the above output.
I replaced:
#define kMySubscriptionFeature @"uk.co.somesite.someapp.sub1"
with:
#define kMySubscriptionFeature @"sub1"
I am going to run some tests with MKStoreKit and with other frameworks to see if it is okay.
The code I used is below, edited for security reasons:
.h file
// ManageSubscriptionsVC.h
// This doesn't have visual output, just NSLog at the moment
// This doesn't use MKStoreKit yet
#import <UIKit/UIKit.h>
#import "StoreKit/StoreKit.h"
#define kMySubscriptionFeature @"sub1"
/*
Shared Secret
A shared secret is a unique code that you should use when you make the
call to our servers for your In-App Purchase receipts.
Without a shared secret, you will not be able to test auto-renewable
In-App Purchase subscriptions in the sandbox mode.
Also note that you will not be able to make them available
on the App Store.
Note: Regardless of what app they are associated with,
all of your auto-renewable subscriptions will use this
same shared secret.
*/
#define sharedSecret @"PUTSHAREDSECRETHERE"
@interface ManageSubscriptionsVC : UIViewController
<SKProductsRequestDelegate, SKProductsRequestDelegate, SKPaymentTransactionObserver>
{
SKProduct *proUpgradeProduct;
SKProductsRequest *productsRequest;
}
- (void)requestProUpgradeProductData;
@end
.m file
//
// ManageSubscriptionsVC.m
#import "ManageSubscriptionsVC.h"
@implementation ManageSubscriptionsVC
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.title = @"Manage Subscriptions";
if ([SKPaymentQueue canMakePayments])
{
// Display a store to the user.
//[MKStoreManager sharedManager];
//NSLog(@"purhcasable = %@", [[MKStoreManager sharedManager] purchasableObjectsDescription] );
[self requestProUpgradeProductData];
}
else
{
// Warn the user that purchases are disabled.
NSString *message = @"In-app purchases are disabled. Please review your settings";
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error" message:message delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
[alertView release];
} // end if
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - StoreKit Delegate
- (void) requestProductData
{
NSLog(@"requestProductData");
SKProductsRequest *request= [[SKProductsRequest alloc] initWithProductIdentifiers: [NSSet setWithObject:kMySubscriptionFeature]];
request.delegate = self;
[request start];
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSLog(@"productsRequest");
NSArray *myProduct = [[NSArray alloc] initWithArray:response.products];
for(SKProduct *item in myProduct)
{
NSLog(@"Product title: %@" , item.localizedTitle);
NSLog(@"Product description: %@" , item.localizedDescription);
NSLog(@"Product price: %@" , item.price);
NSLog(@"Product id: %@" , item.productIdentifier);
}
/*
for(NSString *invalidProduct in response.invalidProductIdentifiers)
NSLog(@"Problem in iTunes connect configuration for product: %@", invalidProduct);
*/
for (NSString *invalidProductId in response.invalidProductIdentifiers)
{
NSLog(@"Problem in iTunes connect configuration for product: %@" , invalidProductId);
}
[myProduct release];
// populate UI
[request autorelease];
}
#pragma mark - PaymentQueue
-(void)paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray *)transactions
{
}
-(void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error
{
}
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
}
-(void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
{
}
#pragma mark - Other
- (void)requestProUpgradeProductData
{
NSSet *productIdentifiers = [NSSet setWithObject:kMySubscriptionFeature];
productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
productsRequest.delegate = self;
[productsRequest start];
// we will release the request object in the delegate callback
}
@end
I just found out that I swapped the product ID and the reference name when I created the in app purchase, so in my case I was using the wrong string to try and find the Product... Hard to spot.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With