Flutter - Gestionar eventos de flow y paywall
Esta guía cubre el manejo de eventos para compras, restauraciones, selección de productos y renderizado. Cerrar la vista y abrir enlaces se gestiona mediante la implementación predeterminada de flowViewDidPerformAction — consulta nuestra guía sobre el manejo de acciones de botones para sobreescribirla o para manejar acciones de botones personalizados.
Los flows y paywalls configurados con el builder no necesitan código adicional para realizar y restaurar compras. Sin embargo, generan algunos eventos a los que tu app puede responder. Estos eventos incluyen pulsaciones de botones (botones de cierre, URLs, selecciones de productos, etc.), así como notificaciones sobre acciones relacionadas con compras realizadas en el flow o paywall. A continuación encontrarás cómo responder a estos eventos.
Para controlar o supervisar los procesos que ocurren en la pantalla del flow o paywall dentro de tu app, implementa los métodos de AdaptyUIFlowsEventsObserver y establece el observer antes de presentar cualquier pantalla:
AdaptyUI().setFlowsEventsObserver(this);Tres métodos de observer son obligatorios — tu clase no compilará sin ellos: flowViewDidFinishPurchase, flowViewDidFinishRestore y flowViewDidReceiveError. El resto de métodos son opcionales. Para desconectar un observer previamente configurado, pasa null a setFlowsEventsObserver.
¿Quieres ver un ejemplo real de cómo se integra el SDK de Adapty en una app móvil? Echa un vistazo a nuestras apps de ejemplo, que muestran la configuración completa, incluyendo la visualización de paywalls, la realización de compras y otras funcionalidades básicas.
Los ejemplos de eventos que aparecen a continuación muestran las propiedades disponibles en cada objeto, con valores ilustrativos en los comentarios.
Eventos generados por el usuario
View appeared
Este método se invoca cuando la vista del flow o el paywall aparece en pantalla.
En iOS, también se invoca cuando el usuario pulsa el botón de web paywall dentro de un paywall y el web paywall se abre en un navegador in-app.
void flowViewDidAppear(AdaptyUIFlowView view) {
}View disappeared
Este método se invoca cuando la vista del flow o el paywall se cierra en pantalla.
En iOS, también se invoca cuando un web paywall abierto desde un paywall en un navegador in-app desaparece de la pantalla.
void flowViewDidDisappear(AdaptyUIFlowView view) {
}Selección de producto
Si se selecciona un producto para su compra (por un usuario o por el sistema), se invocará este método:
void flowViewDidSelectProduct(AdaptyUIFlowView view, String productId) {
}Ejemplo de evento (Haz clic para expandir)
void flowViewDidSelectProduct(AdaptyUIFlowView view, String productId) {
// productId is a String:
productId; // 'premium_monthly'
}Compra iniciada
Si un usuario inicia el proceso de compra, se invocará este método:
void flowViewDidStartPurchase(AdaptyUIFlowView view, AdaptyPaywallProduct product) {
}Ejemplo de evento (haz clic para expandir)
void flowViewDidStartPurchase(AdaptyUIFlowView view, AdaptyPaywallProduct product) {
// product — AdaptyPaywallProduct:
product.vendorProductId; // 'premium_monthly'
product.localizedTitle; // 'Premium Monthly'
product.localizedDescription; // 'Premium subscription for 1 month'
product.price.amount; // 9.99 (double)
product.price.currencyCode; // 'USD'
product.price.localizedString; // '$9.99'
}Compra finalizada
Este método es obligatorio. Se invoca cuando una compra tiene éxito, el usuario cancela su compra, o la compra parece estar pendiente:
void flowViewDidFinishPurchase(AdaptyUIFlowView view,
AdaptyPaywallProduct product,
AdaptyPurchaseResult purchaseResult) {
switch (purchaseResult) {
case AdaptyPurchaseResultSuccess(profile: final profile):
// successful purchase
break;
case AdaptyPurchaseResultPending():
// purchase is pending
break;
case AdaptyPurchaseResultUserCancelled():
// user cancelled the purchase
break;
default:
break;
}
}Ejemplos de eventos (Haz clic para expandir)
void flowViewDidFinishPurchase(AdaptyUIFlowView view,
AdaptyPaywallProduct product,
AdaptyPurchaseResult purchaseResult) {
// product — AdaptyPaywallProduct:
product.vendorProductId; // 'premium_monthly'
switch (purchaseResult) {
case AdaptyPurchaseResultSuccess(profile: final profile):
// profile — AdaptyProfile:
profile.accessLevels['premium']?.isActive; // true
profile.accessLevels['premium']?.expiresAt; // DateTime(2027, 2, 15, 10, 30)
break;
case AdaptyPurchaseResultPending():
// no additional data
break;
case AdaptyPurchaseResultUserCancelled():
// no additional data
break;
}
}A diferencia de v3, este método no tiene un comportamiento predeterminado: la vista ya no se cierra automáticamente tras una compra exitosa. Decide tú mismo qué ocurre a continuación: continuar el flow o llamar a view.dismiss(). Consulta Responder a las acciones de los botones para más detalles sobre cómo cerrar una pantalla.
Navegación de pago web finalizada
Este método se invoca tras un intento de abrir un paywall web para un producto específico. Esto incluye tanto los intentos de navegación exitosos como los fallidos:
void flowViewDidFinishWebPaymentNavigation(AdaptyUIFlowView view,
AdaptyPaywallProduct? product,
AdaptyError? error) {
}Parámetros:
| Parámetro | Descripción |
|---|---|
| product | Un AdaptyPaywallProduct para el que se abrió el paywall web. Puede ser null. |
| error | Un objeto AdaptyError si la navegación del paywall web falló; null si la navegación fue correcta. |
Compra fallida
Este método se invoca cuando una compra falla (por ejemplo, debido a problemas de pago o errores de red). No se activa para cancelaciones iniciadas por el usuario ni para transacciones pendientes; esas las gestiona flowViewDidFinishPurchase:
void flowViewDidFailPurchase(AdaptyUIFlowView view,
AdaptyPaywallProduct product,
AdaptyError error) {
}Restauración iniciada
Si un usuario inicia el proceso de restauración, se invocará este método:
void flowViewDidStartRestore(AdaptyUIFlowView view) {
}Restauración exitosa
Este método es obligatorio. Si la restauración de una compra se completa con éxito, se invocará:
void flowViewDidFinishRestore(AdaptyUIFlowView view, AdaptyProfile profile) {
}Ejemplo de evento (haz clic para ampliar)
void flowViewDidFinishRestore(AdaptyUIFlowView view, AdaptyProfile profile) {
// profile — AdaptyProfile:
profile.accessLevels['premium']?.isActive; // true
profile.accessLevels['premium']?.expiresAt; // DateTime(2027, 2, 15, 10, 30)
profile.subscriptions['premium_monthly']?.isActive; // true
profile.subscriptions['premium_monthly']?.expiresAt; // DateTime(2027, 2, 15, 10, 30)
}Recomendamos cerrar la pantalla si el usuario tiene el accessLevel requerido. Consulta el tema Estado de la suscripción para aprender a verificarlo y el tema Responder a las acciones de los botones para aprender a cerrar una pantalla.
Restauración fallida
Si la restauración de una compra falla, se invocará este método:
void flowViewDidFailRestore(AdaptyUIFlowView view, AdaptyError error) {
}Obtención y renderizado de datos
Errores de carga de productos
Si no pasas el array de productos durante la inicialización, AdaptyUI recuperará los objetos necesarios del servidor por sí solo. Si esta operación falla, AdaptyUI notificará el error invocando este método:
void flowViewDidFailLoadingProducts(AdaptyUIFlowView view, AdaptyError error) {
}Errores de vista
Este método es obligatorio. Reemplaza el método paywallViewDidFailRendering de la v3: los errores que ocurren durante el renderizado de la interfaz, así como otros errores de la vista, se notifican llamando a este método. Una vez que lo implementes, el cierre de la vista queda a tu criterio — recomendamos cerrarla cuando se produzcan este tipo de errores, que es también lo que hace el comportamiento predeterminado del SDK cuando no hay ningún observador configurado:
void flowViewDidReceiveError(AdaptyUIFlowView view, AdaptyError error) {
// log the error and dismiss the broken view
view.dismiss();
}En condiciones normales, no deberían producirse errores de renderizado, así que si te encuentras con alguno, háznoslo saber.
Eventos de análisis
El método opcional flowViewDidReceiveAnalyticEvent está reservado para eventos de análisis personalizados de un flow. Por ahora, los flows no emiten estos eventos a tu código, por lo que no necesitas implementarlo.
Gestionar compras en modo observador
Si activaste el SDK en modo observador y muestras un flow o paywall renderizado por Adapty, el SDK no realiza las compras por ti. Cuando el usuario pulsa el botón de compra o restauración, el SDK llama a tu AdaptyUIObserverModeResolver en su lugar. Consulta Presentar flows en modo observador para ver la configuración completa.
Manejar solicitudes del sistema
AdaptyUISystemRequestsHandler (registrado mediante AdaptyUI().setSystemRequestsHandler(...)) está reservado para solicitudes del sistema generadas por un flow: solicitudes de permisos del SO (como notificaciones push o acceso a la cámara) y solicitudes de valoración en el App Store. Los flows aún no activan estas solicitudes, por lo que no es necesario registrar un handler.
Si registras uno, ten en cuenta que handlePermission es el método obligatorio de la clase: solicita el permiso con tu propio código y luego devuelve AdaptyUIPermissionResult.granted() o AdaptyUIPermissionResult.denied(); handleAppReviewRequest es opcional.
Esta guía cubre el manejo de eventos para compras, restauraciones, selección de productos y renderizado de paywalls. También debes implementar el manejo de botones (cerrar el paywall, abrir enlaces, etc.). Consulta nuestra guía sobre el manejo de acciones de botones para más detalles.
Los paywalls configurados con el Paywall Builder no necesitan código adicional para realizar y restaurar compras. Sin embargo, generan algunos eventos a los que tu app puede responder. Estos eventos incluyen pulsaciones de botones (botones de cierre, URLs, selección de productos, etc.), así como notificaciones sobre acciones relacionadas con compras realizadas en el paywall. A continuación te explicamos cómo responder a estos eventos.
Esta guía es exclusivamente para paywalls del nuevo Paywall Builder que requieren Adapty SDK v3.0 o posterior.
Para controlar o supervisar los procesos que ocurren en la pantalla del paywall dentro de tu aplicación móvil, implementa los métodos de AdaptyUIPaywallsEventsObserver y establece el observer antes de mostrar cualquier pantalla:
AdaptyUI().setPaywallsEventsObserver(this);¿Quieres ver un ejemplo real de cómo se integra el SDK de Adapty en una app móvil? Echa un vistazo a nuestras apps de ejemplo, que muestran la configuración completa, incluyendo la visualización de paywalls, la realización de compras y otras funcionalidades básicas.
Los ejemplos de eventos a continuación muestran las propiedades disponibles en cada objeto, con valores ilustrativos en los comentarios.
Eventos generados por el usuario
Paywall appeared
Este método se invoca cuando la vista del paywall aparece en pantalla.
En iOS, también se invoca cuando el usuario pulsa el botón de web paywall dentro de un paywall y el web paywall se abre en un navegador integrado.
void paywallViewDidAppear(AdaptyUIPaywallView view) {
}Paywall disappeared
Este método se invoca cuando la vista del paywall se cierra y desaparece de la pantalla.
En iOS, también se invoca cuando un web paywall abierto desde un paywall en un navegador in-app desaparece de la pantalla.
void paywallViewDidDisappear(AdaptyUIPaywallView view) {
}Selección de producto
Si se selecciona un producto para su compra (por el usuario o por el sistema), se invocará este método:
void paywallViewDidSelectProduct(AdaptyUIPaywallView view, String productId) {
}Ejemplo de evento (Haz clic para expandir)
void paywallViewDidSelectProduct(AdaptyUIPaywallView view, String productId) {
// productId is a String:
productId; // 'premium_monthly'
}Compra iniciada
Si un usuario inicia el proceso de compra, se invocará este método:
void paywallViewDidStartPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product) {
}Ejemplo de evento (haz clic para expandir)
void paywallViewDidStartPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product) {
// product — AdaptyPaywallProduct:
product.vendorProductId; // 'premium_monthly'
product.localizedTitle; // 'Premium Monthly'
product.localizedDescription; // 'Premium subscription for 1 month'
product.price.amount; // 9.99 (double)
product.price.currencyCode; // 'USD'
product.price.localizedString; // '$9.99'
}Compra finalizada
Este método se invoca cuando una compra tiene éxito, el usuario cancela su compra, o la compra parece estar pendiente:
void paywallViewDidFinishPurchase(AdaptyUIPaywallView view,
AdaptyPaywallProduct product,
AdaptyPurchaseResult purchaseResult) {
switch (purchaseResult) {
case AdaptyPurchaseResultSuccess(profile: final profile):
// successful purchase
break;
case AdaptyPurchaseResultPending():
// purchase is pending
break;
case AdaptyPurchaseResultUserCancelled():
// user cancelled the purchase
break;
default:
break;
}
}Ejemplos de eventos (haz clic para expandir)
void paywallViewDidFinishPurchase(AdaptyUIPaywallView view,
AdaptyPaywallProduct product,
AdaptyPurchaseResult purchaseResult) {
// product — AdaptyPaywallProduct:
product.vendorProductId; // 'premium_monthly'
switch (purchaseResult) {
case AdaptyPurchaseResultSuccess(profile: final profile):
// profile — AdaptyProfile:
profile.accessLevels['premium']?.isActive; // true
profile.accessLevels['premium']?.expiresAt; // DateTime(2027, 2, 15, 10, 30)
break;
case AdaptyPurchaseResultPending():
// no additional data
break;
case AdaptyPurchaseResultUserCancelled():
// no additional data
break;
}
}Recomendamos cerrar la pantalla en ese caso. Consulta Responder a las acciones de botones para obtener más información sobre cómo cerrar una pantalla de paywall.
Navegación de pago web finalizada
Este método se invoca tras un intento de abrir un web paywall para un producto específico. Esto incluye tanto los intentos de navegación exitosos como los fallidos:
void paywallViewDidFinishWebPaymentNavigation(AdaptyUIPaywallView view,
AdaptyPaywallProduct? product,
AdaptyError? error) {
}Parámetros:
| Parámetro | Descripción |
|---|---|
| product | Un AdaptyPaywallProduct para el que se abrió el paywall web. Puede ser null. |
| error | Un objeto AdaptyError si la navegación del paywall web falló; null si la navegación fue correcta. |
Ejemplos de eventos (Haz clic para expandir)
void paywallViewDidFinishWebPaymentNavigation(AdaptyUIPaywallView view,
AdaptyPaywallProduct? product,
AdaptyError? error) {
// product — AdaptyPaywallProduct?:
product?.vendorProductId; // 'premium_monthly'
if (error == null) {
// navigation succeeded
} else {
// error — AdaptyError:
error.code; // AdaptyErrorCode.networkFailed (2005)
error.message; // 'Network request failed'
error.detail; // platform-specific underlying error, or null
}
}Compra fallida
Este método se invoca cuando una compra falla (por ejemplo, por problemas de pago o errores de red). No se activa para cancelaciones iniciadas por el usuario ni para transacciones pendientes; esas se gestionan mediante paywallViewDidFinishPurchase:
void paywallViewDidFailPurchase(AdaptyUIPaywallView view,
AdaptyPaywallProduct product,
AdaptyError error) {
}Ejemplo de evento (haz clic para expandir)
void paywallViewDidFailPurchase(AdaptyUIPaywallView view,
AdaptyPaywallProduct product,
AdaptyError error) {
// product — AdaptyPaywallProduct:
product.vendorProductId; // 'premium_monthly'
// error — AdaptyError:
error.code; // AdaptyErrorCode.productPurchaseFailed (1006)
error.message; // 'Product purchase failed.'
error.detail; // platform-specific underlying error, or null
}Restauración iniciada
Si un usuario inicia el proceso de restauración, se invocará este método:
void paywallViewDidStartRestore(AdaptyUIPaywallView view) {
}Restauración exitosa
Si la restauración de una compra se realiza con éxito, se invocará este método:
void paywallViewDidFinishRestore(AdaptyUIPaywallView view, AdaptyProfile profile) {
}Ejemplo de evento (haz clic para expandir)
void paywallViewDidFinishRestore(AdaptyUIPaywallView view, AdaptyProfile profile) {
// profile — AdaptyProfile:
profile.accessLevels['premium']?.isActive; // true
profile.accessLevels['premium']?.expiresAt; // DateTime(2027, 2, 15, 10, 30)
profile.subscriptions['premium_monthly']?.isActive; // true
profile.subscriptions['premium_monthly']?.expiresAt; // DateTime(2027, 2, 15, 10, 30)
}Recomendamos cerrar la pantalla si el usuario tiene el accessLevel requerido. Consulta el tema Estado de la suscripción para aprender cómo comprobarlo y el tema Responder a las acciones de los botones para aprender cómo cerrar una pantalla de paywall.
Fallo al restaurar
Si la restauración de una compra falla, se invocará este método:
void paywallViewDidFailRestore(AdaptyUIPaywallView view, AdaptyError error) {
}Ejemplo de evento (Haz clic para expandir)
void paywallViewDidFailRestore(AdaptyUIPaywallView view, AdaptyError error) {
// error — AdaptyError:
error.code; // AdaptyErrorCode.receiveRestoredTransactionsFailed (1011)
error.message; // 'Error occurred in the process of restoring purchases.'
error.detail; // platform-specific underlying error, or null
}Obtención y renderizado de datos
Errores al cargar productos
Si no pasas el array de productos durante la inicialización, AdaptyUI recuperará los objetos necesarios del servidor por sí mismo. Si esta operación falla, AdaptyUI reportará el error invocando este método:
void paywallViewDidFailLoadingProducts(AdaptyUIPaywallView view, AdaptyError error) {
}Ejemplo de evento (haz clic para expandir)
void paywallViewDidFailLoadingProducts(AdaptyUIPaywallView view, AdaptyError error) {
// error — AdaptyError:
error.code; // AdaptyErrorCode.productRequestFailed (1002)
error.message; // 'Unable to fetch available In-App Purchase products at the moment.'
error.detail; // platform-specific underlying error, or null
}Errores de renderizado
Si se produce un error durante el renderizado de la interfaz, se notificará llamando a este método. De manera predeterminada (desde v3.15.2), el paywall se cierra automáticamente cuando se produce un error de renderizado, pero puedes cambiar este comportamiento si lo necesitas.
void paywallViewDidFailRendering(AdaptyUIPaywallView view, AdaptyError error) {
// Default behavior: view.dismiss()
// Override with custom logic if needed, for example:
// - Log the error
// - Show an error message to the user
}Ejemplo de evento (haz clic para expandir)
void paywallViewDidFailRendering(AdaptyUIPaywallView view, AdaptyError error) {
// error — AdaptyError:
error.code; // AdaptyErrorCode.jsException (4105)
error.message; // 'An exception was thrown from JS during AdaptyUI flow execution.'
error.detail; // platform-specific underlying error, or null
// Default behavior: view.dismiss()
}En condiciones normales, estos errores no deberían ocurrir, así que si te encuentras con alguno, por favor, haznos saber.