what is the alternative solution for paymentWithProductIdentifier? - iphone

Hi i am using in APP purchase in my project . When i run this project everything works fine, except i am getting a warning message saying that "paymentWithProductIdentifier is deprecated", I gone through the similar questions that are asked in stack overflow but i didn't satisfied. I shown you my coding that i used in the project below
SKPayment *payment=[SKPayment paymentWithProductIdentifier:#"com.mycompany.dmaker.maker1"];
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue] addPayment:payment];
Can anyone tell me
1)the alternative for this warning.
2)or tell me whether this project approve in appstore if i use this existing code.

Try using this:
SKProduct *selectedProduct = <#from the products response list#>;
SKPayment *payment = [SKPayment paymentWithProduct:selectedProduct];
[[SKPaymentQueue defaultQueue] addPayment:payment];

You can replace paymentWithProductIdentifier: with following codes:
// SKPayment *payment = [SKPayment paymentWithProductIdentifier:productId];
// [[SKPaymentQueue defaultQueue] addPayment:payment];
NSSet *productIdentifiers = [NSSet setWithObject:productId];
self.productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
self.productsRequest.delegate = self; // your wrapper for IAP or AppDelegate or anything
[self.productsRequest start];
while productsRequest is a retain property.
And implement a SKProductsRequestDelegate method:
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
for (SKProduct *product in response.products) {
SKPayment *payment = [SKPayment paymentWithProduct:product];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
self.productsRequest = nil;
}

You have 3 options:
suppress this warning with preprocessor definition:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
SKPayment *payment=[SKPayment paymentWithProductIdentifier:#"com.mycompany.dmaker.maker1"];
#pragma clang diagnostic pop
[[SKPaymentQueue defaultQueue] addPayment:payment];
create SKMutablePayment instead of SKPayment:
SKMutablePayment *payment = [[SKMutablePayment alloc] init];
payment.productIdentifier = #"com.mycompany.dmaker.maker1";
payment.quantity = 1;
[[SKPaymentQueue defaultQueue] addPayment:payment];
use paymentWithProduct: convenience initializer:
SKPayment *payment = [SKPayment paymentWithProduct:<# product that you received in productsRequest:didReceiveResponse: #>];
[[SKPaymentQueue defaultQueue] addPayment:payment];

You could use the following code instead, it does have a little extra that you may already have, but just to make sure
#define kInAppPurchaseId "(your product ID here)"
- (void)makePurchase{
//call this when you would like to begin the purchase
//like when the user taps the "purchase" button
NSLog(#"User requests to make purchase");
if([SKPaymentQueue canMakePayments]){
NSLog(#"User can make payments");
SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:kInAppPurchaseId]];
productsRequest.delegate = self;
[productsRequest start];
}
else{
//the user is not allowed to make payments
NSLog(#"User cannot make payments due to parental controls");
}
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
SKProduct *validProduct = nil;
int count = [response.products count];
if(count > 0){
validProduct = [response.products objectAtIndex:0];
NSLog(#"Products Available!");
[self purchase:validProduct];
}
else if(!validProduct){
NSLog(#"No products available");
}
}
- (IBAction)purchase:(SKProduct *)product{
SKPayment *payment = [SKPayment paymentWithProduct:product];
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
I use this code in one off my applications, so it should work.

Related

How to display an activity indicator while loading in app purchase?

I have a button that calls the in app purchase feature. I would to display a loading wheel while it is loading the product and the dismiss it when the UIAlertView to confirm the purchase appears. I am using the MBAlertView to show other messages in my app and I would to use it also here.
How can I do it? I want to display it when the user presses the button and dismiss it when it receives a response.
Here is my code at the moment!
- (IBAction)buyCoffeeInAppPurchase:(id)sender {
SKProductsRequest *request= [[SKProductsRequest alloc]
initWithProductIdentifiers: [NSSet setWithObject: #"com.giovannibalestra.emergencycall.Thankyoudeveloper"]];
request.delegate = self;
[request start];
// I should add something like this line of code to show the activity indicator but I can only set hidesAfter some seconds
// [MBHUDView hudWithBody:#"Wait." type:MBAlertViewHUDTypeActivityIndicator hidesAfter:4.0 show:YES];
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
NSArray *myProduct = response.products;
NSLog(#"%#",[[myProduct objectAtIndex:0] productIdentifier]);
SKPayment *newPayment = [SKPayment paymentWithProduct:[myProduct objectAtIndex:0]];
[[SKPaymentQueue defaultQueue] addPayment:newPayment];
}
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
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;
}
}
}
- (void)completeTransaction:(SKPaymentTransaction *)transaction {
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
- (void)restoreTransaction:(SKPaymentTransaction *)transaction {
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
- (void)failedTransaction:(SKPaymentTransaction *)transaction {
if (transaction.error.code != SKErrorPaymentCancelled)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Purchase Unsuccessful"
message:#"Your purchase failed. Please try again."
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
For show loading you can also use MBProgressHUD. Its a easy way to show loading process. Download MBProgressHUD.h & .m file from internet & just copy in xcode project.
HOW TO USE: Import this #import "MBProgressHUD.h" in your .h & .m files & also this MBProgressHUD *HUD; in .h file.
Then in .m file your code looks like:
- (IBAction)buyCoffeeInAppPurchase:(id)sender {
HUD = [[MBProgressHUD alloc] initWithFrame:CGRectMake(0, 0, 320, 460) ];
HUD.labelText = #"Fetching...";
[self.view addSubview:HUD];
[HUD show:YES];
SKProductsRequest *request= [[SKProductsRequest alloc]
initWithProductIdentifiers: [NSSet setWithObject: #"com.giovannibalestra.emergencycall.Thankyoudeveloper"]];
request.delegate = self;
[request start];
// I should add something like this line of code to show the activity indicator but I can only set hidesAfter some seconds
// [MBHUDView hudWithBody:#"Wait." type:MBAlertViewHUDTypeActivityIndicator hidesAfter:4.0 show:YES];
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
NSArray *myProduct = response.products;
NSLog(#"%#",[[myProduct objectAtIndex:0] productIdentifier]);
SKPayment *newPayment = [SKPayment paymentWithProduct:[myProduct objectAtIndex:0]];
[[SKPaymentQueue defaultQueue] addPayment:newPayment];
[HUD hide:YES];
[HUD removeFromSuperViewOnHide];
}
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
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;
}
}
}
- (void)completeTransaction:(SKPaymentTransaction *)transaction {
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
- (void)restoreTransaction:(SKPaymentTransaction *)transaction {
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
- (void)failedTransaction:(SKPaymentTransaction *)transaction {
if (transaction.error.code != SKErrorPaymentCancelled)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Purchase Unsuccessful"
message:#"Your purchase failed. Please try again."
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
- (void)paymentQueue:(SKPaymentQueue *)queue
updatedTransactions:(NSArray *)transactions
{
for (SKPaymentTransaction *transaction in transactions)
{
if (transaction.transactionState == SKPaymentTransactionStatePurchased) {
[self completeTransaction:transaction];
}
if (transaction.transactionState == SKPaymentTransactionStateFailed) {
[self failedTransaction:transaction];
}
if (transaction.transactionState == SKPaymentTransactionStateRestored) {
[self restoreTransaction:transaction];
}
else {
// Do something.
}
// You can dismiss your Activity Indicator (MBHUDView) here.
}
}
Hi Simply apply the activity indicator when user clicks on purchase button and stop the activity indicator after this method - (void)completeTransaction:(SKPaymentTransaction *)transaction. Don't forget to stop in failed transaction too, other wise activity indicator start animating. Some times activity indicator needs to calls through threads is they not visible. So please try that too.

In-App Purchase failed transactions

I use in-app purchases in my application, exactly consumable. But when everything goes fine before I test it. When I enter test user ID and password it goes into the SKPaymentTransactionStateFailed.
Here is some code I use:
- (void) funcPrepareForPurchasing:(NSString *)stringType
{
if([SKPaymentQueue canMakePayments])
{
NSLog(#"Parental Controls are disabled");
SKProductsRequest *pr = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:[NSString stringWithFormat:#"com.Company.AppName.%#", stringType]]];
pr.delegate = self;
[pr start];
}
else
{
UIAlertView *alertviewPR = [[UIAlertView alloc] initWithTitle:#"Parental Controls" message:#"Parental Controls are On" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:NO, nil];
[alertviewPR show];
}
}
- (void) funcPurchaseBonusScores
{
SKPayment *payment = [SKPayment paymentWithProductIdentifier:#"com.Company.AppName.BonusScores"];
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
- (void) funcPurchaseBonusLife
{
SKPayment *payment = [SKPayment paymentWithProductIdentifier:#"om.Company.AppName.BonusLife"];
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
- (void) funcPurchaseBonusStar
{
SKPayment *payment = [SKPayment paymentWithProductIdentifier:#"com.Company.AppName.BonusStar2"];
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
- (void) productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
SKProduct *vp = nil;
int count = [response.products count];
NSLog(#"%i", count);
if(count)
vp = [response.products objectAtIndex:0];
else if(!vp)
NSLog(#"No Prodacts are available");
}
- (void) paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
for(SKPaymentTransaction *transaction in transactions)
{
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchasing:
NSLog(#"yidulobs = purchasing");
break;
case SKPaymentTransactionStatePurchased:
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
userDefaultsInApps = [NSUserDefaults standardUserDefaults];
if( intInApps == 1 )
[userDefaultsInApps setInteger:5 forKey:#"keyScores"];
else if( intInApps == 2 )
[userDefaultsInApps setInteger:5 forKey:#"keyLife"];
else if( intInApps == 3 )
[userDefaultsInApps setInteger:5 forKey:#"keyStar"];
[userDefaultsInApps synchronize];
NSLog(#"gadaixada");
break;
case SKPaymentTransactionStateRestored:
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
case SKPaymentTransactionStateFailed:
NSLog(#"Error an Cancelled!!!");
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
}
}
}
Then I try to purchase with this function:
- (void) func1
{
intInApps = 1;
[self funcPrepareForPurchasing:#"BonusScores"];
[self funcPurchaseBonusScores];
}
- (void) func2
{
intInApps = 2;
[self funcPrepareForPurchasing:#"BonusLife"];
[self funcPurchaseBonusLife];
}
- (void) func3
{
intInApps = 3;
[self funcPrepareForPurchasing:#"BonusStar2"];
[self funcPurchaseBonusStar];
}
What mistake have I done?
I was testing it on the simulator. In-apps doesn't work on it. It's necessary to test it on a device.

Error Domain=SKErrorDomain Code=3 "Cannot connect to iTunes Store" UserInfo=0x1aaf40 {NSLocalizedDescription=Cannot connect to iTunes Store}

Currently I'm working on in-App Purchase functionality, and I am getting below of the error
"Error Domain=SKErrorDomain Code=3 "Cannot connect to iTunes Store" UserInfo=0x1aaf40 {NSLocalizedDescription=Cannot connect to iTunes Store}"
Here is the step.
1) First I have create a one application "inAppPro" and it is under (Status) : "Prepare for upload"
2) I have added 4 Non-Consumable product. and also fill related details.
3) I have also create test user (sandbox) for test in-App purchase product.
4) I have also created provision profile with enable inApp Purchase.
5) I have also created APP ID without (*) wild card.
Here is the code which are currently I'm using.
- (void)viewDidLoad
{
Detail1 *observer = [[Detail1 alloc] init];
[[SKPaymentQueue defaultQueue] addTransactionObserver:observer];
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
if ([SKPaymentQueue canMakePayments])
{
NSString *product = [NSString stringWithFormat:#"com.companyname.inAppDemo.module%d",ApplicationDelegate.objectID];
NSLog(#"In-App product for request = %#", product);
SKPayment *payment = [SKPayment paymentWithProductIdentifier:product];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
else
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"MyApp" message:#"You are not authorized to purchase from AppStore"
delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
[alert release];
}
}
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
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;
}
}
}
- (void) failedTransaction: (SKPaymentTransaction *)transaction
{
if (transaction.error.code != SKErrorPaymentCancelled)
{
// Optionally, display an error here.
NSLog(#"%#",transaction.error);
}
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
- (void) completeTransaction: (SKPaymentTransaction *)transaction
{
//[[MKStoreManager sharedManager] provideContent: transaction.payment.productIdentifier];
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
- (void) restoreTransaction: (SKPaymentTransaction *)transaction
{
//[[MKStoreManager sharedManager] provideContent: transaction.originalTransaction.payment.productIdentifier];
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
-(IBAction)btnpurchase:(id)sender
{
NSLog(#"ProductStatus = %#", ApplicationDelegate.productStatus);
if ([ApplicationDelegate.productStatus isEqualToString:#"FREE"])
{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:nil message:#"This is free for you so ENJOY it!!!" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil,nil];
[alert show];
[alert release];
}
else if ([ApplicationDelegate.productStatus isEqualToString:#"PAID"])
{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:nil message:#"You have already purchase it!!!" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil,nil];
[alert show];
[alert release];
}
else
{
NSLog(#"Detail1 id for product = %d", ApplicationDelegate.objectID);
NSString *product = [NSString stringWithFormat:#"com.companyname.inAppDemo.module%d",ApplicationDelegate.objectID];
NSLog(#"In-App product-id = %#", product);
SKProductsRequest *request= [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObjects:product,nil]];
request.delegate = self;
[request start];
}
}
Please anyone help me out.
Thanks in advance.
You must have valid contracts in effect in the "Contracts, Tax, and Banking" Section.
And of course, make sure that you use a correct Provisioning Profile and that you have enabled in App Purchase for that ID, and (last) that you have added purchasable items in iTunes Connect (which you did, as your screenshots show).

Inapp Purchase is succeeded but content is not unlock in iPhone app.. Why?

In My iphone app i have used In App purchase. All the things are working and the contents are in Resource folder. After successful transaction i have used a Sql Query to insert data in Sqlite database. I have Uploaded this app in App Store and find that after successful transaction the payment is taken from users but the content is not inserted in database and not Showed in app. Please help me. i am stressed on this Point. Due to this i have removed my app form App Store.
In this code after successful finding list of In App Purchases i am using method
For better Understanding i am putting my Some code here:
- (void)insertNewObject {
// Create a new instance of the entity managed by the fetched results controller.
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
// Save the context.
NSError *error = nil;
if (![context save:&error]) {
/*
Replace this implementation with code to handle the error appropriately.
abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
*/
// NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
-(void)updateObject {
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
// Save the context.
NSError *error = nil;
if (![context save:&error]) {
abort();
}
}
#pragma mark -
#pragma mark Store request
- (void) requestProductData {
request= [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:[arrayProductID objectAtIndex:b-2]]];//#"Scaringmirror11"
request.delegate = self;
[request start];
}
- (void) startPurchase {
//int newB=b-2;
SKPayment *payment = [SKPayment paymentWithProductIdentifier:[arrayProductID objectAtIndex:b-2]];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
#pragma mark Store delegate
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
NSArray *myProduct = response.products;
if (myProduct == nil || [myProduct count] == 0)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:ALERT_TITLE message:#"Missing product from App store.\n"
delegate:self cancelButtonTitle:#"Close" otherButtonTitles:nil];
[alert show];
[alert release];
return;
}
SKProduct *product;
BOOL existProduct = NO;
for (int i=0; i<[myProduct count]; i++) {
product = (SKProduct*)[myProduct objectAtIndex:0];
if ([product.productIdentifier isEqualToString:[arrayProductID objectAtIndex:b-2]]) {
existProduct = YES;
//[[NSUserDefaults standardUserDefaults] setValue:transaction.transactionReceipt forKey:#"proUpgradeTransactionReceipt" ];
//[[NSUserDefaults standardUserDefaults] synchronize];
break;
}
}
if (existProduct == NO) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:ALERT_TITLE message:#"Missing product from App store.No match Identifier found.\n"
delegate:self cancelButtonTitle:#"Close" otherButtonTitles:nil];
[alert show];
[alert release];
return;
}
[request autorelease];
[self startPurchase];
}
#pragma mark Store delegate
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
NSArray *myProduct = response.products;
if (myProduct == nil || [myProduct count] == 0)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:ALERT_TITLE message:#"Missing product from App store.\n"
delegate:self cancelButtonTitle:#"Close" otherButtonTitles:nil];
[alert show];
[alert release];
return;
}
SKProduct *product;
BOOL existProduct = NO;
for (int i=0; i<[myProduct count]; i++) {
product = (SKProduct*)[myProduct objectAtIndex:0];
if ([product.productIdentifier isEqualToString:[arrayProductID objectAtIndex:b-2]]) {
existProduct = YES;
//[[NSUserDefaults standardUserDefaults] setValue:transaction.transactionReceipt forKey:#"proUpgradeTransactionReceipt" ];
//[[NSUserDefaults standardUserDefaults] synchronize];
break;
}
}
if (existProduct == NO) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:ALERT_TITLE message:#"Missing product from App store.No match Identifier found.\n"
delegate:self cancelButtonTitle:#"Close" otherButtonTitles:nil];
[alert show];
[alert release];
return;
}
[request autorelease];
[self startPurchase];
}
#pragma mark observer delegate
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
for (SKPaymentTransaction *transaction in transactions)
{
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchased:
[self completeTransaction:transaction];
NSLog(#"Success");
break;
case SKPaymentTransactionStateFailed:
[self failedTransaction:transaction];
NSLog(#"Failed");
break;
case SKPaymentTransactionStateRestored:
[self restoreTransaction:transaction];
default:
break;
}
}
}
- (void) completeTransaction: (SKPaymentTransaction *)transaction {
//[[NSUserDefaults standardUserDefaults] setBool:YES forKey:REGISTRATION_KEY];
registered = YES;
//NSData *receiptData = [transaction transactionReceipt];
//NSString *str =[NSString string
//[[NSUserDefaults standardUserDefaults] setValue:transaction.transactionReceipt forKey:#"proUpgradeTransactionReceipt" ];
//[self registeredEnable];
// Remove the transaction from the payment queue.
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
[sqlite insertIntoScaryImage:[arrayGetMoreScaryImage objectAtIndex:b] add:[arrayGetMoreScarySound objectAtIndex:b]];
}
- (void) restoreTransaction: (SKPaymentTransaction *)transaction {
//[[NSUserDefaults standardUserDefaults] setBool:YES forKey:REGISTRATION_KEY];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:ALERT_TITLE message:#"Purchase success."
delegate:self cancelButtonTitle:#"Close" otherButtonTitles:nil];
[alert show];
[alert release];
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
//[sq];
}
- (void) failedTransaction: (SKPaymentTransaction *)transaction {
if (transaction.error.code != SKErrorPaymentCancelled)
{
// Optionally, display an error here.
NSString *stringError = [NSString stringWithFormat:#"Payment Cancelled\n\n%#", [transaction.error localizedDescription]];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:ALERT_TITLE message:stringError
delegate:self cancelButtonTitle:#"Close" otherButtonTitles:nil];
[alert show];
[alert release];
}
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
Please have a look and tell me where should i insert data in database so that i will able to provide data to users after Successful in app Purchase.
Thanks in Advance
You should implement your unlocking functionality into the payment observer, right after you receive confirmation that the payment is all right.
Your implementation of the observer is kinda strange, I guess it's not working.
EDIT:
your observer class
#import Foundation/Foundation.h
#import StoreKit/StoreKit.h
#interface InAppPurchaseObserver : NSObject {
}
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions;
#end
#import "InAppPurchaseObserver.h"
#implementation InAppPurchaseObserver
// The transaction status of the SKPaymentQueue is sent here.
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
for(SKPaymentTransaction *transaction in transactions) {
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchasing:
// Item is still in the process of being purchased
NSLog(#"Processing!!!");
break;
case SKPaymentTransactionStatePurchased:
// Item was successfully purchased!
// --- UNLOCK FEATURE OR DOWNLOAD CONTENT HERE ---
// The purchased item ID is accessible via
// transaction.payment.productIdentifier
// After customer has successfully received purchased content,
// remove the finished transaction from the payment queue.
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
break;
case SKPaymentTransactionStateRestored:
// Verified that user has already paid for this item.
// Ideal for restoring item across all devices of this customer.
// --- UNLOCK FEATURE OR DOWNLOAD CONTENT HERE ---
// The purchased item ID is accessible via
// transaction.payment.productIdentifier
// After customer has restored purchased content on this device,
// remove the finished transaction from the payment queue.
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
break;
case SKPaymentTransactionStateFailed:
// Purchase was either cancelled by user or an error occurred.
NSLog(#"Failed!!!");
if (transaction.error.code != SKErrorPaymentCancelled) {
// A transaction error occurred, so notify user.
NSLog(#"Cancelled!!!");
}
// Finished transactions should be removed from the payment queue.
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
break;
}
}
}
#end
implementation
- (void) requestProductData {
inappObserver = [[InAppPurchaseObserver alloc] init];
request= [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:[arrayProductID objectAtIndex:b-2]]];//#"Scaringmirror11"
request.delegate = self;
[request start];
}
- (void) startPurchase {
//int newB=b-2;
SKPayment *payment = [SKPayment paymentWithProductIdentifier:[arrayProductID objectAtIndex:b-2]];
[[SKPaymentQueue defaultQueue] addTransactionObserver:inappObserver];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}

Apple In app purchase StoreKit error

I am implementing in app purchase feature for a bookshelf but an error message RANDOMLY appear during purchasing books.
The error message is
"Payment requests are restricted to products returned as valid via Store Kit's didReceiveResponse method."
I find the document in apple
http://developer.apple.com/library/ios/#qa/qa2010/qa1691.html
but it does not help to solve the problem...
in the same time observer print out another error : "Can't connect to the iTunes Store".
my in app purchase logic flow:
APP START:
- (void) requestProductDataWithSet:(NSSet*)_set
{
SKProductsRequest *request= [[SKProductsRequest alloc] initWithProductIdentifiers: _set];
request.delegate = self;
[request start];
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
//setup UI here
}
PURCHASE:
- (void) purchase:(SKProduct *)product
{
if (!product || !verified) {
return;
}
SKProductsRequest *request= [[SKProductsRequest alloc] initWithProductIdentifiers: [NSSet setWithObject:product.productIdentifier]];
request.delegate = self;
[request start];
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
if ([SKPaymentQueue canMakePayments] && [response.products count] > 0)
{
NSLogInfo(#"xxxxxxxxx Make payment xxxxxxxxx");
SKPayment *payment = [SKPayment paymentWithProduct:[response.products objectAtIndex:0]];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
else
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Purchase" message:#"You are not authorized to purchase from AppStore"
delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
[alert release];
}
}
Observer:
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
for (SKPaymentTransaction *transaction in transactions)
{
NSLogInfo(#"updatedTransactions transactionState:%d, productIdentifier:%#",transaction.transactionState,transaction.payment.productIdentifier);
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchased:
[self completeTransaction:transaction];
break;
case SKPaymentTransactionStateFailed:
[self failedTransaction:transaction];
break;
case SKPaymentTransactionStateRestored:
[self restoreTransaction:transaction];
default:
break;
}
}
}
It looks like the problem isn't on your side. According to Technical Q&A QA1691, your code is fine.
Try changing:
SKPayment *payment = [SKPayment paymentWithProduct:[response.products objectAtIndex:0]];
to:
SKPayment *payment = [SKPayment paymentWithProductIdentifier:[response.products objectAtIndex:0].productIdentifier];
I had the same problem as you and this change worked for me.