tecnico soporte recuperar puedo olvide iforgot como cancelar bloqueado bill apple activar iphone in-app-purchase

iphone - recuperar - soporte icloud



La transacción vuelve después de finishTransaction: se ha llamado en ella (10)

Estoy usando la compra en la aplicación para una aplicación de iPhone. Tengo una clase que actúa como SKProductsRequestDelegate y SKPaymentTransactionObserver , y todo funciona bien en la versión disponible actualmente en iTunes.

Sin embargo, después de agregar recientemente un nuevo producto no consumible y probarlo en el entorno de Sandbox, ahora me encuentro con un problema extraño. Cada vez que abro la aplicación, la compra que hice ayer reaparece en la lista de transacciones que me pasó con paymentQueue:updatedTransactions: pesar de que ya había llamado [[SKPaymentQueue defaultQueue] finishTransaction:transaction] (varias veces). ¡Es un no-muerto!

En mi paymentQueue:updatedTransactions: implementacion, tengo:

for (SKPaymentTransaction* transaction in transactions) switch (transaction.transactionState) { case SKPaymentTransactionStatePurchased: case SKPaymentTransactionStateRestored: { .... DDLog(@"Transaction for %@ occurred originally on %@.", transaction.payment.productIdentifier, transaction.originalTransaction.transactionDate); ....

Luego proceso la compra, descargo el contenido del usuario y, finalmente, en otro método, hago esto:

for (SKPaymentTransaction* transaction in [[SKPaymentQueue defaultQueue] transactions]) if (([transaction.payment.productIdentifier isEqualToString:theParser.currentProductID]) && ((transaction.transactionState==SKPaymentTransactionStatePurchased) || (transaction.transactionState==SKPaymentTransactionStateRestored)) ) { DDLog(@"[[ Transaction will finish: product ID = %@; date = %@ ]]", transaction.payment.productIdentifier, transaction.transactionDate); [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; }

Como habrá notado, no me aferro al objeto de transacción original por simplicidad, y es relativamente fácil encontrarlo más adelante desde la llamada a [[SKPaymentQueue defaultQueue] transactions] . En cualquier caso, de hecho veo el resultado esperado; que la transacción se haya completado y que coincida exactamente con el ID del producto y la fecha de la transacción original. Sin embargo, la próxima vez que ejecute la aplicación, todo volverá a empezar. Es como si iTunes Store nunca fue notificado de que la transacción se completó, o se niega a reconocerla.


Comprueba que no estás simplemente agregando el observador varias veces. Tuve el mismo problema con varias Transacciones actualizadas, pero luego noté que estaba agregando un nuevo observador cada vez en didBecomeActive. Y se llamaba una vez cada vez que, por ejemplo, restauraba las compras en sandbox.


Ese problema me pasó a mí también, encontré una solución. Eso puede ayudarte en casos similares.

Llamé a finishTransaction inmediato, pero la próxima vez que intente comprar algo, ¡el producto anterior también vendría! Así que la primera vez, estaba comprando un producto. Pero en la segunda vez, compré el segundo producto y el primero también.

¡Descubrí que estoy agregando SKPaymentTransactionObserver varias veces! Eso estaba causando el problema, haciendo múltiples compras.

Cuando finaliza el proceso, quiero decir cuando llama a finishTransaction , justo después de eso, llame a: [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];

Eso borrará las transacciones y eliminará al observador. Así que la próxima vez, no harás compras múltiples.


Estaba teniendo el mismo problema exacto.

Basándome en las respuestas, hice algunos experimentos y descubrí que si mantenía una referencia a la Cola, el problema desaparecía.

Por ejemplo:

// myStoreManagerClass.h
...
SKPaymentQueue *_myQueue;
...

//myStoreManagerClass.m
...
if(_myQueue == nil) {
_myQueue = [[SKPaymentQueue defaultQueue];
}
...

Luego me aseguré de que todos mis métodos usaran mi referencia de variable de instancia. Desde que se hizo eso, el problema se ha resuelto.


Este problema también se planteó en los foros de desarrolladores, y la conclusión general fue que se trataba de una diferencia en el manejo de transacciones en iPhone OS 4.0. El problema parece ocurrir solo cuando hay un retraso significativo entre recibir una notificación de la transacción finalizada y llamar a finishTransaction en la cola de pago. Al final no encontramos una solución ideal, pero lo que hicimos fue esto:

  1. Tan pronto como llegue la transacción, procesarla y registrar un valor en las preferencias del usuario si el procesamiento fue exitoso.

  2. La próxima vez que la transacción aparezca en la cola, que puede no ser hasta el próximo lanzamiento de la aplicación, llame inmediatamente a finishTransaction .

Nuestros productos son "no consumibles", por lo que es suficiente para verificar que el producto pagado sea válido y sin errores para ignorar de forma segura cualquier transacción repetida "no muerta" de iTunes. Para los productos consumibles, sería necesario guardar más información sobre la compra, como la fecha de pago original, para asegurarse de que las notificaciones de transacciones futuras puedan coincidir con las compras que ya se procesaron.


Me pregunto, ¿se garantiza que el valor defaultQueue de la cola sea la misma cola que se pasa en paymentQueue:updatedTransactions: :? Si no es así, entonces quizás el problema sea al llamar a finishTransaction en una SKPaymentQueue diferente a la que originó la transacción.


No he profundizado mucho en esto, pero estaba viendo mis llamadas para finalizar Transacción fallando de manera confiable en iOS 4. En una corazonada puse la llamada para terminar Transacción en una llamada dispatch_async y el problema desapareció.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) { [[SKPaymentQueue defaultQueue] finishTransaction: transaction]; });

Quizás un punto importante es que estaba llamando a finalización de transacción desde un bloque que finalmente se ejecutó después de una llamada de red a mi servidor.


Posiblemente es causada por múltiples observadores. No creas que estás a salvo simplemente eliminando el observador en dealloc.

Usted llamó [[SKPaymentQueue defaultQueue] addTransactionObserver:self] en viewDidLoad y [[SKPaymentQueue defaultQueue] removeTransactionObserver:self] en dealloc . Crees que estás a salvo como yo, pero no lo estás.

En realidad, si compra algo, finaliza la transacción, lo elimina de la cola de pagos, saca este controlador de vista del controlador de vista de navegación, luego ingresa al controlador de vista nuevamente, probablemente tenga múltiples observadores de transacciones.

Cada vez que presiona este controlador de vista, está agregando el controlador de vista como transactionObserver, pero cada vez que abre este controlador de vista no garantiza que esté eliminando el controlador de vista de transactionObservers.

De alguna manera, no se llama al dealloc de un controlador de vista incluso si se abre el controlador de vista. Así que el controlador de vista todavía está observando en la oscuridad.

Creo que la mejor solución para esta situación es detectar si este controlador de vista está visible cuando procesa la transacción.

Simplemente agregue esto antes de procesar la transacción, funciona para mí:

if ( !self.view.window) { return; }

Se hace referencia a la detección visible desde here .

PD. Tal vez poner / eliminar transactionObserver en viewWillAppear / viewWillDisappear es otra forma de resolverlo, pero debe controlar con cuidado el teclado para mostrar / ocultar eventos en caso de que el usuario necesite una contraseña de tipo.


Tuve el mismo problema pero lo resolví.

Aquí está mi código:

- (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]; break; default: break; } } } - (void)completeTransaction:(SKPaymentTransaction *)transaction { NSLog(@"completeTransaction... %@", [[transaction class] description]); [self provideContentForProductIdentifier:transaction]; } - (void)restoreTransaction:(SKPaymentTransaction *)transaction { NSLog(@"restoreTransaction..."); [self provideContentForProductIdentifier:transaction.originalTransaction]; }

Entonces estaba llamando a finishTransaction: método dentro del método provContentForProductIdentifier:. Y en el caso de la transacción de restauración, llamaba finishTransaction: al objeto OriginalTransaction, no a la transacción en sí.

Resolví mi problema por este código (método restoreTransaction :)

- (void)restoreTransaction:(SKPaymentTransaction *)transaction { NSLog(@"restoreTransaction..."); //Pass the main transaction object. [self provideContentForProductIdentifier:transaction]; }


Utilizo este código y me funciona

if ([[SKPaymentQueue defaultQueue].transactions count] > 0) { for (SKPaymentTransaction *transaction in [SKPaymentQueue defaultQueue].transactions) { @try { [[SKPaymentQueue defaultQueue] finishTransaction: transaction]; } @catch (NSException *exception) { NSLog([NSString stringWithFormat:@"%@", exception.reason]); } } }


Yo tuve este problema también. El error resultó estar de mi lado. El problema era que había una transacción pasada al acecho que se había ejecutado (el contenido proporcionado) pero que no se había limpiado utilizando finishTransaction . Desafortunadamente, al preguntar en varios lugares, incluyendo un TSI de Apple, descubrí que no había forma de encuestar tales transacciones "no-muertas"; solo tenía que registrarse para paymentQueue:updatedTransactions: notificaciones y esperar el correspondiente paymentQueue:updatedTransactions: Esto complicó mi código, pero no por mucho.

Lo que hago ahora, que ha funcionado bien:

  • Cuando la tienda está a punto de ser invocada (está publicando algunas diapositivas de marketing, tal vez un término de uso), busque su lista de productos y regístrese para [[SKPaymentQueue defaultQueue] addTransactionObserver:self] notificaciones como observador a través de [[SKPaymentQueue defaultQueue] addTransactionObserver:self]
  • Mantenga una variable de estado que se actualiza a SÍ cuando empuja un pago en la cola usando [[SKPaymentQueue defaultQueue] addPayment:payment]
  • Cuando reciba una notificación de una compra exitosa a través de paymentQueue:updatedTransactions: verifique la variable de estado. Si no se ha establecido, significa que ha recibido una notificación por un pago anterior. En ese caso, honre ese pago en lugar de presionar uno nuevo.

Este método naturalmente supone que tienes tiempo para esperar a que aparezcan las transacciones antiguas antes de comenzar una nueva transacción.