I am developing an application and using in-app purchases in it. i have created in-app products in iTunes Connect. till yesterday everything was working fine. but today. it started giving this error.
"Error: Payment requests are restricted to products returned as valid via Store Kit's didRecieveResponse method."
i have no idea what is the issue. please reply
Ok, This may be the smoking gun --
According to the official dataflow from the Store Kit apps, you are supposed to retrieve information about the available purchases (SKProductsRequest) before trying to make a purchase (SKPaymentQueue).
I added code to do just that, even though the localized data wasn't being used. I made the call, verified the item was present, and just dumped an NSLOG about it.
The purchase went through, with no errors!
I then removed the code that called SKProductsRequest, and re-ran it, and got the "Payment requests are restricted..." error message.
It almost seems like the store kit framework was changed in such a way as to REQUIRE you to make a call to SKProductsRequest, in order for purchases to behave correctly when tehy are added to SKPaymentQueue.
In computer science speak, they seem to have introduced a hard dependence between the two logically related, but separate modules. This is a REALLY bad practice.
Try adding this code into your app, and call dumpProductInfo at some point prior to making "real" calls to SKPaymentQueue and see if it starts working -- be sure to update the embedded string literal with your actual product identifier(s).
-(void) dumpProductInfo
{
SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:#"com.company.domain.app.purchase"]];
request.delegate = self;
[request start];
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSArray *myProduct = response.products;
// populate UI
NSLog(#"Products:");
for (int i = 0; i < [myProduct count]; i++)
{
SKProduct *product = [myProduct objectAtIndex:i];
NSLog(#"Name: %# - Price: %f ID: %#" ,
[product localizedTitle],
[[product price] doubleValue],
[product productIdentifier]);
}
}
Follow-up: as mentioned below, Apple Technical Note QA1691 confirms that what I thought was happening was correct -- two weeks after we figured it out :p
I suddenly started getting this also! The last time I tested the purchase code was the end of last week, and it was working fine then!
I even used a previous version to test, in order to ensure that no code changes were responsible. This version was working, and had been submitted to the store.
Something is definitely changed, and it appears to be from the app store side of things!
I will note that the "official" data flow for the store requires the app to retrieve the list of products available for purchase but I instead hard-coded the identifier once the purchase was defined in iTunes Connect. I checked if the purchase ID has changed and the answer there is that it hasn't.
To make this more confusing, I pulled the live app build down from iTunes, and the purchase went through fine. The differences between the two scenarios are
1. one was built using my development profile instead of deployment profile
2. one was running in the sandbox instead of "real"
3. one used a test account to do the purchase
To ensure it wasn't a bad test account, I just now created a new one and tried to test with it. It made no difference.
UPDATE -- I emailed Apple regarding this, received no reply (yet) but the error suddenly went away and everything started working as expected!?!
Here's my theory regarding what's happening from my recent testing of IAPs for a new App:
The sandbox IAP env does NOT allow you to test IAP anymore AFTER you've approved and submitted it for review. This is a new undocumented behavior as far as I can tell that is causing many headaches for us iPhone SDK monkeys. Before this change, you could have test IAPs even after submitting them for Apple review and before the App got approved.
So, in this case, even requesting the IAP store for valid product IDs will not help you out.
It appears that as part of the review process, Apple added the following automated test: invalidate ALL your IAP and test your App to ensure that you are sending a request for valid IAP IDs before populating your UI with IAP. So, if you do not address this with your code, your App will be rejected but they will tell you that requesting valid IDs is only a recommended best practice and not a required one but in my experience it is now required.
I hope this will save somebody some time - been spending hours on this and had to go through several Apps rejection until I figured it out and got working.
You have to have it build directly from xcode to have the sandbox work now apparently.
Related
It has been a long night chasing the problem within my in-app purchase trials yet I can not seem to solve this issue.My product identifier keeps returning as "invalid product identifier". Hopefully someone will point it out;
(With current provisioning profile and appId I got push notifications working)
My App ID is generated (with no wildcards) - inApp purchase is enabled
My IAP(In-App Purchase) is added in "Manage your in-app purchases" and cleared for sale.
My IAP is added 24 hours ago ( maybe couple of hours more) and is in "Waiting For Review" state
My App itself is developer rejected > and it is state "ready to upload", in-app purchase is added to the App.
My phone is not jailbroken (at least not anymore, didn't worked either way)
I am working with a 3GS, 5.1 iOS.
My current provisioning profile is a "Developer Profile" not a "Distribution Profile". "Distribution Profile" is used only while uploading the Application Binary.
I am building for iOS 5.0 and build configuration is set to Debug.
I deleted the app like 100 times now, literally.
All details are set in iTunes Connect, including bank details.
I have created a test user, and I logged in from "Settings > Store" on my device.
My SKProductRequest:
SKProductsRequest *productRequest = [[SKProductsRequest alloc]initWithProductIdentifiers:[NSSet setWithObject:#"com.my_site.my_app.my_product"]];
Any other information can be supplied.
I don't know how, and don't know will it remain valid. But here is the interesting solution which let me solve my problem.
According to the documentation, SKProductRequest should be;
SKProductsRequest *productRequest = [[SKProductsRequest alloc]initWithProductIdentifiers:[NSSet setWithObject:#"com.my_site.my_app.my_product"]];
Your product request should be like this;
com.my_site.my_app.my_product
but in my situation I just sent my product id, just like this and it WORKED;
SOLUTION #1
SKProductsRequest *productRequest = [[SKProductsRequest alloc]initWithProductIdentifiers:[NSSet setWithObject:#"my_product"]];
While digging in, I found that for some people this notation also worked;
SOLUTION #2
SKProductsRequest *productRequest = [[SKProductsRequest alloc]initWithProductIdentifiers:[NSSet setWithObjects:#"com.my_site.my_app","my_product",nil]];
There was nothing wrong with my setup, and the above listed things should be supplied, if anyone having problems with invalid product identifiers, I recommend them to visit Troy Brant's "Cause of Invalid Product ID's List", here . Also you can find his detailed walkthrough about implemeting and setting up IAP, here.
If you get desperate, I strongly recommend you to try both solutions, and they can save you from hours of frustration.
Please make sure you have not missed anything from below list.
Please remove the Existing application from the Device and Install
the fresh build from Xcode.
Have you enabled In-App Purchases for your App ID?
Does your project’s .plist Bundle ID match your App ID?
Have you generated and installed a new provisioning profile for the new App ID?
Have you configured your project to code sign using this new provisioning profile?
Are you using the full product ID when making a SKProductRequest?
Have you waited several hours since adding your product to iTunes Connect?
Are your bank details active on iTunes Connect?
Is your device jailbroken? If so, you need to revert the jailbreak for IAP to work.
If you answered No to any one of these questions, there’s your problem.
Please refer Reference
My paid applications agreement wasn't valid in iTunes Connect. As soon as I agreed to the new one, it fixed the problem.
In my case the problem was that I had previously created "StoreKit Configuration file" and then made change in Product Scheme:
Go to Product > Scheme > Edit Scheme and in Run/Debug tab under
Options I chose StoreKit configuration file.
Apparently this config was used instead of my App Store Connect IAP. So, the solution was to uncheck that option. You don't have to delete StoreKit Config file if you still need it for some reason.
You are using the latest provision profile right(which is downloaded after setting up in-app purchase).
Things ended up working for me:
I use Xcode automatic profiles and I got a bit confused on the app store connect webpage with the profile. I made sure ids matched on Xcode and on the webpage.
I just needed the product id, not the full com.company.app.product
took me like 2 hours to have things work, so maybe some refresh time on Apple's servers
Spends a couple of days at this. Here is what was missing from mine:
Make sure the BundleID in iTunes Connect matches that in your Xcode project.
I Have a strange problem with iphone in app purchase! i created a product in the ituneconnect and then (using MKstorekit) i bought the product in sandbox environment .. and everything went will the first time... i removed the app from the device and created another test account.
and i found in the debugger mode that it sees the product as already purchased !!
tried everything from cleaning the project and all the tricks for the cache problems.. but still the problem occure .. is that normal?? or i'm doing something wrong?
please advice
since you are deleting the app in that case there is no chance that NSUserDefault will be storing this purchase so only thing that comes to my mind is the type of purchase... what type of purchase did you state in itunesconnect consumable , non-consumable or subscription? it could be because you stated subscription as purchase type(subscription purchases can only be bought once)... hope this helps..
this is what I have come across at http://www.raywenderlich.com/2797/introduction-to-in-app-purchases
StoreKit will prompt the user “are you sure?”, ask them to enter their
username/password (if appropriate), make the charge, and send you a
success or failure. They’ll also handle the case where the user
already paid for the app and is just re-downloading it, and give you a
message for that as well.
I fount the solution..
in app delegate i have to call
- (BOOL) removeAllKeychainData
in MKStoreManager, call it once at beginning, and then remove it from code, you don't want to accidently leave that on release :S
Bug reported as fixed by Apple, see accepted answer below ...
UPDATE MON AUG 23rd 10:00 GMT
Although the bug report with apple hasn't been closed yet, it now seems to be working (at least for a couple of us) OK. It could be they have nailed it, or the fix is in testing, and I'll report back when (if) I hear anything more from Apple.
UPDATE FRI AUG 20th
Just to say I've had an email back from Apple Engineering (21:20 GMT) and they have said:
"Thank you for reporting this. We're aware of this issue and are currently working on a fix."
So hopefully there will soon be a resolution!
[ update to question below. There definitely seems to be a storekit sandbox issue at present. I've seen 4 or 5 other people report the same fault, but would appreciate a larger sample size! If you have a storekit implementation that you can test in the sandbox if you could report whether or not it works for you that would be much appreciated. I've logged a bug with apple as bug id#8329461 but am not sure how else to expedite this or if it is really a widespread issue. ]
I have a working iPhone storekit implementation in development. All the items for purchase are consumable, we have multiple test accounts established.
All of a sudden today, my sequence goes;
1) Request product list from Apple ... works fine (so can connect to store OK)
2) Purchase item - get "Confirm your In App Purchase" alert as normal
3) (click buy)
4a) My code gets a failed transaction with error code 2 and description "cannot connect to itunes store" via the - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions method.
[[SKPaymentQueue defaultQueue] finishTransaction: transaction] is being called in this situation.
4b) The user gets an alert "You've already purchased this but it hasn't been downloaded" (it has never been purchased on this device with this user account).
This is happening on different devices and with test accounts that have never been used before. I'm not aware of any changes to our code. Can anyone else confirm that the storekit test framework is working correctly for them? Is anyone else having issues today?
Any ideas as to what causes this strangeness? The message "cannot connect to itunes store" seems odd given it clearly can for retrieving product ids and watching the transaction.
NB. I also note that setting up test user accounts in the store has changed - there are now stricter password requirements etc and so I'm wondering if Apple have changed something that might be causing the issue.
TIA
Roger
PS. On a first attempt on a new device, I get the alert "unable to connect to itunes store try again later" but then what happens is that the device thinks it has already been purchased so gives the message about downloading again.
Just had a final update from Apple closing the bug.
This is a courtesy email regarding Bug ID# 8329461.
Engineering has provided the following feedback regarding this issue:
We believe this issue is now resolved. Please let us know if you have any problems.
I've also been plagued by this problem. I had a fully functional In App Purchase working fine. I later uploaded a new binary and approved it. I made some other changes to the app, and also used a foreign "IN APP" purchase User, attempted to sign-in in Settings. Later when I tested it again, itt was no longer working. The error I got was "Unable to connect to iTunes", "Error Domain=NSURLErrorDomain Code=-1009". Pulled lots of hair out. I was able to fix it by signing out of iTunes account on the iPhone, "cleaning all targets", AND also signing out of iTunes on my MAC, (I closed iTunes), creating a new "local" In-App" user (necessary?). Attempted to sign into that account on my iPhone. Then it started working! Some of the above may be voodoo, but it worked. Hope this helps a few people.
I am also having the same issue. As of a couple days ago it seems. I am on iPad. Exactly the same description as Roger wrote.
Tried the Erase All Content and Settings on the iPad. Didn't work. Tried on several networks. Seemed like at first I was having a real slow connection. Took a long time to get a response from the store with the product info. As of today, I am connecting very quickly to the store but still having the same error after being notified that I have already purchased the product. Created new users, everything. No go. I've gone through all the code and it looks fine. Definitly seems to be a problem with the Sandbox side. Hope to see an update on this thread soon.
Edit
For now I am just skipping the purchase request and calling my provideContent: method when when choosing to make a purchase. Since the store is still providing me with the products, I can keep testing and working on the content providing aspect but it sure would be nice to get this working.
After announced "fix" by apple still have this trouble. It's feels like purchase transaction just falls off while test user input his credentials. But when test user is already logged in, everything is OK.
Either [SKPayment paymentWithProduct:product] nor [SKPayment paymentWithProductIdentifier:product.productIdentifier] works with logged out user in spite of products request was successful.
Does anyone have any workaround?
I've been going nuts over the same issue all morning in Lion and MacOS (not iPhone). The sandbox is not working.
I just got "An unknown error has occurred" when trying to make the purchase and a console error like this one
8/23/11 1:12:26.090 PM storeagent: promptResponse: <CKSignInPromptResponse:0x7fe1c14fb2a0 returnCode:-1>
If there is another poor soul like me out there that has been burning their brains out for hours to make this work I just found the answer: the in-app purchase sandbox is ONLY working for US test users. Other stores are not working (my test user was set to Argentina...). Create a new Test user, set it to the US store, and it will work...
I hope this helps.
For anyone having an issue similar to: "Cannot connect to iTunes Store" make sure to log out of your Apple ID in the iTunes & App Stores in settings and to try using a test account attached to your iTunes Connect account with access to your app and in app purchase
I have had zero success with in app purchase. I have submitted the free app binary, and then rejected the binary. I have added the test product. I have approved the test product TAP001.
I have followed the code examples to no avail. I do a SKProducts request using both "com.companyname.appid.TAP001" and just "TAP001"
Regardless, I get an empty response.products and response.invalidProductIdentifiers with the product string I sent.
I created a test user, but seeing how I cannot get any product info, the test user doesn't really come into play yet.
Can in app purchase be tested in debug or release builds? Or does it have to be a distribution?
Must one have a fully accepted app in the app store prior to testing in app purchase?
I am simply trying to test the process out and I do not have an actual app yet. I went as far as to fill out all the bank and tax information. I have followed the steps in the app docs but clearly I have something wrong or missing.
Thanks
I just got it to work. I used only "TAP001" for a product instead of "com.companyname.appid.TAP001". and I got product information back.
I feel dumb but I know have tried "TAP001" in the past with no success but I have tried so many things prior to this that I must have had some other information wrong a the time I did.
For those who are struggling with this issue, I can say:
Your app does not need to be live in the store.
You do need an app in the App store submission. Reject the binary after uploading it.
Testing your app should work in Release or Debug modes
You do need an in app product "Cleared for sale"
Your product request only needs to contain the product id(s)
Here is an example:
- (IBAction)buyButton1Click:(id)sender{
NSSet *productList = [NSSet setWithObjects:#"TAP001", #"TAP002", nil];
SKProductsRequest *request= [[SKProductsRequest alloc] initWithProductIdentifiers:productList];
request.delegate = self;
[request start];
}
According to Apple's itunes connect FAQ, you need to create a test user in order to use the itunes store sandbox environment.
That being said, even after creating such a user and setting my iphone to use that user, I am still experiencing the same issue that you report: all products are "invalid" according to the store kit API.
I'll update this post when I figure it out.
I've also heard that some times, you need to wait several hours before the in-app item goes through apple sand box servers, so it could be the reason it doesn't work yet. I'm in that case, i'm going to wait 24 hours to see, i'll let you know !!!
So: Imagine an extremely complicated and convoluted set of rules for how to test in app purchases. Now make it ten times more complicated. That is apple's solution. :)
You'll need to read the itunes connect developer guide, and probably also the In App Purchase guide. The short answer is that you'll need a special test account and you'll also need to use it in a very particular way if you want to test your in app purchase.
Good luck!
I have created a test account for sandbox testing of in-app purchases. I am following these steps to test
Logged out of any existing accounts
Open app and start getting list of products available
Start process to download a product
SKPayment *payment = [SKPayment paymentWithProductIdentifier:productId];
[[SKPaymentQueue defaultQueue] addPayment: payment];
Now ideally I should be asked for the user name/pwd at this point. But I am not prompted for anything and the transaction fails (obviously because I am not logged in)
If I try to login from Settings->Store, it asks for my credit info which I'm sure is not necessary.
Can someone please help me with this issue.
Thanks...
Ok. This was stupid! But hope someone can learn from my mistakes :)
I was testing the in-app purchase with a adhoc distribution profile. And acc to Apple engineers, as soon as you do that, the test account "stops" being a test account.
In-app purchases CAN ONLY BE TESTED by launching your app via XCode in debug mode!
Update
This is not true any more. It supposedly works fine with adhoc builds as well now.
Source: recent testing of in-app purchases using an adhoc build.
Make sure that you have in-app purchases turned on in your provisioning file
Check canMakePayments
In Simulator the StoreKit just does not respond : you should test on the device
You must have at least one observer added to the SKPaymentQueue
Try to ask for the product list first (besides the fact that you know the productId already); it sounds silly, but SK framework is far from perfect.
Also, when sending {"receipt-data":...} to verification server do encode the receipt with Base64 before inserting it into json object. This is not mentioned in official docs anywhere: only on a couple of blogs.
I ran into the same problem. As suggested by Oleg, the issue was that the productID was invalid. Set a break point at
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response and check response.products.
You may find that the productID is not in response.products. When this happen, the transaction will proceed as purchase cancel by user, therefore, never prompt for login.