Following in app purchase, app crashing on startup. productIdentifier=nil? Following in app purchase, app crashing on startup. productIdentifier=nil? ios ios

Following in app purchase, app crashing on startup. productIdentifier=nil?


I've run into a similar issue when the transaction is in the SKPaymentTransactionStateRestored. My testing has indicated this might be an issue with IOS 7.0.3, but I have not been able to verify this.

StoreKit keeps a persistent list of transactions that your application must finish. As you've noted the transaction will be reported on every startup until it is finished.

The solution that we implemented is to check if the product identifier is nil before usage from the entry point:

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

Even when we received a transaction with a nil product identifier we were able to successfully call finishTransaction.

I hope this helps.


One of my users complained four days ago about the same problem and was able to send me a crash log. He uses iOS 7.0.3 on iPhone 5,2. Crash occurs after identifying a SKPaymentTransactionStateRestored while trying to build a dictionary with the productIdentifier property from originalTransaction.payment:

NSDictionary* userInfoDict = @{@"productID":transaction.payment.productIdentifier};

I think that either originalTransaction or its properties payment or productIdentifier is nil. I stored the productIdentifier from transaction.payment.productIdentifier instead from transaction.originalTransaction.payment.productIdentifier while restoring and use that as productIdentifier from then on:

case SKPaymentTransactionStateRestored:{  NSString *productID = transaction.originalTransaction.payment.productIdentifier;  if (!productID) {    productID = transaction.payment.productIdentifier;  }  [self handlePurchaseSuccessful:transaction.originalTransaction productIdentifier:productID];}

Still waiting for review / feedback if that fixes the issue.


Elaborating on Shawn's answer, in - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions you probably have some code like this:

- (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) restoreTransaction: (SKPaymentTransaction *)transaction{       /* Handle restore here */    [[SKPaymentQueue defaultQueue] finishTransaction: transaction]; }

You can handle nil productIdentifiers in restoreTransaction: by adding a check to see if the productIdentifier is nil, like this:

- (void) restoreTransaction: (SKPaymentTransaction *)transaction{       if (!transaction.originalTransaction.payment.productIdentifier) {        NSLog(@"productIdentifier is nil; Apple bug?");        [[SKPaymentQueue defaultQueue] finishTransaction: transaction];        return;    }    /* Handle restore here */    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];}

This technique fixed the problem for me in my app. The app started, logged "productIdentifier is nil; Apple bug?" and didn't crash. When I then manually re-restored transactions, Apple sent a valid transaction, and the app worked as designed.