in app purchase non consumable product - iphone

I have written the following code.
But when i execute this code, i got log, which shows "no products available".
I am unable to find the reason.
-(void)viewDidLoad {
[super viewDidLoad];
if ([SKPaymentQueue canMakePayments])
{
SKProductsRequest *productsRequest=[[SKProductsRequest alloc]initWithProductIdentifiers:[NSSet setWithObject:#"com.cmp.name.prdt"]];
productsRequest.delegate=self;
[productsRequest start];
}
else {
NSLog(#"Parental Control are enabled");
}
}
-(IBAction)btnpurchase
{
NSString* isPurchased = [[NSUserDefaults standardUserDefaults] stringForKey:#"com.cmp.name.prdt"];
if ([#"purchased" compare:isPurchased]==NSOrderedSame)
{
///do some task
}
else
{
SKPayment * payment=[SKPayment paymentWithProductIdentifier:#"com.cmp.name.prdt"];
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
}
-(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
SKProduct *validProduct=nil;
int count=[response.products count];
if (count>0) {
validProduct=[response.products objectAtIndex:0];
}
else if(!validProduct)
{
NSLog(#"no products available");
}
}
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
for (SKPaymentTransaction *transaaction in transactions)
{
switch (transaaction.transactionState)
{
case SKPaymentTransactionStatePurchasing:
break;
case SKPaymentTransactionStatePurchased:
[[SKPaymentQueue defaultQueue]finishTransaction:transaaction];
[[NSUserDefaults standardUserDefaults] setObject:#"purchased" forKey:#"com.cmp.name.prdt"];
[[NSUserDefaults standardUserDefaults] synchronize];
break;
case SKPaymentTransactionStateRestored:
[[SKPaymentQueue defaultQueue]finishTransaction:transaaction];
break;
case SKPaymentTransactionStateFailed:
if (transaaction.error.code!=SKErrorPaymentCancelled) {
NSLog(#"Error encountered");
}
[[SKPaymentQueue defaultQueue] finishTransaction:transaaction];
break;
default:
break;
}
}
}
Could anyone help me out in this?

You can try out with following piece of code
//PRODUCT REQUEST DELEGATE METHOD
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSLog(#"The product request didReceiveResponse :%#",[response description]);
NSLog(#"The products are :%#",[response.products description]);
NSLog(#"The invalidProductIdentifiers are:%#",[response.invalidProductIdentifiers description]);
NSArray *products=response.products;
for(SKProduct *currentProduct in products){
NSLog(#"THE Product price is :%#",currentProduct.price);
NSLog(#"THE Product description is :%#",currentProduct.localizedDescription);
NSLog(#"THE Product title is :%#",currentProduct.localizedTitle);
NSLog(#"THE Product's product identifier is :%#",currentProduct.productIdentifier);
}
}
THIS WILL LOG THE PRODUCT DETAILS REGISTERED ON iTUNES CONNECT IN CONSOLE WINDOW

Unfortunately, Apple does not respond with any useful information about why your purchases do not show up. I would go through this checklist. In my apps, things didn't work for a few days, then the suddenly started working. Be sure your financial info is correct.

Related

Issue with transactionreceipt deprecated in iOS 7 warning

I am going to update my application for iOS 7 and I am using IAP , but xcode 5 give me this this error :
transactionreceipt is deprecated : first deprecated in iOS 7
here is my code :
// saves a record of the transaction by storing the receipt to disk
- (void)recordTransaction:(SKPaymentTransaction *)transaction
{
if ([transaction.payment.productIdentifier isEqualToString:kProductIdentifier])
{
// save the transaction receipt to disk
[[NSUserDefaults standardUserDefaults] setValue:transaction.transactionReceipt forKey:#"proUpgradeTransactionReceipt"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
how can I fix this issue ?
//EDITED :
I used my AndreyMan's answer but nothing happened and compiler gave me APP:requestProductData END message
- (void)requestProductData
{
[NSThread sleepForTimeInterval:2];
NSLog(#"IN-APP:requestProductData");
SKProductsRequest *request= [[SKProductsRequest alloc]
initWithProductIdentifiers: [NSSet setWithObject: #"com.compony.product"]];
request.delegate = self;
[request start];
NSLog(#"IN-APP:requestProductData END");
}
and then gives me these messages :
2013-10-08 14:26:21.400 Arta[1138:60b] Purchasing... 2013-10-08 14:26:28.380 Arta[1138:60b] Unknown Reason. 2013-10-08 14:26:28.383
Arta[1138:60b] Purchase faild...
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
for (SKPaymentTransaction *transaction in transactions)
{
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchased:
[self completeTransaction:transaction];
NSLog(#"Purchase compelete...");
break;
case SKPaymentTransactionStateFailed:
[self failedTransaction:transaction];
NSLog(#"Purchase faild...");
break;
case SKPaymentTransactionStateRestored:
[self restoreTransaction:transaction];
NSLog(#"Restore compelete...");
break;
case SKPaymentTransactionStatePurchasing:
NSLog(#"Purchasing...");
break;
default:
break;
}
}
}
- (void)failedTransaction:(SKPaymentTransaction *)transaction
{
if (transaction.error.code != SKErrorPaymentCancelled)
{
// error!
[self finishTransaction:transaction wasSuccessful:NO];
if (transaction.error.code == SKErrorClientInvalid) {
}
else if (transaction.error.code == SKErrorPaymentInvalid) {
}
else if (transaction.error.code == SKErrorPaymentNotAllowed) {
}
else if (transaction.error.code == SKErrorPaymentCancelled) {
// [self showAlert:#"In-App Purchase" withMessage:#"This device is not allowed to make the payment."];
NSLog(#"User Cancellation.");
}
else {
// SKErrorUnknown
NSLog(#"Unknown Reason.");
}
}
else {
// this is fine, the user just cancelled, so don’t notify
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
}
Something like:
NSURL *receiptUrl = [[NSBundle mainBundle] appStoreReceiptURL];
NSData *receipt;
receipt = [NSData dataWithContentsOfURL:receiptUrl];

Changing in app purchase string identifier into an object (deprecated on ios 5)

i need to change this method of string to an SKProduct object, because its' deprecated on my app (ios 5)
(NOTE: this is implemented on the InAppRageIAPHelper class)
- (void)buyProductIdentifier2:(NSString *)productIdentifier {
srtProduct = [productIdentifier copy];
NSLog(#"Buying %#...", productIdentifier);
SKPayment *payment = [SKPayment paymentWithProductIdentifier:productIdentifier];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
then, when you hit buy:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(alertView.tag == 1)
{
NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
if([title isEqualToString:#"Cancel"])
{
if ([delegate respondsToSelector:#selector(purchaseCancelled)]) {
[delegate purchaseCancelled];
}
}
else if([title isEqualToString:#"Buy"])
{
[self buyProductIdentifier2:srtProduct];
}
}
}
Can someone explain me what to change?
You can use this link. It provide the sample code that have what u want.
http://www.raywenderlich.com/23266/in-app-purchases-in-ios-6-tutorial-consumables-and-receipt-validation
Find this method in IAPHelper.m
- (void)buyProduct:(SKProduct *)product {
NSLog(#"Buying %#...", product.productIdentifier);
SKPayment * payment = [SKPayment paymentWithProduct:product];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
After quick look into documentation: it looks like you have to perform SKProductsRequest with product identifier to fetch SKProduct, then you can proceed with SKPayment

multiple in-app purchase in one app

I have an app with multiple in-app contents on same page. when i buy one content it shows already purchased even if i don't buy all of them.
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
NSLog(#"[transactions count] : - %d ", [transactions count]);
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;
}
}
}
you need to create multiple buttons for in App purchase ,then assign them different tags to identify them.
here is sample code:
- (void)purchaseProUpgrade{
SKPayment *payment;
if(btnTag ==0){
payment = [SKPayment paymentWithProductIdentifier:kInAppPurchaseProUpgradeProductId1];
}
else if(btnTag ==1){
payment = [SKPayment paymentWithProductIdentifier:kInAppPurchaseProUpgradeProductId2];
}
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
// saves a record of the transaction by storing the receipt to disk
-(void)recordTransaction:(SKPaymentTransaction *)transaction{
if(btnTag == 0){
if ([transaction.payment.productIdentifier isEqualToString:kInAppPurchaseProUpgradeProductId1]){
[[NSUserDefaults standardUserDefaults] setValue:transaction.transactionReceipt forKey:#"proUpgradeTransactionReceipt" ];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
else if(btnTag == 1){
if ([transaction.payment.productIdentifier isEqualToString:kInAppPurchaseProUpgradeProductId2])
{
// save the transaction receipt to disk
[[NSUserDefaults standardUserDefaults] setValue:transaction.transactionReceipt forKey:#"proUpgradeTransactionReceipt" ];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
}
-(void)finishTransaction:(SKPaymentTransaction *)transaction wasSuccessful:(BOOL)wasSuccessful{
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:transaction, #"transaction" , nil];
if (wasSuccessful) {
[[NSNotificationCenter defaultCenter] postNotificationName:kInAppPurchaseManagerTransactionSucceededNotification object:self userInfo:userInfo];
if(btnTag == 0){
//write ur code
}
else if(btnTag == 1){
//write ur code
}
}
else
{
[[NSNotificationCenter defaultCenter] postNotificationName:kInAppPurchaseManagerTransactionFailedNotification object:self userInfo:userInfo];
}
}
this will solve your problem...
please check this best tutorial of Rey Wenderlich here describing full implementation of in-app Purchase with multiple products.

iOS In-App Purchases restore previous purcases safely

I have implemented an In-App Purchase in my app and I have two questions about it. This is the code I use:
- (IBAction)buyProduct1:(id)sender {
SKPayment *payment = [SKPayment paymentWithProduct:product1];
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
- (IBAction)restorePurchases:(id)sender {
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
}
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
for (SKPaymentTransaction *transaction in transactions) {
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchasing:
break;
case SKPaymentTransactionStatePurchased:
//Can I be 100% sure that this method is only called when the product is bought?
[self product1Bought:transaction];
break;
case SKPaymentTransactionStateRestored:
//What code should I have here to safely restore product1 if the product is bought?
break;
case SKPaymentTransactionStateFailed:
break;
default:
break;
}
}
}
- (void)product1Bought:(SKPaymentTransaction *)transaction {
NSString *string = #"Product1";
[[NSUserDefaults standardUserDefaults] setObject:string forKey:#"Product1"];
NSLog(#"Product1 is bought");
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
1.I was just wondering if I can be 100% sure that the productBought method is only called after a successfully purchase and not if anything strange happens and the product wasn't really purchased?
2.How can I check if product1 is purchased earlier so I can call the product1Bought method?
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
{
if ([queue.transactions count] == 0)
{
UIAlertView *restorealert = [[UIAlertView alloc]
initWithTitle:#"Restore"
message:#"There is no products purchased by you"
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[restorealert show];
activityIndicator.hidden = YES;
}
else
{
NSString *productID;
for(SKPaymentTransaction *transaction in queue.transactions)
{
productID = transaction.payment.productIdentifier;
NSLog(#"the product identifier is %#",productID);
}
here after completing your restore you can get the productId which you bought
1) is working fine and the data will be available when user purchases it
2) for the early purchased items you can call this method under SKPaymentTransactionStateRestored:
[self RestorePurchases];
-(void)RestorePurchases{
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
}

Iphone iAp [response.products count] is empty

Thats the problem - i have no products in my response for the iAp products.
I've read many themes about it here, at stackoverflow, plus here:
http://troybrant.net/blog/2010/01/invalid-product-ids/
And its all "YES". But it still wont work.
My appid iAps is ON, my provisioning new, my iapps connected to the App, and Cleared for sale, so...
Please, help.
PS. All the identifiers, that i've sent, returns me in the response.invalidProductIdentifiers array
PPS. itunes connect account was linked in Australia. (But in the account all stores was included for selling)
- (void)sendProductRequest:(NSString *)ID {
SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:ID]];
request.delegate = self;
[APPDELEGATE increaseNetworkUseCount];
[request start];
}
- (void)sendProductRequestForCourseTests {
[self sendProductRequest:#"au.bla.blabla.blablabla.inapptesting"]; // for example. 100% matching with my productID at itunes connect
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
for (int i = 0; i < [response.invalidProductIdentifiers count]; i ++) {
NSLog(#"%#", [response.invalidProductIdentifiers objectAtIndex:i]); // here we have my Product id
}
DbgLog(#"Products count in received responce: %d", [response.products count]); // here i've got Zero!
SKProduct* product = [response.products count] > 0 ? [response.products objectAtIndex:0] : nil;
if (product) {
//NSString *storeProductID = myProduct.productIdentifier;
//SKPayment *payment = [SKPayment paymentWithProductIdentifier:storeProductID];
SKPayment *payment = [SKPayment paymentWithProduct:product];
DbgLog(#"Payment request sent for product with id: %#", product.productIdentifier);
[[SKPaymentQueue defaultQueue] addPayment:payment];
} else {
[APPDELEGATE decreaseNetworkUseCount];
for (id <IAPManagerObserver> observer in observers) {
[observer IAPManager:self didFinishSuccessfully:NO withTransaction:nil];
}
}
[request autorelease];
}
check below points,
Does your project’s .plist Bundle ID match your App ID
Are you using the full product ID when when making an SKProductRequest
This is the normal scenario issue. Please check this items, it should resolve the issue.