I have got one big problem with an IAP purchase testing.
There are next steps which I have made:
Create App ID (com.domainname.appname)
Create Development Provisioning Profile with an App ID (com.domainname.appname)
Create App on iTunes Connect (Bundle ID com.domainname.appname)
Manage IAP. Create non-consumable products with Product ID com.testitem1, com.testitem2, com.testitem3 (there is Ready to Submit status for each products)
Configurate XCode project settings
Bundle identifier: com.domainname.appname
Code Signing Identity: Development Provisioning Profile that I have made on the step 2
Deployment target: 4.0
Device
iPod Touch 4gen iOS 5.1.1
Write source code
My class support SKProductsRequestDelegate
in - viewDidLoad callback method I have wrote these lines:
if ([SKPaymentQueue canMakePayments])
{
NSLog(#"YES, I CAN MAKE PAYMENTS");
}
else
{
NSLog(#"NO, I CAN NOT MAKE PAYMENTS");
}
On this stage everything is okay. I can make payments.
Next, I'm try to create request for my products:
SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers: [NSSet setWithObjects:#"com.testitem1", #"com.testitem2", #"com.testitem3", nil]];
request.delegate = self;
[request start];
On this stage everything is okay also and on next stage my request object invoke callback method below:
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSArray *myProduct = response.products;
NSLog(#"%#", myProduct);
}
But there are not any products in response and I can not understand why.
I already have this problem before (i just reset my device and everything worked good), but in this case I can not figure out what's wrong.
I have went through this guide:
https://developer.apple.com/library/ios/#technotes/tn2259/_index.html
In my case this is was related that I have not got Banking Information. If you want to test your IAP you must have an iOS Paid Applications contract (iOS) with a your tax information.
This happens because you haven't yet uploaded the app's binary in iTunes Connect. Go to iTunes Connect, upload the app's binary. Once it's uploaded, reject it straight away so that it's marked as "Developer Rejected".
This is a necessary step for you to receive SKProductResponse if it's the first version of your app. It won't affect your app's review.
Related
I have a paid app that I'm thinking about making free with in app purchases. If I make the switch I'll need to check if the user has already paid for the app and then enable the paid features.
I think the below code should do what I need but I'm not sure how to test it. I built the app and ran it using my development provisioning profile on my device and receitpData is empty. So I built the app with a distribution provisioning profile and submitted it to the app store then downloaded the app using test flight but I'm still having the same problem.
How do I get the receipt data from an existing app?
Do I need to enable in-app purchases for this app to get this data?
NSURL *receiptUrl = [[NSBundle mainBundle] appStoreReceiptURL];
NSData *receiptData = [NSData dataWithContentsOfURL:receiptUrl];
I figured it out:
#import <StoreKit/StoreKit.h>
Don't forget to add its delegates
<SKPaymentTransactionObserver, SKProductsRequestDelegate>
Here's the code:
SKReceiptRefreshRequest* request = [[SKReceiptRefreshRequest alloc] initWithReceiptProperties:nil];
request.delegate = self;
[request start];
and then:
-(void)requestDidFinish:(SKRequest*)request{
if([request isKindOfClass:[SKReceiptRefreshRequest class]]){
NSLog(#"YES, You purchased this app");
}
}
- (void)request:(SKRequest*)request didFailWithError:(NSError *)error{
NSLog(#"NO, you need to buy it");
}
In version 1.0 ,the app content was free. Whereas in version 1.1 , I implemented Automatic renewal Subscription for some content and used IAPHelper for implementing InApp purchase. The Subscription is working fine in case of fresh installs whereas the users who updated the version they can access the paid content for free. If any one know ,what could be the reason behind this ,please help me.
this is my code for purchase
[[SubIAPHelper sharedInstance] requestProductsWithCompletionHandler:^(BOOL success, NSArray *products) {
if (success) {
inAppproducts=products;
SKProduct *product =products[0];
if (![[SubIAPHelper sharedInstance] productPurchased:product.productIdentifier]) {
/* purchasing UI shown here and after successful purchase content is downloaded */
}
else
{
/*Content downloaded as previously purchased and rest of the flow*/
}
}
}];
Any kind of help will be appreciable.
I recently had an update to an app approved. This versioned added In app purchases. The app works perfect in sandbox mode and Apple did approve both the IAP and the app, but the in app purchases fails in the app.
I think the crash occurs because the response.products from:
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
}
returns an empty array and that:
SKProduct *product = [[products filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"productIdentifier == %#", _model.packageId]] firstObject];
returns nil. I can't get the price of the SKProduct. I think that the actual app crash is with these lines since product and payment probably is nil.
SKPayment *payment = [SKPayment paymentWithProduct:product];
[[SKPaymentQueue defaultQueue] addPayment:payment];
I read other blog posts that it can take up to 24 hours before IAP becomes available. Is this true? Do I need to worry about bugs regarding the IAP's in my app when it works in sandbox mode and that Apple approved it?
It turned out that this is indeed an Apple problem. I got a response from Apple stating that it can take up to 36 hours before the In App Purchases is available.
I guess this makes it really important to handle the case when
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
}
is called, but when response.products is empty. When you try to get the actual product, make sure that you don't get a nil result.
I wish that Apple would not approve and release an update of an app until the IAP was really ready for sale.
In my app I have an in-app-purchase where I allow to purchase some items. (with mkstorekit)
A think that I notice in iOS 7 is this:
if In general setting of my iPhone I'm logged with my Apple id and I proceed to purchase an item I have an error "Error Domain=SKErrorDomain Code=0" and the code finish in "canceled" block.
Then I logout from my apple id, I start again the app and when I must purchase an item it ask me id and password and its correct (naturally I insert a tester user data that I created in iTunes Connect)
At this time I stop my app and in my general setting is stored the tester user, then I start again my app and when I must purchase an item I have not the problem that I had with my personal apple id and it work fine.
In iOS 6 it didn't happen because if I was logged with my apple id in general settings and I tried to purchase an item, it showed me my apple id and asked me to insert the password (naturally it didn't work)
Finally this is not a big problem, I solve it because I used my tester account, but when I release my app in App Store can I have the same problem? If an user is logged in general setting the mkstorekit sto purchase and go in "canceled" block?
I show the method where is the cancel block:
- (void)purchaseFeature:(NSString *)productID
{
[[MKStoreManager sharedManager] buyFeature:productID
onComplete:^(NSString* purchasedFeature,
NSData* purchasedReceipt,
NSArray* availableDownloads)
{
[HUD hide:YES];
/*** CODE TO OPEN VIEW IF THE PURCHASE IS DONE ****/
}
onCancelled:^
{
NSLog(#"User Cancelled Transaction");
[HUD hide:YES];
/*** HERE FINISH MY CODE IF I'M JUST LOGGED IN GENERAL SETTING WITH MY APPLE ID ***/
}];
}
Reports of our app crashing started flooding in last night. Many users who upgraded to 7.0.3 had the app crash at startup. Analyzing the itunes crash logs it was due to the app getting killed for taking too long to startup. Apparently the call to check for available in-app purchases is what was causing the crash.
We removed all in-app purchases from sale and now users are reporting that the app is now working.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// earlier stuff...
[self requestProductData]; // ask for in-app purchase localized prices/names
[[SKPaymentQueue defaultQueue] addTransactionObserver:self]; // process any pending transactions
// more stuff...
}
- (void) requestProductData
{
NSMutableSet * prodSet = [[[NSMutableSet alloc] initWithCapacity:10] autorelease];
StoreItem * curStoreItem;
for(int j=0; j<[storeArr count]; j++) {
curStoreItem = [storeArr objectAtIndex:j];
[prodSet addObject:curStoreItem.productID];
}
SKProductsRequest *request= [[SKProductsRequest alloc] initWithProductIdentifiers:prodSet];
request.delegate = self;
[request start];
}
In didFinishLaunchingWithOptions, we make the call to request product data. Do we need to be doing this in another thread? Anyone else having this issue?
We solved this in two ways, addressing the immediate live app crashing and then actually addressing the coding error that triggered it.
The iOS 7.0.3 update added a latency to the call to apple servers which return in-app product data. Since we were making the product request call from didFinishLaunching our app was being killed for not starting up quickly enough.
To address the live app crashing we temporarily removed all in app purchases for the app from sale.
Meanwhile we moved the product data request to just prior to presenting the in-app storefront - the correct programmatic solution, as suggested by maddy.