Verify IAP receipt

I'm working on an App like Lovoo. So I want to implement consumable and non-consumable IAPs. After I buy a product I request the receipt from NSBundle.mainBundle().appStoreReceiptURL. I upload it to my server and PHP verifies it with the Apple server. Then my server gives a responst to my App with the number of credits the user owns now. The problem is, I only get old receipts from the Apple server which are several days old. So when I buy a product, I activate the products I bought yesterday but not the one I bought right now. How can I get the current receipt from the Apple server to provide the content?

Answered by PBK in 56259022

You get the current receipt by

      SKReceiptRefreshRequest *request=[[SKReceiptRefreshRequest alloc] init];
      [request setDelegate:self];
      [request start];

-(void)requestDidFinish:(SKRequest *)request{
    if([request isKindOfClass:[SKReceiptRefreshRequest class]] ){
        NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
        if([[NSFileManager defaultManager] fileExistsAtPath:receiptURL.path]){
            [self testTheReceipt];
        }else{
            UIAlertView *noReceipt;
            noReceipt = [[UIAlertView alloc]
                               initWithTitle:nil
                               message:@"It appears that your app does not have a receipt.  This purchase cannot be verified."
                               delegate: nil
                               cancelButtonTitle:@"Sorry"
                               otherButtonTitles:nil ] ;
            [noReceipt show];
        }
    }
}


But you should already have a refreshed receipt when StoreKit calls

-(void) paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{

After StoreKit calls your delegate's updatedTransactions method the receipt will contain all IAP products the user has purchased (non consumables) and the most recent IAP consumable. It isn't a 'yesterday' information.

It didn't work. In updatedTransactions I call the method that sends the receipts to the server. I only get 1 receipt from today (but not the current one) and 4 old ones (10 days old).

Let's be clear -


a) there is only one receipt. You are saying the receipt does not contain the current purchase. That's quite unusual and incorrect - please report it as a bug.

b) You wrote - "I call the method that sends the receipts to the server" - there is no such method. You are using someone's code to do that. I suspect that code is sending an old archived receipt.


Note that the one receipt contains the following purchases:

1) all non-consumable items ever purchased by that iTunes Account in this app

2) all non-renewing subscriptions "

3) all autorenewable subscriptiosn and each renewal "

4) the latest consumable purchase

5) sometimes, but not always, all previous consumable purchases "

a) I already reported it as a bug. I didn't get any answer yet.


b) Yes, the is a method that sends the receipt to the server. Although this doesn't come from Apple it's there because I implemented it by my own. As I said, the function gets the receipt from NSBundle.mainBundle().appStoreReceiptURL. Is there another source, that gives the me the receipt with more recent IAPs? You wrote "I suspect that code is sending an old archived receipt." So if it ist possible to get an old archived receipt, it should also be possible to get the current one.

Accepted Answer

You get the current receipt by

      SKReceiptRefreshRequest *request=[[SKReceiptRefreshRequest alloc] init];
      [request setDelegate:self];
      [request start];

-(void)requestDidFinish:(SKRequest *)request{
    if([request isKindOfClass:[SKReceiptRefreshRequest class]] ){
        NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
        if([[NSFileManager defaultManager] fileExistsAtPath:receiptURL.path]){
            [self testTheReceipt];
        }else{
            UIAlertView *noReceipt;
            noReceipt = [[UIAlertView alloc]
                               initWithTitle:nil
                               message:@"It appears that your app does not have a receipt.  This purchase cannot be verified."
                               delegate: nil
                               cancelButtonTitle:@"Sorry"
                               otherButtonTitles:nil ] ;
            [noReceipt show];
        }
    }
}


But you should already have a refreshed receipt when StoreKit calls

-(void) paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{

omg, i made such a stupid mistake. The user chooses the product in an UICollectionView. In didSelectItemAtIndexPath I wrote


let product = self.products.objectAtIndex(indexPath.section) as! SKProduct


instead of


let product = self.products.objectAtIndex(indexPath.row) as! SKProduct


as there is only 1 section I always purchased the first product. I logged the receipt information and as the purchase time is always 2 hours before my local time I thought I would get only the purchase information of the first product, 2 hours ago. Now everything works. Sometimes a small mistake makes very big trouble.

Verify IAP receipt
 
 
Q