Note that there are some explanatory texts on larger screens.

plurals
  1. POIn App purchase not work on device
    primarykey
    data
    text
    <p>I try to make in app purchase on my app. But I have not result when I try to run it in device.</p> <p>My code is following:</p> <p>This is object needed for get info about products and purchase it.</p> <p><strong>.h</strong></p> <pre><code>#import &lt;Foundation/Foundation.h&gt; #import "StoreKit/StoreKit.h" #define kProductsLoadedNotification @"ProductsLoaded" #define kProductPurchasedNotification @"ProductPurchased" #define kProductPurchaseFailedNotification @"ProductPurchaseFailed" @interface StoreManager : NSObject &lt;SKProductsRequestDelegate, SKPaymentTransactionObserver&gt; @property (strong, nonatomic) NSMutableSet * _purchasedProducts; @property (strong, nonatomic) NSArray *products; @property (strong, nonatomic) NSSet *_productIdentifiers; @property (strong, nonatomic) SKProductsRequest *request; - (id)initWithProductIdentifiers:(NSSet *)productIdentifiers; - (void)requestProducts; - (void)buyProduct:(SKProduct *)product; - (void)completeTransaction:(SKPaymentTransaction *)transaction; - (void)restoreTransaction:(SKPaymentTransaction *)transaction; - (void)failedTransaction:(SKPaymentTransaction *)transaction; - (void)provideContent:(NSString *)productIdentifier; - (void)recordTransaction:(SKPaymentTransaction *)transaction; @end </code></pre> <p><strong>.m</strong></p> <pre><code>#import "StoreManager.h" @implementation StoreManager @synthesize _purchasedProducts; @synthesize products; @synthesize _productIdentifiers; @synthesize request; // Initializes the request object with the set of product identifiers. - (id)initWithProductIdentifiers:(NSSet *)productIdentifiers{ self = [super init]; if(self){ self._productIdentifiers = productIdentifiers; NSMutableSet *purchased = [NSMutableSet set]; for(NSString * productId in self._productIdentifiers){ BOOL flag = [[NSUserDefaults standardUserDefaults] boolForKey:productId]; if(flag){ [purchased addObject:productId]; NSLog(@"Previously purchased: %@", productId); } NSLog(@"Not purchased: %@", productId); } self._purchasedProducts = purchased; } return self; } // Request info for the product. - (void)requestProducts{ self.request = [[SKProductsRequest alloc] initWithProductIdentifiers:self._productIdentifiers]; self.request.delegate = self; [self.request start]; } // Request fail. - (void)request:(SKRequest *)request didFailWithError:(NSError *)error{ NSLog(@"Fail request! Error: %@", error); } // Delegate method - did receive responce. - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{ self.products = response.products; self.request = nil; [[NSNotificationCenter defaultCenter] postNotificationName:kProductsLoadedNotification object:self.products]; } // Buy product. - (void)buyProduct:(SKProduct *)product{ SKPayment *payment = [SKPayment paymentWithProduct:product]; [[SKPaymentQueue defaultQueue] addPayment:payment]; } // Payment transactions - (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)recordTransaction:(SKPaymentTransaction *)transaction { // TODO: Record the transaction on the server side... } - (void)completeTransaction:(SKPaymentTransaction *)transaction{ [self recordTransaction: transaction]; [self provideContent: transaction.payment.productIdentifier]; NSLog(@"completeTransaction..."); } - (void)provideContent:(NSString *)productIdentifier { NSLog(@"Toggling flag for: %@", productIdentifier); [[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:productIdentifier]; [[NSUserDefaults standardUserDefaults] synchronize]; [self._purchasedProducts addObject:productIdentifier]; [[NSNotificationCenter defaultCenter] postNotificationName:kProductPurchasedNotification object:productIdentifier]; } - (void)restoreTransaction:(SKPaymentTransaction *)transaction { NSLog(@"restoreTransaction..."); [self recordTransaction: transaction]; [self provideContent: transaction.originalTransaction.payment.productIdentifier]; [[SKPaymentQueue defaultQueue] finishTransaction: transaction]; } - (void)failedTransaction:(SKPaymentTransaction *)transaction { if (transaction.error.code != SKErrorPaymentCancelled) { NSLog(@"Transaction error: %@", transaction.error.localizedDescription); } [[NSNotificationCenter defaultCenter] postNotificationName:kProductPurchaseFailedNotification object:transaction]; [[SKPaymentQueue defaultQueue] finishTransaction: transaction]; } @end </code></pre> <p>Singleton object</p> <p><strong>.h</strong></p> <pre><code>#import &lt;Foundation/Foundation.h&gt; #import "StoreManager.h" @interface StoreWrapper : StoreManager + (StoreWrapper *)sharedInstance; @end </code></pre> <p><strong>.m</strong></p> <pre><code>#import "StoreWrapper.h" @implementation StoreWrapper static StoreWrapper *gInstance = NULL; - (id)init{ NSSet *productId = [NSSet setWithObjects:@"com.company.sb.pack1", @"com.company.sb.pack5", nil]; self = [super initWithProductIdentifiers:productId]; if(self){ } return self; } + (StoreWrapper *)sharedInstance{ if(gInstance == NULL){ gInstance = [[self alloc] init]; } return gInstance; } @end </code></pre> <p>In the my view controller i call next:</p> <pre><code>- (void)viewWillAppear:(BOOL)animated { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(productsLoaded:) name:kProductsLoadedNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(productPurchased:) name:kProductPurchasedNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector: @selector(productPurchaseFailed:) name:kProductPurchaseFailedNotification object: nil]; Reachability *reach = [Reachability reachabilityForInternetConnection]; NetworkStatus netStatus = [reach currentReachabilityStatus]; if (netStatus == NotReachable) { NSLog(@"No internet connection!"); } else { NSLog(@"Internet connection available!"); // Request product [[StoreWrapper sharedInstance] requestProducts]; [activIndicator startAnimating]; } [super viewWillAppear:animated]; } </code></pre> <p>for this point I send an request for get product info from server with my product id</p> <p>next if product loaded my class get notification about this (and call following method).</p> <pre><code>- (void)productsLoaded:(NSNotification *)notification{ [activIndicator stopAnimating]; [activIndicator setHidden:YES]; NSArray *arr = [notification object]; for(int i = 0; i &lt; [arr count]; i++){ SKProduct *product = [[StoreWrapper sharedInstance].products objectAtIndex:i]; UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect]; [btn setFrame:CGRectMake(0, i*55, 100, 50)]; [btn setTitle:product.localizedTitle forState:UIControlStateNormal]; [btn setTag:i]; [btn addTarget:self action:@selector(buyProduct:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:btn]; } } </code></pre> <p>For the button i add selector buyProduct (as shown above)</p> <pre><code>- (void)buyProduct:(id)sender{ NSLog(@"sender tag %d", [sender tag]); int tag = [sender tag]; SKProduct *product = [[StoreWrapper sharedInstance].products objectAtIndex:tag]; [[StoreWrapper sharedInstance] buyProduct:product]; } </code></pre> <p>For iPhone Simulator this work wonderful, but on device I don have any button, because response.products not download.</p> <p>All method are called, but delegate method <strong>*- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse <em>)response</em></strong> not return response.products.</p> <p>Thanks for your time and thanks for answer!</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload