Restore Purchase Functionality doesn't work well in ios - ios

I am having an app in which I have 5 Non Consumable In App Purchases.
I am using the following code for Restore In App Purchase.
- (void) paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
{
//NSLog(#"into method1");
purchasedItemIDs = [[NSMutableArray alloc] init];
NSLog(#"received restored transactions: %i", queue.transactions.count);
for (SKPaymentTransaction *transaction in queue.transactions)
{
NSString *productID = transaction.payment.productIdentifier;
[purchasedItemIDs addObject:productID];
}
// [customSpinner hide:YES];
if (queue.transactions.count==0)
{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"FameFace" message:#"It seems you have not buy this Package" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
else
{
NSLog(#"Data available");
NSString *isInApp = [[NSUserDefaults standardUserDefaults]valueForKey:#"Package"];
if ([isInApp isEqualToString:#"Pack1"])
{
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedp1Once"])
{
// app already launched
NSLog(#"Launching secondtime");
}
else
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedp1Once"];
NSLog(#"Launching first time");
requestText= #"Animal";
[self MakeQueryForUpdate];
[self getdata];
}
}
else if ([isInApp isEqualToString:#"Pack2"])
{
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedp2Once"])
{
// app already launched
NSLog(#"Launching secondtime");
}
else
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedp2Once"];
NSLog(#"Launching first time");
requestText= #"Celebrity";
[self MakeQueryForUpdate];
[self getdata];
}
}
else if ([isInApp isEqualToString:#"Pack3"])
{
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedp3Once"])
{
// app already launched
NSLog(#"Launching secondtime");
}
else
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedp3Once"];
NSLog(#"Launching first time");
requestText= #"Nature";
[self MakeQueryForUpdate];
[self getdata];
}
}
}
Below is the code when there is successful transaction.
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
for (SKPaymentTransaction *transaction in transactions) {
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchasing:
break;
case SKPaymentTransactionStatePurchased:
//[self downloadFromURL:[NSURL URLWithString:#"http://www.iphonedevnation.com/tutorials/ForestGreen.mp3"]];
// flgCheck = 1;
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
[self completeTransaction:transaction];
NSString *isInApp = [[NSUserDefaults standardUserDefaults]valueForKey:#"Package"];
if ([isInApp isEqualToString:#"Pack1"])
{
//by manthan...7th may
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedp1Once"])
{
// app already launched
NSLog(#"Launching secondtime");
}
else
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedp1Once"];
NSLog(#"Launching first time");
requestText= #"Animal";
[self MakeQueryForUpdate];
[self getdata];
}
}
else if ([isInApp isEqualToString:#"Pack2"])
{
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedp2Once"])
{
// app already launched
NSLog(#"Launching secondtime");
}
else
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedp2Once"];
NSLog(#"Launching first time");
requestText= #"Celebrity";
[self MakeQueryForUpdate];
[self getdata];
}
}
else if ([isInApp isEqualToString:#"Pack3"])
{
//by manthan... 7th may
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedp3Once"])
{
// app already launched
NSLog(#"Launching secondtime");
}
else
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedp3Once"];
NSLog(#"Launching first time");
requestText= #"Nature";
[self MakeQueryForUpdate];
[self getdata];
}
}
This is working fine.
What I am doing is that I am inserting some images in my DB when user Purchases a package from In App Purchase.
But as the Product is Non Consumable, If the user deletes the app and trying to Restore Images, My DB doesn't get updated.
Any help will be appreciated.
Thanks...
Edited
I put my code in the method below when user try to restore purchase.
As I have a single restore button and on pressing that button, user will have previously purchased packages that may be 2,3 or 4(any of the 5 packages that user has purchased once as these are non consumable products).
case SKPaymentTransactionStateRestored:
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
NSString *pk = [[NSUserDefaults standardUserDefaults]valueForKey:#"Package"];
if ([pk isEqualToString:#"Pack1"])
{
//by manthan...7th may
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedp1Once"])
{
// app already launched
NSLog(#"Launching secondtime");
}
else
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedp1Once"];
NSLog(#"Launching first time");
requestText= #"Animal";
[self MakeQueryForUpdate];
[self getdata];
}
}
else if ([pk isEqualToString:#"Pack2"])
{
//by manthan... 7th may
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedp2Once"])
{
// app already launched
NSLog(#"Launching secondtime");
}
else
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedp2Once"];
NSLog(#"Launching first time");
requestText= #"Celebrity";
[self MakeQueryForUpdate];
[self getdata];
}
}
else if ([pk isEqualToString:#"Pack3"])
{
//by manthan... 7th may
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedp3Once"])
{
// app already launched
NSLog(#"Launching secondtime");
}
else
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedp3Once"];
NSLog(#"Launching first time");
requestText= #"Nature";
[self MakeQueryForUpdate];
[self getdata];
}
}
when there is only one single purchase I can simply update my DB in SKPaymentTransactionStateRestored.
But when i have multiple non consumable products what should i do?
edited
if ([transaction.payment.productIdentifier isEqualToString:#"Pack1"])
{
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedp1Once"])
{
// app already launched
NSLog(#"Launching secondtime");
}
else
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedp1Once"];
NSLog(#"Launching first time");
requestText= #"Animal";
[self MakeQueryForUpdate];
[self getdata];
}
}
else if ([transaction.payment.productIdentifier isEqualToString:#"Pack2"])
{
//by manthan... 7th may
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedp2Once"])
{
// app already launched
NSLog(#"Launching secondtime");
}
else
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedp2Once"];
NSLog(#"Launching first time");
requestText= #"Celebrity";
[self MakeQueryForUpdate];
[self getdata];
}
}
else if ([transaction.payment.productIdentifier isEqualToString:#"Pack3"])
{
//by manthan... 7th may
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedp3Once"])
{
// app already launched
NSLog(#"Launching secondtime");
}
else
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedp3Once"];
NSLog(#"Launching first time");
requestText= #"Nature";
[self MakeQueryForUpdate];
[self getdata];
}
}

You need to use the case of SKPaymentTransactionStateRestored in the updatedTransactions method for doing this.
When restoring this case will be executed.
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
for (SKPaymentTransaction * transaction in transactions)
{
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchased:
//do your stuff
break;
case SKPaymentTransactionStateFailed:
//do your stuff
break;
case SKPaymentTransactionStateRestored:
//do your database stuff
default:
break;
}
};
}
Reference
Payment Transaction States
The state of a transaction.
enum { SKPaymentTransactionStatePurchasing,
SKPaymentTransactionStatePurchased, SKPaymentTransactionStateFailed,
SKPaymentTransactionStateRestored };
typedef NSInteger SKPaymentTransactionState;
Constants
SKPaymentTransactionStatePurchasing
The transaction is being processed by the App Store.
SKPaymentTransactionStatePurchased
The App Store successfully processed payment. Your application should provide the content the user purchased.
SKPaymentTransactionStateFailed
The transaction failed. Check the error property to determine what happened.
SKPaymentTransactionStateRestored
This transaction restores content previously purchased by the user. Read the originalTransaction property to obtain information about the original purchase.
Available in iOS 3.0 and later.
Declared in SKPaymentTransaction.h.
Check SKPaymentTransaction for more

Related

How to retain Remove Ads in app purchase after app has closed

I have successfully removed ads from the app with an in app purchase.
The problem is that if I close the app and reopen. The ads start up again.
I have 2 main scenes. The GameOverScene and the GameScene. The In App Purchase happens in the GameOverScene.
GameOverScene.m :
- (void)OnRemoveADS {
[self showPurchaseAlert: IAP_Q_RemoveADS :0];
g_bRemoveADS = [[NSUserDefaults standardUserDefaults] boolForKey: #"REMOVEADS"];
// For HZInterstitialAd, HZVideoAd, and HZIncentivizedAd, just check the BOOL to see if an ad should be shown
if (!g_bRemoveADS) {
[HZInterstitialAd show];
[self removeBannerAds];
[self disableAds];
NSLog(#"Disable ads is called");
}
}
- (void)removeBannerAds {
HZBannerAdOptions *options = [[HZBannerAdOptions alloc] init];
[HZBannerAd placeBannerInView:self.view
position:HZBannerPositionBottom
options:options
success:^(HZBannerAd *banner) {
if (g_bRemoveADS) { // case (2)
// Just discard the banner
[banner setHidden: YES];
[banner removeFromSuperview];
banner = nil;
//_currentBannerAd = banner;
NSLog(#"Banner ad removed!GameOverScene");
} else {
// Keep a reference to the current banner ad, so we can remove it from screen later if we want to disable ads.
_currentBannerAd = banner;
}
NSLog(#"Ad Shown! GameOverScene");
}
failure:^(NSError *error) {
NSLog(#"Error = %#",error);
}];
}
- (void)disableAds {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"REMOVEADS"];
[_currentBannerAd removeFromSuperview]; // case (3)
}
GameScene.m :
-(id) init {
if (self = [super init]) {
if (!g_bRemoveADS) {
g_bRemoveADS=FALSE;
[[NSUserDefaults standardUserDefaults] setBool:g_bRemoveADS forKey:#"REMOVEADS"];
[[NSUserDefaults standardUserDefaults] synchronize];
} else {
g_bRemoveADS=TRUE;
[[NSUserDefaults standardUserDefaults] setBool:g_bRemoveADS forKey:#"REMOVEADS"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
}
The way I'm trying to solve it is by using the same code from the GameOverScene.m in the AppDelegate.m that way when the app starts up it will remove the ads.
AppDelegate.m :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
g_bRemoveADS = [[NSUserDefaults standardUserDefaults] boolForKey: #"REMOVEADS"];
if (!g_bRemoveADS) {
[HZInterstitialAd show];
[self disableAds];
NSLog(#"Disable ads is called");
}
}
Out of my perspective you have one negation to much.
if (!g_bRemoveADS) { should be replaced with if (g_bRemoveADS) { in GameOverScene.m.
if (g_bRemoveADS) {
[HZInterstitialAd show];
[self removeBannerAds];
[self disableAds];
NSLog(#"Disable ads is called");
}
g_bRemoveADS evaluates to TRUE when the respective user-default is set. When it is set, then you call the removeBannerAds stuff etc. which seems to be the deactivation action.
You have to synchronise your NSUserDefaults after changing changing a value in your disableAds method with:
[[NSUserDefaults standardUserDefaults]synchronize];

Various Glitches With In App Purchase (iOS)

I've been experiencing various glitches with in-app purchases. Here are a few.
When I tap an item to buy it, it shows the Confirm you In-App Purchase alert and then after a second or so, it closes it self and opens the login alert.
Some times I'll log in, then it will ask me to log in again. Alerts pop up and go away on their own and it looks very glitchy. Some times the app crashes with no error message.
I haven't been able to search for any answers because these issues are quite strange.
Here is the code I'm using (I'm using a class named Game and a category names Game-Resources)
Game.m:
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
product = response;
}
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{
if (purchasing == NO){
// if I don't put (purchasing) in, this method is run multiples times
purchasing = YES;
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
for (SKPaymentTransaction * transaction in transactions){
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchasing:
NSLog(#"purchasing");
break;
case SKPaymentTransactionStatePurchased:
purchasing = NO;
NSLog(#"done");
if ([[NSUserDefaults standardUserDefaults] objectForKey:purchaseNSUserName] != nil){
int i = (int) [[NSUserDefaults standardUserDefaults] integerForKey:purchaseNSUserName];
[[NSUserDefaults standardUserDefaults] setInteger:i + purchaseNSUserAmount forKey:purchaseNSUserName];
[[NSUserDefaults standardUserDefaults] synchronize];
}else{
[[NSUserDefaults standardUserDefaults] setInteger:purchaseNSUserAmount forKey:purchaseNSUserName];
[[NSUserDefaults standardUserDefaults] synchronize];
}
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
case SKPaymentTransactionStateRestored:
purchasing = NO;
break;
case SKPaymentTransactionStateFailed:
purchasing = NO;
if (transaction.error.code != SKErrorPaymentCancelled){
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
//error happened
}
break;
case SKPaymentTransactionStateDeferred:
purchasing = NO;
break;
default:
break;
}
purchaseNSUserName = nil;
purchaseNSUserAmount = 0;
}
}
}
In the ViewDidLoad:
if ([SKPaymentQueue canMakePayments]){
self.productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObjects:#"somethinghere", #"anotherthing", nil]];
self.productsRequest.delegate = self;
[self.productsRequest start];
}
In Game-Resources (when buy button is pressed):
SKPayment *payment = [SKPayment paymentWithProduct: product.products[productID]];
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue] addPayment:payment];

Fire PushNotification in didRangeBeacons methods

I am developing app using Estimote beacons, so i have three beacons one for Entry and second for Exit and third for messages.I want to fire push notification based on proximity user is getting so i get the push notification but issue is that it give multiple same notification.
so i use NSUserDefault to stop multiple pushnotification but it also not works so how can i stop this issue.i also check with local notification but it also give me multiple local notification.
Code:-
-(void)beaconManager:(ESTBeaconManager *)manager
didRangeBeacons:(NSArray *)beacons
inRegion:(ESTBeaconRegion *)region
{
if ([beacons count] == 0)
return;
ESTBeacon* beacon = [beacons firstObject];
int dist = [beacon.distance intValue];
if([region.identifier isEqualToString:BeaconIdentifier2]){
switch (beacon.proximity) {
case CLProximityUnknown:{
[[NSUserDefaults standardUserDefaults] setObject:#"FALSE" forKey:#"Far"];
[[NSUserDefaults standardUserDefaults] setObject:#"FALSE" forKey:#"Near"];
[[NSUserDefaults standardUserDefaults] setObject:#"FALSE" forKey:#"Immediate"];
[[NSUserDefaults standardUserDefaults] synchronize];
if([[[NSUserDefaults standardUserDefaults] valueForKey:#"Unknown"] isEqualToString:#"FALSE"])
{
[[NSUserDefaults standardUserDefaults] setObject:#"TRUE" forKey:#"Unknown"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSLog(#"Call Unknown");
[self callPush];
}
}
break;
case CLProximityFar:{
[[NSUserDefaults standardUserDefaults] setObject:#"FALSE" forKey:#"Unknown"];
[[NSUserDefaults standardUserDefaults] setObject:#"FALSE" forKey:#"Near"];
[[NSUserDefaults standardUserDefaults] setObject:#"FALSE" forKey:#"Immediate"];
[[NSUserDefaults standardUserDefaults] synchronize];
if([[[NSUserDefaults standardUserDefaults] valueForKey:#"Far"] isEqualToString:#"FALSE"])
{
[[NSUserDefaults standardUserDefaults] setObject:#"TRUE" forKey:#"Far"];
[[NSUserDefaults standardUserDefaults] synchronize];
//Call webservice
[self callPush];
}
}
break;
case CLProximityNear:{
[[NSUserDefaults standardUserDefaults] setObject:#"FALSE" forKey:#"Unknown"];
[[NSUserDefaults standardUserDefaults] setObject:#"FALSE" forKey:#"Far"];
[[NSUserDefaults standardUserDefaults] setObject:#"FALSE" forKey:#"Immediate"];
[[NSUserDefaults standardUserDefaults] synchronize];
if([[[NSUserDefaults standardUserDefaults] valueForKey:#"Near"] isEqualToString: #"FALSE"])
{
[[NSUserDefaults standardUserDefaults] setObject:#"TRUE" forKey:#"Near"];
[[NSUserDefaults standardUserDefaults] synchronize];
//Call webservice
[self callPush];
}
}
break;
case CLProximityImmediate:{
[[NSUserDefaults standardUserDefaults] setObject:#"FALSE" forKey:#"Unknown"];
[[NSUserDefaults standardUserDefaults] setObject:#"FALSE" forKey:#"Far"];
[[NSUserDefaults standardUserDefaults] setObject:#"FALSE" forKey:#"Near"];
[[NSUserDefaults standardUserDefaults] synchronize];
if([[[NSUserDefaults standardUserDefaults] valueForKey:#"Immediate"] isEqualToString:#"FALSE"])
{
[[NSUserDefaults standardUserDefaults] setObject:#"TRUE" forKey:#"Immediate"];
[[NSUserDefaults standardUserDefaults] synchronize];
//Call webservice
[self callPush];
}
}
break;
}
}
}
Thanks in advance.
Try this,
BOOL isFar=TRUE;
- (void)locationManager:(CLLocationManager *)manager
didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region{
if (self.beaconRegion) {
if([beacons count] > 0)
{
//get closes beacon and find its major
CLBeacon *beacon = [beacons objectAtIndex:0];
switch (beacon.proximity)
{
case CLProximityUnknown:
break;
case CLProximityImmediate:
NSLog(#"Immediate");
if (isFar) {
isFar=false;
// Call WebService
}
break;
case CLProximityNear:
if (isFar) {
// Call WebService
}
isFar=false;
break;
case CLProximityFar:
NSLog(#"far");
if (!isFar) {
// call websercie
}
isFar=TRUE;
break;
default:
break;
}
}
}
}

Why are transactions being updated on startup?

I'm learning how to use in-app purchases and recently implemented it in my first app. To test it out on my phone, I created two test accounts and bought one item with each account, both different. When I delete the app and reopen it, it attempts to restore the data of both accounts and provides the upgrades regardless of whether I sign in or not. (paymentQueue: updatedTransactions: is being called and passing a transaction in the state SKPaymentTransactionStateRestored)
Could this be solved by validating the receipts? I've looked into it but have been putting it off since it looks a little daunting. Hopefully this is only a problem when testing multiple accounts.
For reference, I followed this guide but did the Transaction Observer methods in the App Delegate and the Product Request in a custom class. I also never reorded the transactions because apparently that's outdated. http://troybrant.net/blog/2010/01/in-app-purchases-a-full-walkthrough/
edit: I was just doing some testing and found that there are 0 transactions on the queue on startup right after being added as an observer but after the uidatedTransactions gets called there are 3.
My code for reference (Sorry if it's bad I'm still new):
#pragma mark - SKPaymentTransactionObserver
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
NSLog(#"Transactions Count: %d", [[[SKPaymentQueue defaultQueue] transactions] count]);
for (SKPaymentTransaction *transaction in transactions) {
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchased:
[self comleteTransaction:transaction];
break;
case SKPaymentTransactionStateRestored:
[self restoreTransaction:transaction];
break;
case SKPaymentTransactionStateFailed:
[self failedTransaction:transaction];
break;
default:
break;
}
}
}
//case methods
- (void)comleteTransaction:(SKPaymentTransaction *)transaction
{
[self provideContent:transaction.payment.productIdentifier];
[self finishTransaction:transaction wasSuccessful:YES];
}
- (void)restoreTransaction:(SKPaymentTransaction *)transaction
{
[self provideContent:transaction.originalTransaction.payment.productIdentifier];
[self finishTransaction:transaction.originalTransaction wasSuccessful:YES];
}
- (void)failedTransaction:(SKPaymentTransaction *)transaction
{
if (transaction.error.code != SKErrorPaymentCancelled)
[self finishTransaction:transaction wasSuccessful:NO]; //serious error
else
[[SKPaymentQueue defaultQueue] finishTransaction:transaction]; //user cancelled
}
//action methods
- (void)provideContent:(NSString *)productID
{
//validate app receipt?
if ([productID isEqualToString:UNLOCK_EVERYTHING_ID])
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:UNLOCK_EVERYTHING_PURCHASED_KEY];
else if ([productID isEqualToString:REMOVE_ADS_ID])
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:REMOVE_ADS_PURCHASED_KEY];
else if ([productID isEqualToString:BASIC_PACK_ID])
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:BASIC_PACK_PURCHASED_KEY];
else if ([productID isEqualToString:CLOTHING_PACK_ID])
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:CLOTHING_PACK_PURCHASED_KEY];
else if ([productID isEqualToString:FOOD_PACK_ID])
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:FOOD_PACK_PURCHASED_KEY];
else if ([productID isEqualToString:ORIGINAL_PACK_ID])
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:ORIGINAL_PACK_PURCHASED_KEY];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (void)finishTransaction:(SKPaymentTransaction *)transaction wasSuccessful:(BOOL)wasSuccessful
{
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
//post notification that transaction finished
if (wasSuccessful) {
[[NSNotificationCenter defaultCenter] postNotificationName:TRANSACTION_SUCCESSFUL object:nil];
} else {
[[NSNotificationCenter defaultCenter] postNotificationName:TRANSACTION_UNSUCCESSFUL object:nil];
}
}
I didn't look at the tutorial, but if any part of the purchase process adds details to the keychain, deleting the app and reinstalling it will leave keychain entries intact. The app is probably checking purchase status... see here
iphone keychain items persist after application uninstall?
If anyone else is experiencing the same problem, I just solved it on my own by changing the RestoreState case to do the same thing as PurchasedState case. Turns out that using the original transaction to make the restore was unnecessary and just caused problems.

How to get List of Only Purchased Product Ids fron inApp in ios?

I am having an app in which I have 5 Non Consumable In App Purchases.
On every Single In App Purchase I Update my DB with the images.
There are 5 Packages for 5 Non Consumable In App Purchases.
Now there is a Restore Purchase Functionality as it is a Non Consumable In App Purchase.
There is a single Restore Button in my app. But How to identify that Which Product has already being purchased?
I use the following code for restoring in app purchase. But it doesn't update my DB because it doesn't know which products are previously purchased.
if ([transaction.payment.productIdentifier isEqualToString:#"Pack1"])
{
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedp1Once"])
{
// app already launched
NSLog(#"Launching secondtime");
}
else
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedp1Once"];
NSLog(#"Launching first time");
requestText= #"Animal";
[self MakeQueryForUpdate];
[self getdata];
}
}
else if ([transaction.payment.productIdentifier isEqualToString:#"Pack2"])
{
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedp2Once"])
{
// app already launched
NSLog(#"Launching secondtime");
}
else
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedp2Once"];
NSLog(#"Launching first time");
requestText= #"Celebrity";
[self MakeQueryForUpdate];
[self getdata];
}
}
else if ([transaction.payment.productIdentifier isEqualToString:#"Pack3"])
{
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedp3Once"])
{
// app already launched
NSLog(#"Launching secondtime");
}
else
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedp3Once"];
NSLog(#"Launching first time");
requestText= #"Nature";
[self MakeQueryForUpdate];
[self getdata];
}
}
How to get list of only purchased Product Ids?
Any help will be appreciated...
You can restore the purchases by using :
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
then SKPaymentTransactionObserver will call its
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
with the SKPaymentTransactionStatePurchased transaction state. You can see that it returns an Array for the transactions.
You can get a single transaction using,
for (SKPaymentTransaction * transaction in transactions) {
NSLog(#"Purchased indentifier : %#", transaction.payment.productIdentifier);
}
This will print out the identifiers that the user have purchased. You can set your NSUserDefaults regarding to these values
For getting list of purchased products, you can call below function :
[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
This will return the list of previously purchased items.
You can find more details here and here is the apple's documentation.

Resources