### Durante el login/registro \{#during-loginsignup\}
Si identificas a los usuarios después del lanzamiento de la app (por ejemplo, después de que inicien sesión o se registren), usa el método `identify` para establecer su customer user ID.
- Si **no has usado este customer user ID antes**, Adapty lo vinculará automáticamente al perfil actual.
- Si **ya has usado este customer user ID para identificar al usuario**, Adapty cambiará al perfil asociado a ese customer user ID.
:::important
Los customer user IDs deben ser únicos para cada usuario. Si defines el valor del parámetro de forma fija en el código, todos los usuarios se considerarán como uno solo.
:::
Siempre usa `await` con `identify` antes de llamar a otros métodos del SDK. Las llamadas concurrentes generan `#3006 profileWasChanged` o se aplican al perfil anónimo. Consulta [Orden de llamadas en el SDK de Flutter](flutter-sdk-call-order).
```dart showLineNumbers
try {
await Adapty().identify(customerUserId); // Unique for each user
} on AdaptyError catch (adaptyError) {
// handle the error
} catch (e) {
}
```
### Durante la activación del SDK \{#during-the-sdk-activation\}
Si ya conoces el customer user ID cuando activas el SDK, puedes enviarlo en el método `activate` en lugar de llamar a `identify` por separado.
Si conoces el customer user ID pero lo defines solo después de la activación, Adapty creará un nuevo perfil anónimo al activarse y cambiará al existente solo después de que llames a `identify`.
Puedes pasar un customer user ID existente (uno que hayas usado antes) o uno nuevo. Si pasas uno nuevo, el perfil creado al activarse se vinculará automáticamente al customer user ID.
:::note
De forma predeterminada, la creación de perfiles anónimos no afecta a los dashboards de análisis, porque las instalaciones se cuentan según los IDs de dispositivo.
Un ID de dispositivo representa una única instalación de la app desde el store en un dispositivo y solo se regenera después de reinstalar la app.
No depende de si es una primera o posterior instalación, ni de si se usa un customer user ID existente.
Crear un perfil (al activar el SDK o al cerrar sesión), iniciar sesión o actualizar la app sin reinstalarla no genera eventos de instalación adicionales.
Si quieres contar las instalaciones por usuarios únicos en lugar de por dispositivos, ve a **App settings** y configura [**Installs definition for analytics**](general#4-installs-definition-for-analytics).
:::
```dart showLineNumbers"
try {
await Adapty().activate(
configuration: AdaptyConfiguration(apiKey: 'YOUR_API_KEY')
..withCustomerUserId(YOUR_CUSTOMER_USER_ID) // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one.
);
} catch (e) {
// handle the error
}
```
### Cerrar sesión de usuarios \{#log-users-out\}
Si tienes un botón para cerrar sesión de los usuarios, usa el método `logout`.
:::important
Cerrar la sesión de un usuario crea un nuevo perfil anónimo para ese usuario.
:::
```dart showLineNumbers
try {
await Adapty().logout();
} on AdaptyError catch (adaptyError) {
// handle the error
} catch (e) {
// handle unknown error
}
```
:::info
Para volver a iniciar sesión en la app, usa el método `identify`.
:::
### Permitir compras sin inicio de sesión \{#allow-purchases-without-login\}
Si tus usuarios pueden realizar compras tanto antes como después de iniciar sesión en tu app, debes asegurarte de que conserven el acceso después de iniciar sesión:
1. Cuando un usuario sin sesión iniciada realiza una compra, Adapty la vincula a su ID de perfil anónimo.
2. Cuando el usuario inicia sesión en su cuenta, Adapty cambia a trabajar con su perfil identificado.
- Si es un nuevo customer user ID (por ejemplo, la compra se realizó antes del registro), Adapty asigna el customer user ID al perfil actual, por lo que se mantiene todo el historial de compras.
- Si es un customer user ID existente (el customer user ID ya está vinculado a un perfil), debes obtener el nivel de acceso actual después del cambio de perfil. Puedes llamar a [`getProfile`](flutter-check-subscription-status) justo después de la identificación, o [escuchar las actualizaciones del perfil](flutter-check-subscription-status) para que los datos se sincronicen automáticamente.
## Siguientes pasos \{#next-steps\}
¡Enhorabuena! Has implementado la lógica de pagos in-app en tu app. ¡Te deseamos mucho éxito con la monetización de tu app!
Para sacar aún más partido a Adapty, puedes explorar estos temas:
- [**Pruebas**](troubleshooting-test-purchases): Verifica que todo funciona como se espera
- [**Onboardings**](flutter-onboardings): Engancha a los usuarios con onboardings y mejora la retención
- [**Integraciones**](configuration): Integra con servicios de atribución de marketing y análisis con una sola línea de código
- [**Establecer atributos de perfil personalizados**](flutter-setting-user-attributes): Añade atributos personalizados a los perfiles de usuario y crea segmentos para lanzar pruebas A/B o mostrar diferentes paywalls a distintos usuarios
---
# File: adapty-cursor-flutter
---
---
title: "Integra Adapty en tu app de Flutter con asistencia de IA"
description: "Una guía paso a paso para integrar Adapty en tu app de Flutter usando Cursor, Context7, ChatGPT, Claude u otras herramientas de IA."
---
Esta página explica dos formas de integrar Adapty en tu app de Flutter. Usa la habilidad de integración del SDK que se describe a continuación para un flujo automatizado de extremo a extremo, o sigue el recorrido manual más adelante.
## Usa la habilidad de integración del SDK (beta) \{#use-the-sdk-integration-skill-beta\}
La [habilidad adapty-sdk-integration](https://github.com/adaptyteam/adapty-sdk-integration-skill) automatiza la integración de principio a fin: configuración del dashboard, instalación del SDK, paywall y verificación por etapas. El recorrido manual que aparece más abajo es la alternativa si tu herramienta no admite el formato Claude Skills.
**Herramientas compatibles**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI.
### Instalación \{#install\}
Elige el formato para tu herramienta. La lista completa está en el [README de la habilidad](https://github.com/adaptyteam/adapty-sdk-integration-skill).
- **Claude Code**: Ejecuta `claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill` y después `claude plugin install adapty-sdk-integration@adapty` desde tu shell.
- **GitHub Copilot CLI**: Ejecuta `gh skill install adaptyteam/adapty-sdk-integration-skill`.
- **Gemini CLI**: Ejecuta `gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill`.
- **OpenAI Codex u otra herramienta**: Clona el repositorio y copia `plugins/adapty-sdk-integration/skills/adapty-sdk-integration/` en el directorio de habilidades de tu herramienta.
### Ejecución \{#run\}
Desde tu proyecto, ejecuta `/adapty-sdk-integration`. La habilidad detecta tu plataforma y hace algunas preguntas de configuración. Luego recorre la configuración del dashboard, la instalación del SDK, el paywall y la verificación, consultando la documentación de Adapty en cada etapa.
:::note
La habilidad está en beta. Si se detiene o se comporta de forma inesperada, el recorrido manual que aparece a continuación cubre cada etapa paso a paso.
:::
## Antes de empezar: configuración del dashboard \{#before-you-start-dashboard-setup\}
Adapty requiere cierta configuración en el dashboard antes de escribir código del SDK. Puedes hacerlo con una habilidad de LLM interactiva o manualmente desde el Dashboard.
### Enfoque con habilidad (recomendado) \{#skill-approach-recommended\}
La habilidad CLI de Adapty permite que tu LLM configure tu app, productos, niveles de acceso, paywalls y placements directamente, sin necesidad de abrir el Dashboard en cada paso. Solo necesitas [conectar tus stores](integrate-payments) desde el Dashboard.
```
npx skills add adaptyteam/adapty-cli --skill adapty-cli
```
Una vez añadida la habilidad, ejecuta `/adapty-cli` en tu agente. Te guiará por cada paso, incluido cuándo abrir el Dashboard para conectar tus stores.
### Enfoque manual desde el dashboard \{#dashboard-approach\}
Si prefieres configurarlo todo manualmente, esto es lo que necesitas antes de escribir código. Tu LLM no puede buscar los valores del dashboard por ti, así que tendrás que proporcionarlos.
1. **Conecta tus stores**: En el Adapty Dashboard, ve a **App settings → General**. Conecta App Store y Google Play si tu app de Flutter se dirige a ambas plataformas. Esto es obligatorio para que las compras funcionen.
[Conectar stores](integrate-payments)
2. **Copia tu clave SDK pública**: En el Adapty Dashboard, ve a **App settings → General** y localiza la sección **API keys**. En el código, esta es la cadena que pasas a la configuración de Adapty.
3. **Crea al menos un producto**: En el Adapty Dashboard, ve a la página **Products**. No referenciarás los productos directamente en el código: Adapty los entrega a través de los paywalls.
[Añadir productos](quickstart-products)
4. **Crea un paywall y un placement**: En el Adapty Dashboard, crea un paywall en la página **Paywalls** y asígnalo a un placement en la página **Placements**. En el código, el ID del placement es la cadena que pasas a `Adapty().getPaywall()`.
[Crear paywall](quickstart-paywalls)
5. **Configura los niveles de acceso**: En el Adapty Dashboard, configúralos por producto en la página **Products**. En el código, la cadena que se comprueba es `profile.accessLevels['premium']?.isActive`. El nivel de acceso `premium` predeterminado funciona para la mayoría de las apps. Si los usuarios de pago acceden a distintas funciones según el producto (por ejemplo, un plan `basic` frente a uno `pro`), [crea niveles de acceso adicionales](assigning-access-level-to-a-product) antes de empezar a programar.
:::tip
Una vez que tengas los cinco, estás listo para escribir código. Dile a tu LLM: "Mi clave SDK pública es X, mi ID de placement es Y" para que pueda generar el código correcto de inicialización y obtención del paywall.
:::
### Configura cuando estés listo \{#set-up-when-ready\}
Estos pasos no son necesarios para empezar a programar, pero los querrás a medida que tu integración madure:
- **Pruebas A/B**: Configúralas en la página **Placements**. No requieren cambios en el código.
[Pruebas A/B](ab-tests)
- **Paywalls y placements adicionales**: Añade más llamadas a `getPaywall` con distintos IDs de placement.
- **Integraciones de analíticas**: Configúralas en la página **Integrations**. La configuración varía según la integración. Consulta [integraciones de analíticas](analytics-integration) e [integraciones de atribución](attribution-integration).
## Proporciona documentación de Adapty a tu LLM \{#feed-adapty-docs-to-your-llm\}
### Usa Context7 (recomendado) \{#use-context7-recommended\}
[Context7](https://context7.com) es un servidor MCP que da a tu LLM acceso directo a la documentación actualizada de Adapty. El LLM obtiene automáticamente la documentación adecuada según lo que preguntes, sin necesidad de pegar URLs manualmente.
Context7 funciona con **Cursor**, **Claude Code**, **Windsurf** y otras herramientas compatibles con MCP. Para configurarlo, ejecuta:
```
npx ctx7 setup
```
Esto detecta tu editor y configura el servidor Context7. Para la configuración manual, consulta el [repositorio GitHub de Context7](https://github.com/upstash/context7).
Una vez configurado, referencia la biblioteca de Adapty en tus prompts:
```
Use the adaptyteam/adapty-docs library to look up how to install the Flutter SDK
```
:::warning
Aunque Context7 elimina la necesidad de pegar enlaces de documentación manualmente, el orden de implementación importa. Sigue el [recorrido de implementación](#implementation-walkthrough) paso a paso para asegurarte de que todo funciona correctamente.
:::
### Usa documentación en texto plano \{#use-plain-text-docs\}
Puedes acceder a cualquier documento de Adapty como Markdown en texto plano. Añade `.md` al final de su URL o haz clic en **Copy for LLM** debajo del título del artículo. Por ejemplo: [adapty-cursor-flutter.md](https://adapty.io/docs/es/adapty-cursor-flutter.md).
Cada etapa del [recorrido de implementación](#implementation-walkthrough) que aparece a continuación incluye un bloque "Envía esto a tu LLM" con enlaces `.md` listos para pegar.
Para obtener más documentación a la vez, consulta los [archivos de índice y subconjuntos por plataforma](#plain-text-doc-index-files) que aparecen más abajo.
## Recorrido de implementación \{#implementation-walkthrough\}
El resto de esta guía recorre la integración de Adapty en el orden de implementación recomendado. Cada etapa incluye la documentación que debes enviar a tu LLM, qué deberías ver al terminar y los problemas más comunes.
### Planifica tu integración \{#plan-your-integration\}
Antes de escribir código, pide a tu LLM que analice tu proyecto y cree un plan de implementación. Si tu herramienta de IA admite un modo de planificación (como el modo plan de Cursor o Claude Code), úsalo para que el LLM pueda leer tanto la estructura de tu proyecto como la documentación de Adapty antes de escribir código.
Dile a tu LLM qué enfoque usas para las compras, ya que esto afecta a las guías que debe seguir:
- [**Adapty Paywall Builder**](adapty-paywall-builder): Creas los paywalls en el editor no-code de Adapty y el SDK los renderiza automáticamente.
- [**Paywalls creados manualmente**](flutter-making-purchases): Construyes tu propia interfaz de paywall en código, pero sigues usando Adapty para obtener productos y gestionar compras.
- [**Modo Observer**](observer-vs-full-mode): Mantienes tu infraestructura de compras existente y usas Adapty solo para analíticas e integraciones.
¿No sabes cuál elegir? Lee la [tabla comparativa en la guía de inicio rápido](flutter-quickstart-paywalls).
### Instala y configura el SDK \{#install-and-configure-the-sdk\}
Añade la dependencia del SDK de Adapty usando `flutter pub add` y actívalo con tu clave SDK pública. Esta es la base: nada más funciona sin ella.
**Guía:** [Instalar y configurar el SDK de Adapty](sdk-installation-flutter)
Envía esto a tu LLM:
```
Read these Adapty docs before writing code:
- https://adapty.io/docs/es/sdk-installation-flutter.md
```
:::tip[Punto de control]
- **Esperado:** La app se compila y ejecuta en iOS y Android. La consola de depuración muestra el log de activación de Adapty.
- **Problema frecuente:** "Public API key is missing" → comprueba que reemplazaste el marcador de posición con tu clave real desde App settings.
:::
### Muestra paywalls y gestiona compras \{#show-paywalls-and-handle-purchases\}
Obtén un paywall por ID de placement, muéstralo y gestiona los eventos de compra. Las guías que necesitas dependen de cómo gestionas las compras.
Prueba cada compra en el sandbox a medida que avanzas; no esperes hasta el final. Consulta [Probar compras en sandbox](test-purchases-in-sandbox) para las instrucciones de configuración.
opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-paywall-locale-in-adapty-paywall-builder). Se espera que este parámetro sea un código de idioma compuesto por una o dos subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de idioma](flutter-localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre reciban los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En este caso, los usuarios podrían no obtener los datos más recientes, pero experimentarán tiempos de carga más rápidos, sin importar la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar peticiones de red.
Ten en cuenta que la caché se mantiene al reiniciar la app y solo se borra al desinstalarla o mediante una limpieza manual.
El SDK de Adapty almacena los paywalls localmente en dos capas: la caché actualizada regularmente descrita anteriormente y los [paywalls de respaldo](fallback-paywalls). También usamos CDN para obtener los paywalls más rápido y un servidor de respaldo independiente en caso de que la CDN no esté disponible. Este sistema está diseñado para garantizar que siempre obtengas la versión más reciente de tus paywalls, asegurando la fiabilidad incluso cuando la conexión a internet es escasa.
| | **loadTimeout** | por defecto: 5 seg |Este valor limita el tiempo de espera para este método. Si se alcanza el tiempo límite, se devolverán los datos en caché o el fallback local.
Ten en cuenta que en casos excepcionales este método puede exceder ligeramente el tiempo especificado en `loadTimeout`, ya que la operación puede estar compuesta por distintas peticiones internamente.
Para Android: puedes crear `TimeInterval` con funciones de extensión (como `5.seconds`, donde `.seconds` es de `import com.adapty.utils.seconds`), o `TimeInterval.seconds(5)`. Para no establecer límite, usa `TimeInterval.INFINITE`.
| Parámetros de respuesta: | Parámetro | Descripción | | :-------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | Un objeto [`AdaptyPaywall`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywall-class.html) con una lista de IDs de productos, el identificador del paywall, el Remote Config y varias otras propiedades. | ## Obtener la configuración de vista del paywall diseñado con Paywall Builder \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important Asegúrate de activar el toggle **Show on device** en el Paywall Builder. Si esta opción no está activada, la configuración de vista no estará disponible para recuperar. ::: Después de obtener el paywall, comprueba si incluye una `ViewConfiguration`, lo que indica que fue creado con el Paywall Builder. Esto te indicará cómo mostrar el paywall. Si la `ViewConfiguration` está presente, trátalo como un paywall de Paywall Builder; si no, [manéjalo como un paywall de Remote Config](present-remote-config-paywalls-flutter). ```dart showLineNumbers try { final view = await AdaptyUI().createPaywallView( paywall: paywall, ); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` Una vez que tengas la vista, [presenta el paywall](flutter-present-paywalls). ## Obtener un paywall para la audiencia por defecto y cargarlo más rápido \{#get-a-paywall-for-a-default-audience-to-fetch-it-faster\} Normalmente, los paywalls se obtienen casi de inmediato, por lo que no necesitas preocuparte por acelerar este proceso. Sin embargo, si tienes muchas audiencias y paywalls, y tus usuarios tienen una conexión a internet débil, obtener un paywall puede tardar más de lo deseado. En esos casos, puede que quieras mostrar un paywall por defecto para garantizar una experiencia de usuario fluida en lugar de no mostrar ninguno. Para resolver esto, puedes usar el método `getPaywallForDefaultAudience`, que obtiene el paywall del placement especificado para la audiencia **All Users**. Sin embargo, es fundamental entender que el enfoque recomendado es obtener el paywall con el método `getPaywall`, como se detalla en la sección [Obtener el paywall diseñado con Paywall Builder](flutter-get-pb-paywalls#fetch-paywall-designed-with-paywall-builder) anterior. :::warning Por qué recomendamos usar `getPaywall` El método `getPaywallForDefaultAudience` tiene algunos inconvenientes importantes: - **Posibles problemas de compatibilidad con versiones anteriores**: Si necesitas mostrar paywalls distintos para diferentes versiones de la app (actual y futuras), puedes encontrar dificultades. Tendrás que diseñar paywalls que soporten la versión actual (legacy) o asumir que los usuarios con esa versión podrían encontrar problemas con paywalls que no se renderizan. - **Pérdida de targeting**: Todos los usuarios verán el mismo paywall diseñado para la audiencia **All Users**, lo que significa que pierdes el targeting personalizado (incluido el basado en países, atribución de marketing o tus propios atributos personalizados). Si estás dispuesto a asumir estos inconvenientes para beneficiarte de una carga más rápida del paywall, usa el método `getPaywallForDefaultAudience` como se indica a continuación. De lo contrario, usa `getPaywall` descrito [arriba](#fetch-paywall-designed-with-paywall-builder). ::: ```dart showLineNumbers try { final paywall = await Adapty().getPaywallForDefaultAudience(placementId: 'YOUR_PLACEMENT_ID'); } on AdaptyError catch (adaptyError) { // handle error } catch (e) { // handle unknown error } ``` :::note El método `getPaywallForDefaultAudience` está disponible a partir de la versión 3.2.0 del Flutter SDK. ::: | Parámetro | Presencia | Descripción | |---------|--------|-----------| | **placementId** | requerido | El identificador del [Placement](placements). Es el valor que especificaste al crear un placement en tu Adapty Dashboard. | | **locale** |opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-remote-config-locale). Se espera que este parámetro sea un código de idioma compuesto por una o más subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de idioma](localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre reciban los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En este caso, los usuarios podrían no obtener los datos más recientes, pero experimentarán tiempos de carga más rápidos, sin importar la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar peticiones de red.
Ten en cuenta que la caché se mantiene al reiniciar la app y solo se borra al desinstalarla o mediante una limpieza manual.
| ## Personalizar recursos \{#customize-assets\} Para personalizar imágenes y vídeos en tu paywall, implementa los recursos personalizados. Las imágenes y vídeos principales tienen IDs predefinidos: `hero_image` y `hero_video`. En un bundle de recursos personalizados, apuntas a estos elementos por sus IDs y personalizas su comportamiento. Para otras imágenes y vídeos, necesitas [establecer un ID personalizado](custom-media) en el dashboard de Adapty. Por ejemplo, puedes: - Mostrar una imagen o vídeo diferente a algunos usuarios. - Mostrar una imagen de vista previa local mientras se carga la imagen principal remota. - Mostrar una imagen de vista previa antes de reproducir un vídeo. :::important Para usar esta funcionalidad, actualiza el Flutter SDK de Adapty a la versión 3.8.0 o superior. ::: Aquí tienes un ejemplo de cómo proporcionar recursos personalizados mediante un diccionario simple: ```dart final customAssets = { // Show a local image using a custom ID 'custom_image': AdaptyCustomAsset.localImageAsset( assetId: 'assets/images/image_name.png', ), // Show a local video with a preview image 'hero_video': AdaptyCustomAsset.localVideoAsset( assetId: 'assets/videos/custom_video.mp4', ), }; try { final view = await AdaptyUI().createPaywallView( paywall: paywall, customAssets:
## El número de vistas del paywall es demasiado alto \{#the-paywall-view-number-is-too-big\}
**Problema**: El recuento de vistas del paywall muestra el doble del número esperado.
**Causa**: Es posible que estés llamando a `logShowPaywall` en tu código, lo que duplica el recuento de vistas si usas el Paywall Builder. En los paywalls diseñados con el Paywall Builder, el seguimiento de analytics es automático, por lo que no es necesario usar este método.
**Solución**: Asegúrate de no llamar a `logShowPaywall` en tu código si estás usando el Paywall Builder.
## Otros problemas \{#other-issues\}
**Problema**: Experimentas otros problemas relacionados con el Paywall Builder que no se han tratado anteriormente.
**Solución**: Si es necesario, migra el SDK a la versión más reciente siguiendo las [guías de migración](flutter-sdk-migration-guides). Muchos problemas se resuelven en versiones más nuevas del SDK.
---
# File: flutter-quickstart-manual
---
---
title: "Habilitar compras en tu paywall personalizado en Flutter SDK"
description: "Integra el SDK de Adapty en tus paywalls personalizados de Flutter para habilitar compras in-app."
---
Esta guía describe cómo integrar Adapty en tus paywalls personalizados. Mantén el control total sobre la implementación del paywall, mientras el SDK de Adapty obtiene los productos, gestiona las nuevas compras y restaura las anteriores.
:::important
**Esta guía es para desarrolladores que implementan paywalls personalizados.** Si quieres la forma más sencilla de habilitar compras, usa el [Paywall Builder de Adapty](flutter-quickstart-paywalls). Con Paywall Builder, creas paywalls en un editor visual sin código, Adapty gestiona toda la lógica de compras automáticamente y puedes probar distintos diseños sin volver a publicar tu app.
:::
## Antes de empezar \{#before-you-start\}
### Configura los productos \{#set-up-products\}
Para habilitar las compras in-app, necesitas entender tres conceptos clave:
- [**Productos**](product) – todo lo que los usuarios pueden comprar (suscripciones, consumibles, acceso de por vida)
- [**Paywalls**](paywalls) – configuraciones que definen qué productos ofrecer. En Adapty, los paywalls son la única forma de recuperar productos, pero este diseño te permite modificar productos, precios y ofertas sin tocar el código de tu app.
- [**Placements**](placements) – dónde y cuándo muestras los paywalls en tu app (como `main`, `onboarding`, `settings`). Configuras los paywalls para los placements en el dashboard y luego los solicitas por ID de placement en tu código. Esto facilita ejecutar pruebas A/B y mostrar paywalls distintos a diferentes usuarios.
Asegúrate de entender estos conceptos aunque trabajes con tu paywall personalizado. Básicamente, son tu forma de gestionar los productos que vendes en tu app.
Para implementar tu paywall personalizado, necesitarás crear un **paywall** y añadirlo a un **placement**. Esta configuración te permite recuperar tus productos. Para entender qué debes hacer en el dashboard, sigue la guía de inicio rápido [aquí](quickstart).
### Gestiona usuarios \{#manage-users\}
Puedes trabajar con o sin autenticación de backend en tu lado.
Sin embargo, el SDK de Adapty gestiona de forma diferente a los usuarios anónimos e identificados. Lee la [guía de inicio rápido de identificación](flutter-quickstart-identify) para entender las particularidades y asegurarte de que trabajas con los usuarios correctamente.
## Paso 1. Obtén los productos \{#step-1-get-products\}
Para recuperar los productos de tu paywall personalizado, necesitas:
1. Obtener el objeto `paywall` pasando el ID del [placement](placements) al método `getPaywall`.
2. Obtener el array de productos para ese paywall usando el método `getPaywallProducts`.
```dart showLineNumbers
Futureopcional
por defecto: `en`
|El identificador de la [localización del paywall](add-remote-config-locale). Se espera que este parámetro sea un código de idioma compuesto por una o más subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de configuración regional](flutter-localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar datos del servidor y devolverá datos en caché en caso de error. Recomendamos esta opción porque garantiza que tus usuarios siempre reciban los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver datos en caché si existen. En este caso, puede que los usuarios no reciban los datos más recientes, pero experimentarán tiempos de carga más rápidos independientemente de la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar peticiones de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se desinstala la app o mediante una limpieza manual.
El SDK de Adapty almacena los paywalls en dos capas: la caché actualizada regularmente descrita arriba y los [paywalls de respaldo](flutter-use-fallback-paywalls). También usamos CDN para obtener los paywalls más rápido y un servidor de respaldo independiente en caso de que el CDN no sea accesible. Este sistema está diseñado para garantizar que siempre obtengas la versión más reciente de tus paywalls, asegurando la fiabilidad incluso cuando la conexión a internet es escasa.
| | **loadTimeout** | por defecto: 5 seg |Este valor limita el tiempo de espera para este método. Si se alcanza el tiempo de espera, se devolverán datos en caché o el fallback local.
Ten en cuenta que en casos excepcionales este método puede superar ligeramente el tiempo de espera especificado en `loadTimeout`, ya que la operación puede incluir diferentes solicitudes internamente.
| ¡No escribas los IDs de producto en el código! Dado que los paywalls se configuran de forma remota, los productos disponibles, el número de productos y las ofertas especiales (como períodos de prueba gratuitos) pueden cambiar con el tiempo. Asegúrate de que tu código gestione estos escenarios. Por ejemplo, si inicialmente obtienes 2 productos, tu app debería mostrar esos 2 productos. Sin embargo, si luego obtienes 3 productos, tu app debería mostrar los 3 sin necesidad de cambios en el código. Lo único que debes escribir en el código es el ID del placement. Parámetros de respuesta: | Parámetro | Descripción | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | Un objeto [`AdaptyPaywall`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywall-class.html) con: una lista de IDs de productos, el identificador del paywall, el Remote Config y varias otras propiedades. | ## Obtener productos \{#fetch-products\} Una vez que tengas el paywall, puedes consultar el array de productos que le corresponde: ```dart showLineNumbers try { final products = await Adapty().getPaywallProducts(paywall: paywall); // the requested products array } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` Parámetros de respuesta: | Parámetro | Descripción | | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Products | Lista de objetos [`AdaptyPaywallProduct`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywallProduct-class.html) con: identificador del producto, nombre del producto, precio, moneda, duración de la suscripción y varias otras propiedades. | Cuando implementes tu propio diseño de paywall, probablemente necesitarás acceder a estas propiedades del objeto [`AdaptyPaywallProduct`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywallProduct-class.html). A continuación se muestran las propiedades más utilizadas, pero consulta el documento enlazado para ver todos los detalles de las propiedades disponibles. | Propiedad | Descripción | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Title** | Para mostrar el título del producto, usa `product.localizedTitle`. Ten en cuenta que la localización se basa en el país del store seleccionado por el usuario, no en la configuración regional del dispositivo. | | **Price** | Para mostrar una versión localizada del precio, usa `product.price.localizedString`. Esta localización se basa en la información de configuración regional del dispositivo. También puedes acceder al precio como número con `product.price.amount`. El valor se proporcionará en la moneda local. Para obtener el símbolo de moneda asociado, usa `product.price.currencySymbol`. | | **Subscription Period** | Para mostrar el período (por ejemplo, semana, mes, año, etc.), usa `product.subscription?.localizedPeriod`. Esta localización se basa en la configuración regional del dispositivo. Para obtener el período de suscripción de forma programática, usa `product.subscription?.period`. Desde ahí puedes acceder al enum `unit` para obtener la duración (es decir, día, semana, mes, año o desconocido). El valor `numberOfUnits` te dará el número de unidades del período. Por ejemplo, para una suscripción trimestral, verías `AdaptyPeriodUnit.month` en la propiedad unit y `3` en la propiedad numberOfUnits. | | **Introductory Offer** | Para mostrar un distintivo u otro indicador de que una suscripción contiene una oferta introductoria, consulta la propiedad `product.subscription?.offer?.phases`. Es una lista que puede contener hasta dos fases de descuento: la fase de prueba gratuita y la fase de precio introductorio. Dentro de cada objeto de fase se encuentran las siguientes propiedades útiles:opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-remote-config-locale). Se espera que este parámetro sea un código de idioma compuesto por una o más subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de configuración regional](flutter-localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar datos del servidor y devolverá datos en caché en caso de error. Recomendamos esta opción porque garantiza que tus usuarios siempre reciban los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver datos en caché si existen. En este caso, puede que los usuarios no reciban los datos más recientes, pero experimentarán tiempos de carga más rápidos independientemente de la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar peticiones de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se desinstala la app o mediante una limpieza manual.
| --- # File: present-remote-config-paywalls-flutter --- --- title: "Renderizar un paywall diseñado con Remote Config en el SDK de Flutter" description: "Descubre cómo presentar paywalls de Remote Config en el SDK de Flutter de Adapty para personalizar la experiencia del usuario." --- Si has personalizado un paywall usando Remote Config, necesitarás implementar el renderizado en el código de tu app para mostrárselo a los usuarios. Como Remote Config ofrece flexibilidad adaptada a tus necesidades, tú decides qué incluir y cómo se muestra la vista de tu paywall. Proporcionamos un método para obtener la configuración remota, dándote autonomía para mostrar tu paywall personalizado configurado a través de Remote Config. ## Obtener el Remote Config del paywall y presentarlo \{#get-paywall-remote-config-and-present-it\} Para obtener el Remote Config de un paywall, accede a la propiedad `remoteConfig` y extrae los valores necesarios. ```dart showLineNumbers try { final paywall = await Adapty().getPaywall(id: "YOUR_PLACEMENT_ID"); final String? headerText = paywall.remoteConfig?.dictionary?['header_text'] as String?; } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` En este punto, una vez que hayas recibido todos los valores necesarios, es momento de renderizarlos y ensamblarlos en una página visualmente atractiva. Asegúrate de que el diseño se adapte a las distintas pantallas y orientaciones de los móviles, ofreciendo una experiencia fluida y amigable en todos los dispositivos. :::warning Asegúrate de [registrar el evento de visualización del paywall](present-remote-config-paywalls-flutter#track-paywall-view-events) tal como se describe a continuación, para que Adapty Analytics pueda capturar información para los embudos y las pruebas A/B. ::: Una vez que hayas terminado de mostrar el paywall, continúa configurando el flujo de compra. Cuando el usuario realice una compra, simplemente llama a `.makePurchase()` con el producto de tu paywall. Para más detalles sobre el método `.makePurchase()`, consulta [Realizar compras](flutter-making-purchases). Te recomendamos [crear un paywall de respaldo llamado fallback paywall](flutter-use-fallback-paywalls). Este respaldo se mostrará al usuario cuando no haya conexión a internet ni caché disponible, garantizando una experiencia fluida incluso en esas situaciones. ## Registrar eventos de visualización del paywall \{#track-paywall-view-events\} Adapty te ayuda a medir el rendimiento de tus paywalls. Aunque los datos de compras se recopilan automáticamente, el registro de las visualizaciones del paywall requiere tu intervención, ya que solo tú sabes cuándo un usuario ve un paywall. Para registrar un evento de visualización del paywall, simplemente llama a `.logShowPaywall(paywall)`, y se reflejará en las métricas de tu paywall en los embudos y las pruebas A/B. :::important No es necesario llamar a `.logShowPaywall(paywall)` si estás mostrando paywalls creados en el [Paywall Builder](adapty-paywall-builder). ::: ```dart showLineNumbers try { final result = await Adapty().logShowPaywall(paywall: paywall); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` Parámetros de la solicitud: | Parámetro | Presencia | Descripción | | :---------- | :------- |:----------------------------------------------------------------------| | **paywall** | obligatorio | Un objeto [`AdaptyPaywall`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywall-class.html). | --- # File: flutter-making-purchases --- --- title: "Realizar compras en una aplicación móvil con Flutter SDK" description: "Guía sobre cómo gestionar compras in-app y suscripciones con Adapty." --- Mostrar paywalls en tu aplicación móvil es un paso esencial para ofrecer a los usuarios acceso a contenido o servicios premium. Sin embargo, simplemente mostrar esos paywalls es suficiente para gestionar las compras solo si usas el [Paywall Builder](adapty-paywall-builder) para personalizarlos. Si no usas el Paywall Builder, debes utilizar un método específico llamado `.makePurchase()` para completar una compra y desbloquear el contenido deseado. Este método es la puerta de entrada para que los usuarios interactúen con los paywalls y realicen sus transacciones. Si tu paywall tiene una oferta promocional activa para el producto que el usuario intenta comprar, Adapty la aplicará automáticamente en el momento de la compra. :::warning Ten en cuenta que la oferta introductoria solo se aplicará automáticamente si usas paywalls configurados con el Paywall Builder. En otros casos, tendrás que [verificar la elegibilidad del usuario para una oferta introductoria en iOS](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios). Omitir este paso puede provocar que tu app sea rechazada durante la revisión. Además, podría resultar en que se cobre el precio completo a usuarios que son elegibles para una oferta introductoria. ::: Asegúrate de haber completado la [configuración inicial](quickstart) sin saltarte ningún paso. Sin ella, no podemos validar las compras. ## Realizar una compra \{#make-purchase\} :::note **¿Usas el [Paywall Builder](adapty-paywall-builder)?** Las compras se procesan automáticamente; puedes omitir este paso. **¿Buscas instrucciones paso a paso?** Consulta la [guía de inicio rápido](flutter-implement-paywalls-manually) para obtener instrucciones de implementación completas con todo el contexto. ::: ```dart showLineNumbers try { final purchaseResult = await Adapty().makePurchase(product: product); switch (purchaseResult) { case AdaptyPurchaseResultSuccess(profile: final profile): if (profile.accessLevels['premium']?.isActive ?? false) { // Grant access to the paid features } break; case AdaptyPurchaseResultPending(): break; case AdaptyPurchaseResultUserCancelled(): break; default: break; } } on AdaptyError catch (adaptyError) { // Handle the error } catch (e) { // Handle the error } ``` Parámetros de la solicitud: | Parámetro | Presencia | Descripción | | :---------- | :-------- | :-------------------------------------------------------------------------------------------------- | | **Product** | obligatorio | Un objeto [`AdaptyPaywallProduct`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywallProduct-class.html) obtenido del paywall. | Parámetros de la respuesta: | Parámetro | Descripción | |---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** |Si la solicitud se ha realizado correctamente, la respuesta contiene este objeto. Un objeto [AdaptyProfile](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyProfile-class.html) proporciona información completa sobre los niveles de acceso, suscripciones y compras únicas de un usuario dentro de la app.
Comprueba el estado del nivel de acceso para determinar si el usuario tiene el acceso requerido en la app.
| :::warning **Nota:** si aún utilizas una versión de StoreKit de Apple inferior a v2.0 y una versión del SDK de Adapty inferior a v.2.9.0, debes proporcionar el [secreto compartido de la App Store de Apple](app-store-connection-configuration#step-5-enter-app-store-shared-secret). Este método está actualmente deprecado por Apple. ::: ## Cambiar la suscripción al realizar una compra \{#change-subscription-when-making-a-purchase\} Cuando un usuario opta por una nueva suscripción en lugar de renovar la actual, el comportamiento depende del store: - En la App Store, la suscripción se actualiza automáticamente dentro del grupo de suscripciones. Si un usuario compra una suscripción de un grupo mientras ya tiene activa una de otro grupo, ambas suscripciones estarán activas al mismo tiempo. - En Google Play, la suscripción no se actualiza automáticamente. Tendrás que gestionar el cambio en el código de tu aplicación móvil tal como se describe a continuación. Para reemplazar la suscripción por otra en Android, llama al método `.makePurchase()` con el parámetro adicional: ```dart showLineNumbers try { final result = await adapty.makePurchase( product: product, subscriptionUpdateParams: subscriptionUpdateParams, ); // successful cross-grade } on AdaptyError catch (adaptyError) { // Handle the error } catch (e) { // Handle the error } ``` Parámetro adicional de la solicitud: | Parámetro | Presencia | Descripción | | :--------------------------- | :-------- |:--------------------------------------------------------------------------------------------------------| | **subscriptionUpdateParams** | obligatorio | Un objeto [`AdaptyAndroidSubscriptionUpdateParameters`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyAndroidSubscriptionUpdateParameters-class.html). | Puedes obtener más información sobre las suscripciones y los modos de reemplazo en la documentación para desarrolladores de Google: - [Acerca de los modos de reemplazo](https://developer.android.com/google/play/billing/subscriptions#replacement-modes) - [Recomendaciones de Google para los modos de reemplazo](https://developer.android.com/google/play/billing/subscriptions#replacement-recommendations) - Modo de reemplazo [`CHARGE_PRORATED_PRICE`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#CHARGE_PRORATED_PRICE()). Nota: este método solo está disponible para actualizaciones de suscripción. Las degradaciones no son compatibles. - Modo de reemplazo [`DEFERRED`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#DEFERRED()). Nota: el cambio de suscripción real solo ocurrirá cuando finalice el período de facturación de la suscripción actual. ## Canjear códigos de oferta en iOS \{#redeem-offer-codes-in-ios\} --- no_index: true --- import Callout from '../../../components/Callout.astro';Un objeto [`AdaptyProfile`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyProfile-class.html). Este modelo contiene información sobre niveles de acceso, suscripciones y compras únicas.
Comprueba el **estado del nivel de acceso** para determinar si el usuario tiene acceso a la app.
| :::tip ¿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](sample-apps), que muestran la configuración completa, incluyendo la visualización de paywalls, la realización de compras y otras funcionalidades básicas. ::: --- # File: implement-observer-mode-flutter --- --- title: "Implementar el modo Observer en Flutter SDK" description: "Implementa el modo observer en Adapty para rastrear eventos de suscripción de usuarios en Flutter SDK." --- Si ya tienes tu propia infraestructura de compras y no estás listo para migrar completamente a Adapty, puedes explorar el [modo Observer](observer-vs-full-mode). En su forma básica, el modo Observer ofrece analíticas avanzadas e integración fluida con sistemas de atribución y analítica. Si esto cubre tus necesidades, solo tienes que: 1. Activarlo al configurar el SDK de Adapty estableciendo el parámetro `observerMode` en `true`. Sigue las instrucciones de configuración para [Flutter](sdk-installation-flutter#activate-adapty-module-of-adapty-sdk). 2. [Reportar transacciones](report-transactions-observer-mode-flutter) desde tu infraestructura de compras existente a Adapty. ## Configuración del modo Observer \{#observer-mode-setup\} Activa el modo Observer si gestionas las compras y el estado de la suscripción tú mismo y usas Adapty para enviar eventos de suscripción y analíticas. :::important Cuando se ejecuta en modo Observer, el SDK de Adapty no cerrará ninguna transacción, así que asegúrate de gestionarlo tú mismo. ::: ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withObserverMode(true) // Enable observer mode ..withLogLevel(AdaptyLogLevel.verbose), ); ``` Parámetros: | Parámetro | Descripción | | --------------------------- | ------------------------------------------------------------ | | observerMode | Un valor booleano que controla el [modo Observer](observer-vs-full-mode). El valor predeterminado es `false`. | ## Usar paywalls de Adapty en el modo Observer \{#using-adapty-paywalls-in-observer-mode\} Si también quieres usar los paywalls y las funciones de pruebas A/B de Adapty, puedes hacerlo, pero requiere algo de configuración adicional en el modo Observer. Esto es lo que necesitas hacer además de los pasos anteriores: 1. Muestra los paywalls como de costumbre para [paywalls con Remote Config](present-remote-config-paywalls-flutter). 3. [Asocia los paywalls](report-transactions-observer-mode-flutter) con las transacciones de compra. --- # File: report-transactions-observer-mode-flutter --- --- title: "Reportar transacciones en Observer Mode en Flutter SDK" description: "Reporta transacciones de compra en el Observer Mode de Adapty para obtener información sobre usuarios y seguimiento de ingresos en Flutter SDK." ---phoneNumber
firstName
lastName
| String | | gender | Enum, los valores permitidos son: `female`, `male`, `other` | | birthday | Date | ### Atributos de usuario personalizados \{#custom-user-attributes\} Puedes definir tus propios atributos personalizados, que habitualmente están relacionados con el uso de tu app. Por ejemplo, en aplicaciones de fitness podrían ser el número de ejercicios por semana; en apps de aprendizaje de idiomas, el nivel de conocimiento del usuario, etc. Puedes usarlos en segmentos para crear paywalls y ofertas dirigidas, y también en analítica para descubrir qué métricas de producto tienen más impacto en los ingresos. ```javascript showLineNumbers try { final builder = AdaptyProfileParametersBuilder() ..setCustomStringAttribute('value1', 'key1') ..setCustomDoubleAttribute(1.0, 'key2'); await Adapty().updateProfile(builder.build()); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` Para eliminar una clave existente, usa el método `.withRemoved(customAttributeForKey:)`: ```javascript showLineNumbers try { final builder = AdaptyProfileParametersBuilder() ..removeCustomAttribute('key1') ..removeCustomAttribute('key2'); await Adapty().updateProfile(builder.build()); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` A veces necesitas saber qué atributos personalizados se han establecido previamente. Para ello, utiliza el campo `customAttributes` del objeto `AdaptyProfile`. :::warning Ten en cuenta que el valor de `customAttributes` puede estar desactualizado, ya que los atributos de usuario pueden enviarse desde distintos dispositivos en cualquier momento, por lo que los atributos en el servidor podrían haber cambiado tras la última sincronización. ::: ### Límites \{#limits\} - Hasta 30 atributos personalizados por usuario - Los nombres de clave pueden tener hasta 30 caracteres. El nombre de la clave puede incluir caracteres alfanuméricos y cualquiera de los siguientes: `_` `-` `.` - El valor puede ser una cadena de texto o un número decimal con un máximo de 50 caracteres. --- # File: flutter-listen-subscription-changes --- --- title: "Comprobar el estado de suscripción en el SDK de Flutter" description: "Rastrea y gestiona el estado de suscripción de los usuarios en Adapty para mejorar la retención en tu app de Flutter." --- Con Adapty, llevar el control del estado de suscripción es muy sencillo. No tienes que insertar manualmente los IDs de producto en tu código. En su lugar, puedes confirmar fácilmente el estado de suscripción de un usuario comprobando si tiene un [nivel de acceso](access-level) activo.Un objeto [AdaptyProfile](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyProfile-class.html). En general, solo tienes que comprobar el estado del nivel de acceso del perfil para determinar si el usuario tiene acceso premium a la app.
El método `.getProfile` devuelve el resultado más actualizado posible, ya que siempre intenta consultar la API. Si por algún motivo (por ejemplo, sin conexión a internet) el SDK de Adapty no puede obtener la información del servidor, se devolverán los datos de la caché. También es importante destacar que el SDK de Adapty actualiza la caché de `AdaptyProfile` periódicamente para mantener esta información lo más actualizada posible.
| El método `.getProfile()` te proporciona el perfil del usuario desde el que puedes obtener el estado del nivel de acceso. Puedes tener múltiples niveles de acceso por app. Por ejemplo, si tienes una app de noticias y vendes suscripciones a diferentes temáticas de forma independiente, puedes crear niveles de acceso "sports" y "science". Pero la mayoría de las veces solo necesitarás un nivel de acceso; en ese caso, puedes usar simplemente el nivel de acceso "premium" por defecto. Aquí tienes un ejemplo para comprobar el nivel de acceso "premium" por defecto: ```javascript showLineNumbers try { final profile = await Adapty().getProfile(); if (profile?.accessLevels['premium']?.isActive ?? false) { // grant access to premium features } } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` ### Escuchar actualizaciones del estado de suscripción \{#listening-for-subscription-status-updates\} Cada vez que cambia la suscripción del usuario, Adapty lanza un evento. Para recibir mensajes de Adapty, necesitas realizar una configuración adicional: ```javascript showLineNumbers Adapty().didUpdateProfileStream.listen((profile) { // handle any changes to subscription state }); ``` Adapty también lanza un evento al iniciar la aplicación. En ese caso, se pasará el estado de suscripción almacenado en caché. ### Caché del estado de suscripción \{#subscription-status-cache\} La caché implementada en el SDK de Adapty almacena el estado de suscripción del perfil. Esto significa que, aunque el servidor no esté disponible, se puede acceder a los datos en caché para obtener información sobre el estado de suscripción del perfil. No obstante, hay que tener en cuenta que no es posible solicitar datos directamente desde la caché. El SDK consulta periódicamente el servidor cada minuto para comprobar si hay actualizaciones o cambios relacionados con el perfil. Si hay alguna modificación, como nuevas transacciones u otras actualizaciones, se enviarán a los datos en caché para mantenerlos sincronizados con el servidor. --- # File: flutter-deal-with-att --- --- title: "Gestionar ATT en Flutter SDK" description: "Empieza con Adapty en Flutter para simplificar la configuración y gestión de suscripciones." --- Si tu aplicación utiliza el framework AppTrackingTransparency y muestra al usuario una solicitud de autorización de seguimiento, debes enviar el [estado de autorización](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/) a Adapty. ```dart showLineNumbers final builder = AdaptyProfileParametersBuilder() ..setAppTrackingTransparencyStatus(AdaptyIOSAppTrackingTransparencyStatus.authorized); try { await Adapty().updateProfile(builder.build()); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle unknown error } ``` :::warning Recomendamos encarecidamente que envíes este valor lo antes posible cuando cambie; solo así los datos se transmitirán a tiempo a las integraciones que hayas configurado. ::: --- # File: kids-mode-flutter --- --- title: "Modo Kids en Flutter SDK" description: "Activa fácilmente el Modo Kids para cumplir con las políticas de Apple y Google. Sin recopilación de IDFA, GAID ni datos de publicidad en Flutter SDK." --- Si tu aplicación Flutter está destinada a niños, debes seguir las políticas de [Apple](https://developer.apple.com/kids/) y [Google](https://support.google.com/googleplay/android-developer/answer/9893335). Si usas el SDK de Adapty, unos pocos pasos sencillos te ayudarán a configurarlo para cumplir con estas políticas y superar las revisiones de las tiendas. ## ¿Qué se requiere? \{#whats-required\} Debes configurar el SDK de Adapty para deshabilitar la recopilación de: - [IDFA (Identificador para Anunciantes)](https://en.wikipedia.org/wiki/Identifier_for_Advertisers) (iOS) - [Android Advertising ID (AAID/GAID)](https://support.google.com/googleplay/android-developer/answer/6048248) (Android) - [Dirección IP](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf) Además, te recomendamos usar el ID de usuario con precaución. Un ID de usuario con formato `opcional
por defecto: `en`
|El identificador de la localización del onboarding. Se espera que este parámetro sea un código de idioma compuesto por uno o dos subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar los datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre reciban los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen conexiones inestables a internet, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En este caso, puede que los usuarios no reciban los últimos datos, pero experimentarán tiempos de carga más rápidos independientemente de lo inestable que sea su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se reinstala la app o mediante una limpieza manual.
El SDK de Adapty almacena los onboardings localmente en dos capas: la caché de actualización regular descrita anteriormente y los onboardings de respaldo. También usamos CDN para obtener los onboardings más rápido y un servidor de respaldo independiente en caso de que el CDN no sea accesible. Este sistema está diseñado para garantizar que siempre obtengas la última versión de tus onboardings y asegurar la fiabilidad incluso cuando la conexión a internet es escasa.
| | **loadTimeout** | por defecto: 5 seg |Este valor limita el tiempo de espera de este método. Si se alcanza el tiempo límite, se devolverán los datos en caché o el respaldo local.
Ten en cuenta que en casos excepcionales este método puede agotar el tiempo de espera ligeramente después de lo especificado en `loadTimeout`, ya que la operación puede consistir en diferentes solicitudes internamente.
| Parámetros de respuesta: | Parámetro | Descripción | |:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------| | Onboarding | Un objeto [`AdaptyOnboarding`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyOnboarding-class.html) con: el identificador y la configuración del onboarding, el Remote Config y otras propiedades. | ## Acelerar la obtención del onboarding con el onboarding de audiencia predeterminada \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} Por lo general, los onboardings se obtienen casi de forma instantánea, por lo que no es necesario preocuparse por acelerar este proceso. Sin embargo, en casos donde tienes muchas audiencias y onboardings, y tus usuarios tienen una conexión a internet débil, obtener un onboarding puede tardar más de lo deseable. En esas situaciones, puede que quieras mostrar un onboarding predeterminado para garantizar una experiencia fluida en lugar de no mostrar ninguno. Para esto, puedes usar el método `getOnboardingForDefaultAudience`, que obtiene el onboarding del placement especificado para la audiencia **All Users**. Sin embargo, es fundamental entender que el enfoque recomendado es obtener el onboarding con el método `getOnboarding`, como se detalla en la sección [Obtener el onboarding](#fetch-onboarding) anterior. :::warning Considera usar `getOnboarding` en lugar de `getOnboardingForDefaultAudience`, ya que este último tiene limitaciones importantes: - **Problemas de compatibilidad**: Puede crear problemas al admitir varias versiones de la app, lo que requiere diseños compatibles hacia atrás o aceptar que las versiones más antiguas puedan mostrarse incorrectamente. - **Sin personalización**: Solo muestra contenido para la audiencia "All Users", eliminando la segmentación basada en país, atribución o atributos personalizados. Si una obtención más rápida supera estos inconvenientes para tu caso de uso, utiliza `getOnboardingForDefaultAudience` como se muestra a continuación. De lo contrario, usa `getOnboarding` como se describe [arriba](#fetch-onboarding). ::: ```dart showLineNumbers try { final onboarding = await Adapty().getOnboardingForDefaultAudience(placementId: 'YOUR_PLACEMENT_ID'); } on AdaptyError catch (adaptyError) { // handle error } catch (e) { // handle unknown error } ``` Parámetros: | Parámetro | Presencia | Descripción | |-----------------|-----------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | obligatorio | El identificador del [Placement](placements) deseado. Es el valor que especificaste al crear un placement en el Adapty Dashboard. | | **locale** |opcional
por defecto: `en`
|El identificador de la localización del onboarding. Se espera que este parámetro sea un código de idioma compuesto por uno o dos subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar los datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre reciban los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen conexiones inestables a internet, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En este caso, puede que los usuarios no reciban los últimos datos, pero experimentarán tiempos de carga más rápidos independientemente de lo inestable que sea su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se reinstala la app o mediante una limpieza manual.
El SDK de Adapty almacena los onboardings localmente en dos capas: la caché de actualización regular descrita anteriormente y los onboardings de respaldo. También usamos CDN para obtener los onboardings más rápido y un servidor de respaldo independiente en caso de que el CDN no sea accesible. Este sistema está diseñado para garantizar que siempre obtengas la última versión de tus onboardings y asegurar la fiabilidad incluso cuando la conexión a internet es escasa.
| --- # File: flutter-present-onboardings --- --- title: "Presentar onboardings en Flutter SDK" description: "Aprende a presentar onboardings de forma efectiva para impulsar más conversiones." --- Si has personalizado un onboarding con el builder, no necesitas preocuparte por renderizarlo en el código de tu app Flutter para mostrárselo al usuario. Ese onboarding ya contiene tanto lo que debe mostrarse como la forma en que debe hacerse. Antes de empezar, asegúrate de que: 1. Tienes instalado el [SDK de Flutter de Adapty](sdk-installation-flutter) versión 3.8.0 o posterior. 2. Has [creado un onboarding](create-onboarding). 3. Has añadido el onboarding a un [placement](placements). El SDK de Flutter de Adapty ofrece dos formas de presentar onboardings: - **Pantalla independiente** - **Widget embebido** ## Presentar como pantalla independiente \{#present-as-standalone-screen\} Para mostrar un onboarding como pantalla independiente, usa el método `onboardingView.present()` en el `onboardingView` creado por el método `createOnboardingView`. Cada `view` solo puede usarse una vez. Si necesitas mostrar el onboarding de nuevo, llama a `createOnboardingView` otra vez para crear una nueva instancia de `onboardingView`. :::warning Reutilizar el mismo `onboardingView` sin recrearlo puede provocar un error `AdaptyUIError.viewAlreadyPresented`. ::: ```javascript showLineNumbers title="Flutter" try { await onboardingView.present(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ### Cerrar el onboarding \{#dismiss-the-onboarding\} Cuando necesites cerrar el onboarding por código, usa el método `dismiss()`: ```dart showLineNumbers title="Flutter" try { await onboardingView.dismiss(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ### Configurar el estilo de presentación en iOS \{#configure-ios-presentation-style\} Configura cómo se presenta el onboarding en iOS pasando el parámetro `iosPresentationStyle` al método `present()`. El parámetro acepta los valores `AdaptyUIIOSPresentationStyle.fullScreen` (predeterminado) o `AdaptyUIIOSPresentationStyle.pageSheet`. ```dart showLineNumbers try { await onboardingView.present(iosPresentationStyle: AdaptyUIIOSPresentationStyle.pageSheet); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ## Embeber en la jerarquía de widgets \{#embed-in-widget-hierarchy\} Para embeber un onboarding dentro de tu árbol de widgets existente, usa el widget `AdaptyUIOnboardingPlatformView` directamente en la jerarquía de widgets de Flutter. ```javascript showLineNumbers title="Flutter" AdaptyUIOnboardingPlatformView( onboarding: onboarding, // The onboarding object you fetched onDidFinishLoading: (meta) { }, onDidFailWithError: (error) { }, onCloseAction: (meta, actionId) { }, onPaywallAction: (meta, actionId) { }, onCustomAction: (meta, actionId) { }, onStateUpdatedAction: (meta, elementId, params) { }, onAnalyticsEvent: (meta, event) { }, ) ``` :::note Para que la platform view de Android funcione, asegúrate de que tu `MainActivity` extiende `FlutterFragmentActivity`: ```kotlin showLineNumbers title="Kotlin" class MainActivity : FlutterFragmentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) } } ``` ::: ## Loader durante el onboarding \{#loader-during-onboarding\} Al presentar un onboarding, puede que notes una breve pantalla de carga entre tu splash screen y el onboarding mientras se inicializa la vista subyacente. Puedes gestionar esto de distintas formas según tus necesidades. #### Controlar el splash screen con onDidFinishLoading \{#control-splash-screen-using-ondidfinishloading\} :::note Este enfoque solo está disponible cuando el onboarding se embebe como widget. No está disponible para la presentación como pantalla independiente. ::: El enfoque multiplataforma recomendado es mantener visible tu splash screen o superposición personalizada hasta que el onboarding se haya cargado por completo y luego ocultarla manualmente. Al usar el widget embebido, superpón tu propio widget sobre él y oculta la superposición cuando se dispare `onDidFinishLoading`: ```dart showLineNumbers title="Flutter" AdaptyUIOnboardingPlatformView( onboarding: onboarding, onDidFinishLoading: (meta) { // Hide your custom splash screen or overlay here }, // ... other callbacks ) ``` ### Personalizar el loader nativo \{#customize-native-loader\} :::important Este enfoque es específico de plataforma y requiere mantener código de UI nativo. No se recomienda a menos que ya mantengas capas nativas separadas en tu app. ::: Si necesitas personalizar el loader predeterminado, puedes reemplazarlo con layouts específicos de cada plataforma. Este enfoque requiere implementaciones separadas para Android e iOS: - **iOS**: Añade `AdaptyOnboardingPlaceholderView.xib` a tu proyecto de Xcode - **Android**: Crea `adapty_onboarding_placeholder_view.xml` en `res/layout` y define ahí un placeholder ## Personalizar cómo se abren los enlaces en los onboardings \{#customize-how-links-open-in-onboardings\} :::important La personalización de cómo se abren los enlaces en los onboardings está disponible a partir del SDK de Adapty v.3.15.1. ::: Por defecto, los enlaces en los onboardings se abren en un navegador in-app. Esto ofrece una experiencia fluida al mostrar las páginas web dentro de tu aplicación, sin que el usuario tenga que cambiar de app. Si prefieres abrir los enlaces en un navegador externo, puedes personalizar este comportamiento estableciendo el parámetro `externalUrlsPresentation` en `AdaptyWebPresentation.externalBrowser`:
Después puedes usar este ID en tu código y gestionarlo como una acción personalizada. Por ejemplo, si un usuario pulsa un botón personalizado como **Login** o **Allow notifications**, el método delegado `onboardingController` se activará con el caso `.custom(id:)` y el parámetro `actionId` corresponde al **Action ID** del builder. Puedes crear tus propios IDs, como "allowNotifications".
```javascript
// Full-screen presentation
void onboardingViewOnCustomAction(
AdaptyUIOnboardingView view,
AdaptyUIOnboardingMeta meta,
String actionId,
) {
switch (actionId) {
case 'login':
_login();
break;
case 'allow_notifications':
_allowNotifications();
break;
}
}
// Embedded widget
onCustomAction: (meta, actionId) {
_handleCustomAction(actionId);
}
```
:::important
Ten en cuenta que debes gestionar qué ocurre cuando un usuario cierra el onboarding. Por ejemplo, debes dejar de mostrar el propio onboarding.
:::
```javascript showLineNumbers title="Flutter"
// Full-screen presentation
void onboardingViewOnCloseAction(
AdaptyUIOnboardingView view,
AdaptyUIOnboardingMeta meta,
String actionId,
) {
await view.dismiss();
}
// Embedded widget
onCloseAction: (meta, actionId) {
Navigator.of(context).pop();
}
```
2. Haz clic en el nombre del grupo de suscripciones. Verás tus productos listados en la sección **Subscriptions**.
3. Asegúrate de que el producto que estás probando esté marcado como **Ready to Submit**.
4. Compara el ID del producto de la tabla con el que aparece en la pestaña [**Products**](https://app.adapty.io/products) del Adapty Dashboard. Si los IDs no coinciden, copia el ID del producto de la tabla y [crea un producto](create-product) con ese ID en el Adapty Dashboard.
## Paso 3. Comprueba la disponibilidad del producto \{#step-4-check-product-availability\}
1. Vuelve a **App Store Connect** y abre la misma sección **Subscriptions**.
2. Haz clic en el nombre del grupo de suscripciones para ver tus productos.
3. Selecciona el producto que estás probando.
4. Desplázate hasta la sección **Availability** y comprueba que todos los países y regiones requeridos estén listados.
## Paso 4. Comprueba los precios del producto \{#step-5-check-product-prices\}
1. De nuevo, ve a la sección **Monetization** → **Subscriptions** en **App Store Connect**.
2. Haz clic en el nombre del grupo de suscripciones.
3. Selecciona el producto que estás probando.
4. Desplázate hacia abajo hasta **Subscription Pricing** y despliega la sección **Current Pricing for New Subscribers**.
5. Asegúrate de que todos los precios requeridos estén listados.
## Paso 5. Comprueba que el estado de pago de la app, la cuenta bancaria y los formularios fiscales estén activos \{#step-5-check-app-paid-status-bank-account-and-tax-forms-are-active\}
1. En la página de inicio de [**App Store Connect**](https://appstoreconnect.apple.com/), haz clic en **Business**.
2. Selecciona el nombre de tu empresa.
3. Desplázate hacia abajo y comprueba que tu **Paid Apps Agreement**, tu **Bank Account** y tus **Tax forms** aparezcan como **Active**.
Siguiendo estos pasos, deberías poder resolver la advertencia `InvalidProductIdentifiers` y tener tus productos disponibles en la store.
## Paso 6. Recrea el producto si está bloqueado \{#step-6-recreate-the-product-if-its-stuck\}
Es posible que los pasos 1–5 pasen todos correctamente —estado `Approved`, Bundle ID coincidente, API key válida— y aun así el SDK devuelva `1000 noProductIDsFound`. En ese caso, puede que el producto esté bloqueado en el registro de Apple. El registro de productos de Apple entra ocasionalmente en un estado en el que un producto existe en la interfaz de App Store Connect pero no está expuesto en la ruta de búsqueda de StoreKit.
Elimina el producto en App Store Connect y vuelve a crearlo con el mismo ID de producto. Espera hasta 24 horas tras la recreación para que los cambios se propaguen.
---
# File: cantMakePayments-flutter
---
---
title: "Solución al error Code-1003 cantMakePayment en Flutter SDK"
description: "Resuelve el error de realización de pagos al gestionar suscripciones en Adapty."
---
El error 1003, `cantMakePayments`, indica que no es posible realizar compras in-app en este dispositivo.
Si encuentras el error `cantMakePayments`, normalmente se debe a una de estas razones:
- Restricciones del dispositivo: El error no está relacionado con Adapty. Consulta las soluciones más abajo.
- Configuración del modo Observer: El método `makePurchase` y el modo Observer no pueden usarse al mismo tiempo. Consulta la sección más abajo.
## Problema: Restricciones del dispositivo \{#issue-device-restrictions\}
| Problema | Solución |
|-------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|
| Restricciones de Screen Time | Desactiva las restricciones de compras in-app en [Screen Time](https://support.apple.com/en-us/102470) |
| Cuenta suspendida | Contacta con el soporte de Apple para resolver problemas con la cuenta |
| Restricciones regionales | Usa una cuenta de App Store de una región compatible |
## Problema: Usar el modo Observer y makePurchase a la vez \{#issue-using-both-observer-mode-and-makepurchase\}
Si usas `makePurchases` para gestionar las compras, no necesitas el modo Observer. El [modo Observer](observer-vs-full-mode) solo es necesario si implementas la lógica de compra tú mismo.
Por lo tanto, si usas `makePurchase`, puedes eliminar sin problema la activación del modo Observer del código de inicialización del SDK.
---
# File: flutter-migration-guide-310
---
---
title: "Guía de migración al SDK de Adapty para Flutter 3.10.0"
description: ""
---
El SDK de Adapty 3.10.0 es una versión principal que incorpora mejoras que, sin embargo, pueden requerir algunos pasos de migración por tu parte:
1. Actualiza el método `makePurchase` para usar `AdaptyPurchaseParameters` en lugar de parámetros individuales.
2. Reemplaza `vendorProductIds` por `productIdentifiers` en el modelo `AdaptyPaywall`.
## Actualizar el método makePurchase \{#update-makepurchase-method\}
El método `makePurchase` ahora usa `AdaptyPurchaseParameters` en lugar de los argumentos individuales `subscriptionUpdateParams` e `isOfferPersonalized`. Esto proporciona mayor seguridad de tipos y permite una mayor extensibilidad de los parámetros de compra en el futuro.
```diff showLineNumbers
- final purchaseResult = await adapty.makePurchase(
- product: product,
- subscriptionUpdateParams: subscriptionUpdateParams,
- isOfferPersonalized: true,
- );
+ final parameters = AdaptyPurchaseParametersBuilder()
+ ..setSubscriptionUpdateParams(subscriptionUpdateParams)
+ ..setIsOfferPersonalized(true)
+ ..setObfuscatedAccountId('your-account-id')
+ ..setObfuscatedProfileId('your-profile-id');
+ final purchaseResult = await adapty.makePurchase(
+ product: product,
+ parameters: parameters.build(),
+ );
```
Si no necesitas parámetros adicionales, puedes usar simplemente:
```dart showLineNumbers
final purchaseResult = await adapty.makePurchase(
product: product,
);
```
## Actualizar el uso del modelo AdaptyPaywall \{#update-adaptyp-aywall-model-usage\}
La propiedad `vendorProductIds` ha quedado obsoleta en favor de `productIdentifiers`. La nueva propiedad devuelve objetos `AdaptyProductIdentifier` en lugar de cadenas de texto simples, lo que ofrece información de producto con una estructura más organizada.
```diff showLineNumbers
- paywall.vendorProductIds.map((vendorId) =>
- ListTextTile(title: vendorId)
- ).toList()
+ paywall.productIdentifiers.map((productId) =>
+ ListTextTile(title: productId.vendorProductId)
+ ).toList()
```
El objeto `AdaptyProductIdentifier` proporciona acceso al ID del producto del proveedor a través de la propiedad `vendorProductId`, manteniendo la misma funcionalidad y ofreciendo una mejor estructura para mejoras futuras.
## Compatibilidad con versiones anteriores \{#backward-compatibility\}
Ambos cambios mantienen la compatibilidad con versiones anteriores:
- Los parámetros antiguos en `makePurchase` están obsoletos, pero siguen funcionando
- La propiedad `vendorProductIds` está obsoleta, pero sigue siendo accesible
- El código existente seguirá funcionando, aunque verás advertencias de obsolescencia
Te recomendamos actualizar tu código para usar las nuevas API y garantizar la compatibilidad futura, además de aprovechar la mayor seguridad de tipos y extensibilidad.
---
# File: flutter-migration-guide-38
---
---
title: "Migrar el SDK de Adapty para Flutter a v. 3.8"
description: "Migra al SDK de Adapty para Flutter v3.8 para obtener mejor rendimiento y nuevas funciones de monetización."
---
El SDK 3.8.0 de Adapty es una versión mayor que incluye mejoras que pueden requerir algunos pasos de migración por tu parte.
1. Actualiza los nombres de la clase observadora y sus métodos.
2. Actualiza el nombre del método de paywalls de respaldo.
3. Actualiza el nombre de la clase de vista en los métodos de manejo de eventos.
## Actualiza los nombres de la clase observadora y sus métodos \{#update-observer-class-and-method-names\}
La clase observadora y su método de registro han sido renombrados:
```diff showLineNumbers
- class MyObserver extends AdaptyUIObserver {
+ class MyObserver extends AdaptyUIPaywallsEventsObserver {
@override
void paywallViewDidPerformAction(AdaptyUIView view, AdaptyUIAction action) {
// Handle action
}
}
// Register observer
- AdaptyUI().setObserver(this);
+ AdaptyUI().setPaywallsEventsObserver(this);
```
## Actualiza el nombre del método de paywalls de respaldo \{#update-fallback-paywalls-method-name\}
El método para configurar los paywalls de respaldo ha sido simplificado:
```diff showLineNumbers
try {
- await Adapty.setFallbackPaywalls(assetId);
+ await Adapty.setFallback(assetId);
} on AdaptyError catch (adaptyError) {
// handle the error
} catch (e) {
// handle the error
}
```
## Actualiza el nombre de la clase de vista en los métodos de manejo de eventos \{#update-view-class-name-in-event-handling-methods\}
Todos los métodos de manejo de eventos ahora usan la nueva clase `AdaptyUIPaywallView` en lugar de `AdaptyUIView`:
```diff showLineNumbers
- void paywallViewDidPerformAction(AdaptyUIView view, AdaptyUIAction action)
+ void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action)
- void paywallViewDidSelectProduct(AdaptyUIView view, AdaptyPaywallProduct product)
+ void paywallViewDidSelectProduct(AdaptyUIPaywallView view, AdaptyPaywallProduct product)
- void paywallViewDidStartPurchase(AdaptyUIView view, AdaptyPaywallProduct product)
+ void paywallViewDidStartPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product)
- void paywallViewDidFinishPurchase(AdaptyUIView view, AdaptyPaywallProduct product, AdaptyProfile profile)
+ void paywallViewDidFinishPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyProfile profile)
- void paywallViewDidFailPurchase(AdaptyUIView view, AdaptyPaywallProduct product, AdaptyError error)
+ void paywallViewDidFailPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyError error)
- void paywallViewDidFinishRestore(AdaptyUIView view, AdaptyProfile profile)
+ void paywallViewDidFinishRestore(AdaptyUIPaywallView view, AdaptyProfile profile)
- void paywallViewDidFailRestore(AdaptyUIView view, AdaptyError error)
+ void paywallViewDidFailRestore(AdaptyUIPaywallView view, AdaptyError error)
- void paywallViewDidFailLoadingProducts(AdaptyUIView view, AdaptyIOSProductsFetchPolicy? fetchPolicy, AdaptyError error)
+ void paywallViewDidFailLoadingProducts(AdaptyUIPaywallView view, AdaptyIOSProductsFetchPolicy? fetchPolicy, AdaptyError error)
- void paywallViewDidFailRendering(AdaptyUIView view, AdaptyError error)
+ void paywallViewDidFailRendering(AdaptyUIPaywallView view, AdaptyError error)
```
---
# File: migration-to-flutter-sdk-34
---
---
title: "Migrar Adapty Flutter SDK a la v. 3.4"
description: "Migra al Adapty Flutter SDK v3.4 para mejor rendimiento y nuevas funciones de monetización."
---
Adapty SDK 3.4.0 es una versión mayor que introduce mejoras que requieren pasos de migración por tu parte.
## Actualizar los archivos de paywall de respaldo \{#update-fallback-paywall-files\}
Actualiza tus archivos de paywall de respaldo para garantizar la compatibilidad con la nueva versión del SDK:
1. [Descarga los archivos de paywall de respaldo actualizados](fallback-paywalls) desde el Adapty Dashboard.
2. [Reemplaza los paywalls de respaldo existentes en tu app](flutter-use-fallback-paywalls) con los nuevos archivos.
## Actualizar la implementación del modo Observer \{#update-implementation-of-observer-mode\}
Si usas el modo Observer, asegúrate de actualizar su implementación.
Anteriormente, se usaban distintos métodos para reportar transacciones a Adapty. En la nueva versión, el método `reportTransaction` debe usarse de forma consistente tanto en Android como en iOS. Este método reporta explícitamente cada transacción a Adapty, asegurando que sea reconocida. Si se usó un paywall, pasa el ID de variación para vincular la transacción con él.
:::warning
**¡No omitas el reporte de transacciones!**
Si no llamas a `reportTransaction`, Adapty no reconocerá la transacción, no aparecerá en los análisis y no se enviará a las integraciones.
:::
```diff showLineNumbers
- // every time when calling transaction.finish()
- if (Platform.isAndroid) {
- try {
- await Adapty().restorePurchases();
- } on AdaptyError catch (adaptyError) {
- // handle the error
- } catch (e) {
- }
- }
try {
// every time when calling transaction.finish()
await Adapty().reportTransaction(
"YOUR_TRANSACTION_ID",
variationId: "PAYWALL_VARIATION_ID", // optional
);
} on AdaptyError catch (adaptyError) {
// handle the error
} catch (e) {
// handle the error
}
```
---
# File: migration-to-flutter330
---
---
title: "Migrar el SDK de Adapty Flutter a v. 3.3"
description: "Migra al SDK de Adapty Flutter v3.3 para mejor rendimiento y nuevas funcionalidades de monetización."
---
Adapty SDK 3.3.0 es una versión mayor que incluye mejoras que pueden requerir algunos pasos de migración de tu parte.
1. Actualiza el método para proporcionar paywalls de respaldo.
2. Elimina el método `getProductsIntroductoryOfferEligibility`.
3. Actualiza las configuraciones de integración para Adjust, AirBridge, Amplitude, AppMetrica, Appsflyer, Branch, Facebook Ads, Firebase y Google Analytics, Mixpanel, OneSignal, Pushwoosh.
4. Actualiza la implementación del modo Observer.
## Actualiza el método para proporcionar paywalls de respaldo \{#update-method-for-providing-fallback-paywalls\}
Anteriormente, el método requería el paywall de respaldo como una cadena JSON (`jsonString`), pero ahora recibe la ruta al archivo de respaldo local (`assetId`).
```diff showLineNumbers
import 'dart:async' show Future;
import 'dart:io' show Platform;
-import 'package:flutter/services.dart' show rootBundle;
-final filePath = Platform.isIOS ? 'assets/ios_fallback.json' : 'assets/android_fallback.json';
-final jsonString = await rootBundle.loadString(filePath);
+final assetId = Platform.isIOS ? 'assets/ios_fallback.json' : 'assets/android_fallback.json';
try {
- await adapty.setFallbackPaywalls(jsonString);
+ await adapty.setFallbackPaywalls(assetId);
} on AdaptyError catch (adaptyError) {
// handle the error
} catch (e) {
}
```
Para ver el ejemplo de código completo, consulta la página [Usar paywalls de respaldo](flutter-use-fallback-paywalls).
## Elimina el método `getProductsIntroductoryOfferEligibility` \{#remove-getproductsintroductoryoffereligibility-method\}
Antes del SDK de Adapty iOS 3.3.0, el objeto de producto siempre incluía las ofertas, independientemente de si el usuario era elegible. Tenías que verificar la elegibilidad manualmente antes de usar la oferta.
Ahora, el objeto de producto solo incluye una oferta si el usuario es elegible. Esto significa que ya no necesitas verificar la elegibilidad: si hay una oferta presente, el usuario es elegible.
## Actualiza la configuración del SDK de integraciones de terceros \{#update-third-party-integration-sdk-configuration\}
Para garantizar que las integraciones funcionen correctamente con el SDK de Adapty Flutter 3.3.0 y versiones posteriores, actualiza las configuraciones de tu SDK para las siguientes integraciones tal como se describe en las secciones a continuación.
### Adjust \{#adjust\}
Actualiza el código de tu app como se muestra a continuación. Para ver el ejemplo de código completo, consulta la [configuración del SDK para la integración con Adjust](adjust#connect-your-app-to-adjust).
```diff showLineNumbers
import 'package:adjust_sdk/adjust.dart';
import 'package:adjust_sdk/adjust_config.dart';
try {
final adid = await Adjust.getAdid();
if (adid == null) {
// handle the error
}
+ await Adapty().setIntegrationIdentifier(
+ key: "adjust_device_id",
+ value: adid,
+ );
final attributionData = await Adjust.getAttribution();
var attribution = MapUn valor booleano que controla el [modo Observer](observer-vs-full-mode). Actívalo si gestionas las compras y el estado de las suscripciones tú mismo y usas Adapty solo para enviar eventos de suscripción y analíticas.
El valor predeterminado es `false`.
🚧 Al ejecutarse en modo Observer, el SDK de Adapty no cerrará ninguna transacción, así que asegúrate de gestionarlas tú.
| | **withCustomerUserId** | opcional | Un identificador del usuario en tu sistema. Lo enviamos en eventos de suscripción y analíticos para atribuir los eventos al perfil correcto. También puedes buscar clientes por `customerUserId` en el menú [**Profiles and Segments**](https://app.adapty.io/profiles/users). | | **withIdfaCollectionDisabled** | opcional |Ponlo en `true` para deshabilitar la recopilación y el uso compartido del IDFA.
la dirección IP del usuario.
El valor predeterminado es `false`.
Para más detalles sobre la recopilación del IDFA, consulta la sección [Integración de analíticas](analytics-integration#disable-collection-of-advertising-identifiers).
| | **withIpAddressCollectionDisabled** | opcional |Ponlo en `true` para deshabilitar la recopilación y el uso compartido de la dirección IP del usuario.
El valor predeterminado es `false`.
| ### Activar el módulo AdaptyUI del SDK de Adapty \{#activate-adaptyui-module-of-adapty-sdk\} Solo necesitas configurar el módulo AdaptyUI si planeas usar el [Paywall Builder](adapty-paywall-builder): ```dart showLineNumbers title="Dart" try { final mediaCache = AdaptyUIMediaCacheConfiguration( memoryStorageTotalCostLimit: 100 * 1024 * 1024, // 100MB memoryStorageCountLimit: 2147483647, // 2^31 - 1, max int value in Dart diskStorageSizeLimit: 100 * 1024 * 1024, // 100MB ); await AdaptyUI().activate( configuration: AdaptyUIConfiguration(mediaCache: mediaCache), observer: