title: In-App purchase runs well in SandBox but rejected by review team
body: <p>We have been rejected by review team recently for a In-App Purchase issue.</p>
  
  <blockquote>
    <p>We discovered one or more bugs in your app when reviewed on iPhone
    running iOS 8.2 on both Wi-Fi and cellular networks. 
    Specifically,
    your application’s In App Purchase Transaction cannot be completed.
    The steps to reproduce are:</p>
    
    <ol>
    <li>Launch app</li>
    <li>Navigate to purchase/recharge tab</li>
    <li>Proceed to purchase one of the In-App Purchase products</li>
    <li>In-App Purchase confirmation window appears</li>
    <li>Confirm purchase</li>
    <li>In-App Purchase results in an error</li>
    </ol>
  </blockquote>
  
  <p>BUT! In-App Purchase runs well in sandbox! We checked log on our server, but we can't find any receipt verification logs. It seems that purchase completion window didn't appear at all.</p>
  
  <p>We found we would use the following code sometimes:</p>
  
  <pre><code>SKPayment *payment = [SKPayment paymentWithProductIdentifier:productIdentifier];
  [[SKPaymentQueue defaultQueue] addPayment:payment];
  </code></pre>
  
  <p>Is that the ONLY reason? T.T</p>
  
  <p>EDIT:
  We had released several versions before. This time we added a new product. But we forgot to add its identifier to the following array.</p>
  
  <pre><code>-(void)requestProducts
  {
      if (_products) {
          return;
      }
      NSSet* identifiers = [NSSet setWithObjects:
                            @"identifier",
                            @"new identifier",  // forgot this line
                            nil];
      SKProductsRequest* _request = [[SKProductsRequest alloc] initWithProductIdentifiers:identifiers];
      _request.delegate = self;
      [_request start];
      _requestProcessing = YES;
  }
  </code></pre>
  
  <p>So the following code will return nil:</p>
  
  <pre><code>-(SKProduct*)getProduct:(NSString *)identifier
  {
      if (_products) {
          for (SKProduct* product in _products) {
              if ([product.productIdentifier isEqualToString:identifier]) {
                  return product;
              }
          }
      } else if (!_requestProcessing) {
          [self requestProducts];
      }
      return nil;
  }
  </code></pre>
  
  <p>When user buy a product:</p>
  
  <pre><code>-(void)buyProductIdentifier:(NSString *)productIdentifier
  {
      if (![self isNetworkOK] || ![SKPaymentQueue canMakePayments]) {
          [[NSNotificationCenter defaultCenter] postNotificationName:NotifyPurchaseFailed object:productIdentifier];
          return;
      }
  
      NSLog(@"Buying %@...", productIdentifier);
      SKProduct* product = [self getProduct:productIdentifier];
      if (product) { // the new identifier gets nil here
          SKPayment* payment = [SKPayment paymentWithProduct:product];
          [[SKPaymentQueue defaultQueue] addPayment:payment];
      } else {  // calls the deprecated api
          SKPayment *payment = [SKPayment paymentWithProductIdentifier:productIdentifier];
          [[SKPaymentQueue defaultQueue] addPayment:payment];
      }
  }
  </code></pre>
  
  <p>BUT, it runs well in sandbox.</p>
  
  <pre><code>-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
  {
      for (SKPaymentTransaction *transaction in transactions)
      {
          switch (transaction.transactionState)
          {
              case SKPaymentTransactionStatePurchased:
                  [self completeTransaction:transaction];
                  break;
              case SKPaymentTransactionStateFailed: // may break here
                  [self failedTransaction:transaction];
                  break;
              case SKPaymentTransactionStateRestored:
                  [self restoreTransaction:transaction];
              default:
                  break;
          }
      }
  }
  </code></pre>
  
  <p>Any idea? All the products on itunes connect are in Approved state except the new one. The new product is in Waiting for Review state.</p>