bottom bar ios in-app-purchase null storekit

ios - bottom - status bar iphone



Siguiendo en la compra de la aplicaciĆ³n, la aplicaciĆ³n se bloquea en el inicio. productIdentifier=nil? (5)

Tengo algunos usuarios que informaron que después de intentar comprar una aplicación, la aplicación ahora se bloquea al iniciarse. Les pedí que eliminen y reinstalen la aplicación que no ha funcionado, y traté de pedirles que entren en modo avión para detener cualquier comunicación de red que no haya funcionado.

No puedo replicar el error de ninguna manera en mis dispositivos y la compra de la aplicación pasa muy bien en el modo de caja de arena y en los modos de producción. Mi idea es que, de alguna manera, su transacción recibió un identificador de producto nulo, lo que está causando el bloqueo del inicio, pero no estoy seguro de qué métodos de observación de la transacción se llaman al inicio de la aplicación y puedo solucionar el problema.

¿Hay alguna forma de "borrar" la cola de transacciones o, de lo contrario, probar si no hay ningún identificador de producto en el inicio y permitir que estos usuarios hagan que la aplicación se ejecute al menos otra vez? He realizado varios cientos de compras de aplicaciones utilizando el código siguiente y esto acaba de comenzar a suceder. ¿A cuál de los métodos de ayuda se llama en el inicio de la aplicación?

En AppDelegate.m

[[SKPaymentQueue defaultQueue] addTransactionObserver:[MovieClockIAPHelper sharedHelper]];

En el código de ayuda de la aplicación:

- (id)initWithProductIdentifiers:(NSSet *)productIdentifiers { if ((self = [super init])) { // Store product identifiers _productIdentifiers = [productIdentifiers retain]; // Check for previously purchased products NSMutableSet * purchasedProducts = [NSMutableSet set]; for (NSString * productIdentifier in _productIdentifiers) { BOOL productPurchased = [[NSUserDefaults standardUserDefaults] boolForKey:productIdentifier]; if (productPurchased) { [purchasedProducts addObject:productIdentifier]; NSLog(@"Previously purchased: %@", productIdentifier); } else{ NSLog(@"Not purchased: %@", productIdentifier); } } self.purchasedProducts = purchasedProducts; } return self; } - (void)requestProducts { self.request = [[[SKProductsRequest alloc] initWithProductIdentifiers:_productIdentifiers] autorelease]; _request.delegate = self; [_request start]; } - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response { NSLog(@"Received products results..."); self.products = response.products; self.request = nil; [[NSNotificationCenter defaultCenter] postNotificationName:kProductsLoadedNotification object:_products]; } - (void)restoreCompletedTransactions { [[SKPaymentQueue defaultQueue] restoreCompletedTransactions]; } - (void)provideContent:(NSString *)productIdentifier { NSLog(@"Toggling flag for: %@", productIdentifier); [[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:productIdentifier]; [[NSUserDefaults standardUserDefaults] synchronize]; [_purchasedProducts addObject:productIdentifier]; [[NSNotificationCenter defaultCenter] postNotificationName:kProductPurchasedNotification object:productIdentifier]; } - (void)completeTransaction:(SKPaymentTransaction *)transaction { NSLog(@"completeTransaction..."); [self recordTransaction: transaction]; [self provideContent: transaction.payment.productIdentifier]; [[SKPaymentQueue defaultQueue] finishTransaction: transaction]; } - (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]; } - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions { NSLog(@"in the payment queue"); 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)buyProduct:(SKProduct *)product { NSLog(@"In buyproduct Buying %@...", product.productIdentifier); SKPayment *payment = [SKPayment paymentWithProduct:product]; [[SKPaymentQueue defaultQueue] addPayment:payment]; } - (void)dealloc { [_productIdentifiers release]; _productIdentifiers = nil; [_products release]; _products = nil; [_purchasedProducts release]; _purchasedProducts = nil; [_request release]; _request = nil; [super dealloc]; } @end


Al elaborar la respuesta de Shawn, en - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions que probablemente tenga algún código como este:

- (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]; }

Puede manejar cero productIdentifiers en restoreTransaction: agregando una comprobación para ver si el productIdentifier es nil, como esto:

- (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]; }

Esta técnica solucionó el problema para mí en mi aplicación. La aplicación se inició, se registró "productIdentifier is nil; Apple bug?" y no se estrelló. Cuando luego restauré manualmente las transacciones, Apple envió una transacción válida, y la aplicación funcionó como estaba diseñada.


Hace cuatro días, uno de mis usuarios se quejó del mismo problema y pudo enviarme un registro de fallos. Utiliza iOS 7.0.3 en iPhone 5,2. Se produce un bloqueo después de identificar un SKPaymentTransactionStateRestored al intentar crear un diccionario con la propiedad productIdentifier de originalTransaction.payment:

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

Creo que o bien originalTransaction o sus propiedades de pago o productIdentifier es nulo. Guardé el productIdentifier de transaction.payment.productIdentifier en lugar de transaction.originalTransaction.payment.productIdentifier mientras lo restauraba y lo utilizaba como productIdentifier a partir de entonces:

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

Todavía estoy esperando revisión / retroalimentación si eso arregla el problema


Me he encontrado con un problema similar cuando la transacción está en el SKPaymentTransactionStateRestored. Mis pruebas indicaron que esto podría ser un problema con IOS 7.0.3, pero no he podido verificarlo.

StoreKit mantiene una lista persistente de transacciones que su aplicación debe finalizar. Como se ha señalado, la transacción se informará en cada inicio hasta que finalice.

La solución que implementamos es verificar si el identificador del producto es nulo antes del uso desde el punto de entrada:

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

Incluso cuando recibimos una transacción con un identificador de producto nulo, pudimos llamar a finishTransaction con éxito.

Espero que esto ayude.


Solucioné este problema tal como Marimba publicó anteriormente y ayudó a nuestros clientes:

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


Tuve el mismo problema paymentQueue:updatedTransactions: se llamaba con instancias de SKPaymentTransaction con un estado de SKPaymentTransactionStateRestored y un productIdentifier nil en la SKPaymentTransactionStateRestored originalTransaction .

Suena realmente raro y podría ser un error de SDK 7.0.3.

¿Todos ustedes todavía compilan con el SDK 6?

Estoy a punto de volver a enviar mi aplicación a la tienda para ver si el problema se soluciona, pero solo estoy terminando dichas transacciones, pero espero que se procesen otras transacciones con un identificador de producto válido ahora que la aplicación no se bloqueará para que sepa qué. para restaurar.