How to handle a production-signed app getting receipts from test environment?

I have an app that was rejected with this message:


“When validating receipts on your server, your server needs to be able to handle a production-signed app getting its receipts from Apple’s test environment. The recommended approach is for your production server to always validate receipts against the production App Store first. If validation fails with the error code “Sandbox receipt used in production,” you should validate against the test environment instead.”


When I run the app from Xcode using a test account, the purchase works fine in the sandbox. I also tried testing an ad-hoc build and it works using the test account too. I’ve submitted other apps with in-app purchase that basically use the same exact code and they were approved.


I’m not sure what “for your production server to always validate receipts” is talking about. The in-app purchase is done entirely within the app and doesn’t need to access my server for anything.


I have a class StoreObserver that implements SKPaymentTransactionObserver


- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
    for (SKPaymentTransaction *transaction in transactions) {
        switch (transaction.transactionState) {
           case SKPaymentTransactionStatePurchased:
                // this is where it goes when I test it
                break;
            case SKPaymentTransactionStateFailed:
                // somehow Apple review is getting here
                break;
            …
        }
    }
}


In the view controller to make the in-app purchase:


- (void)viewDidLoad {
    [super viewDidLoad];
    storeObserver = [[StoreObserver alloc] init];
    storeObserver.delegate = self;
    [[SKPaymentQueue defaultQueue] addTransactionObserver:storeObserver];
}

- (void) viewDidAppear:(BOOL)animated {
    SKProductsRequest *request= [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObjects:@“productid”,nil]];
    request.delegate = self;
    [request start];
}

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
    product = [response.products objectAtIndex:0];
    // show button for in-app purchase
}

// handle button click to make in-app purchase
- (IBAction) purchaseClick:(id)sender {
    [SKPayment *payment = [SKPayment paymentWithProduct:product];
    [[SKPaymentQueue defaultQueue] addPayment:payment];
}


What do I need to do to make this work?

First, App Review is speculating that the reason why your code is failing is because you are trying to validate the App Review receipt that is sent to your app using Apple's production website server. The reason why you would want to do that is because the reral app will get receipts that are validated on the production website server. But during App Review that app, which will soon be receiving and validating production receipts, needs to be able to validate a sandbox receipt sent to it by App Review. The standard procedure is to first test against production and, if that fails, test against sandbox.


But your problem is different. It sounds like your code can't handle a failed transaction followed shortly (i.e. less than a second) by a purchased transaction. This happens whenever a person goes to buy an IAP and when they get to the App Store they need to update their cerdit card or account information. After updating their info they are given the opportunity of going forward with the IAP. If they do that then the App Store sends two transactions to the App in quick succession; a failed and a purchased.

How to handle a production-signed app getting receipts from test environment?
 
 
Q