Right now the final step in finishing my app comes with finishing the in App Purchases.
I think i'm really close to finishing but there is something fundamental I am missing to get over the line.
I have my code set up so that with sandbox testing I can succesfully buy the non-consumable product which unlocks a new view.
The only problem I am having is that if I purchase one non-consumable, shutdown my app, re open it and restore the purchase, as soon as I have done that all other in app purchases can be restored without even purchasing them. Meaning once one product is bought and restored something in my code unlocks all other in app purchases for free.
Now I think I know where something needs to be put but i'm just not sure exactly what it is.
For the code i'll show you two seperate in app purchases and hopefully you'll be able to see something that is either missing or is just wrong.
First is the Rap Genre purchase view controller:
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:(BOOL)animated];
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}
- (IBAction)Restore:(id)sender {
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
}
- (IBAction)Buy:(id)sender {
SKPayment *payment = [SKPayment paymentWithProduct:_product];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
-(void)getProductID:(ViewController *)viewController {
_homeController = viewController;
if ([SKPaymentQueue canMakePayments]) {
SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:
[NSSet setWithObject:self.productID]];
request.delegate = self;
[request start];
} else
_ProductDescription.text = @"Please enable in app purchase within your settings";
}
-(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
NSArray *products = response.products;
/
if (products.count !=0) {
_product = products[0];
_ProductTitle.text = _product.localizedTitle;
_ProductDescription.text = _product.localizedDescription;
_buyButton.enabled = YES;
} else {
_ProductTitle.text = @"Product not found";
}
products = response.invalidProductIdentifiers;
for (SKProduct *product in products) {
NSLog(@"%@", product);
}
}
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions {
for (SKPaymentTransaction *transaction in transactions) {
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchased:[self UnlockPurchase];
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
case SKPaymentTransactionStateFailed:NSLog(@"Failed");
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
case SKPaymentTransactionStateRestored:
[self UnlockPurchase];
NSLog(@"Transaction state -> Restored");
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
default:
break;
}
}
}
-(void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue {
NSLog(@"received restored transactions: %lu", (unsigned long)queue.transactions.count);
for (SKPaymentTransaction *transaction in queue.transactions) {
if (transaction.transactionState == SKPaymentTransactionStateRestored) {
NSLog(@"Transaction State -> Restored");
/
/
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
}
}
}
-(void)UnlockPurchase {
/
_buyButton.enabled = NO;
[_buyButton setTitle:@"Purchased" forState:UIControlStateDisabled];
[_homeController Purchased];Then the Country Genre:
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:(BOOL)animated];
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}
- (IBAction)RestoreCountry:(id)sender {
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
}
- (IBAction)BuyCountry:(id)sender {
SKPayment *payment = [SKPayment paymentWithProduct:_countryProduct];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
-(void)getCountryProductID:(ViewController *)viewController {
_homeController = viewController;
if ([SKPaymentQueue canMakePayments]) {
SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:self.countryProductID]];
request.delegate = self;
[request start];
} else
_countryProductDescription.text = @"Please enable in app purchase within your settings";
}
-(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
NSArray *products = response.products;
if (products.count !=0) {
_countryProduct = products[0];
_countryProductTitle.text = _countryProduct.localizedTitle;
_countryProductDescription.text = _countryProduct.localizedDescription;
_countryBuyButton.enabled = YES;
} else {
_countryProductTitle.text = @"Product not found";
}
products = response.invalidProductIdentifiers;
for (SKProduct *product in products) {
NSLog(@"%@", product);
}
}
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions {
for (SKPaymentTransaction *transaction in transactions) {
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchased:[self UnlockCountryPurchase];
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
case SKPaymentTransactionStateFailed:NSLog(@"Failed");
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
case SKPaymentTransactionStateRestored:
[self UnlockCountryPurchase];
NSLog(@"Transaction state -> Restored");
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
default:
break;
}
}
}
-(void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue {
NSLog(@"received restored transactions: %lu", (unsigned long)queue.transactions.count);
for (SKPaymentTransaction *transaction in queue.transactions) {
if (transaction.transactionState == SKPaymentTransactionStateRestored) {
NSLog(@"Transaction State -> Restored");
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
}
}
}
-(void)UnlockCountryPurchase {
/
_countryBuyButton.enabled = NO;
[_countryBuyButton setTitle:@"Purchased" forState:UIControlStateDisabled];
[_homeController PurchasedTwo];
}I believe i'm missing something within paymentQueueRestoreCompletedTransactionsFinished
that specifies exactly what should be restored and what shouldn't but i'm not sure how to implement it.`