---
title: "Realizar compras in-app en Unity SDK"
description: "Guía sobre cómo gestionar compras in-app y suscripciones usando Adapty."
---

Mostrar paywalls en tu app es un paso fundamental para ofrecer a los usuarios acceso a contenido o servicios premium. Sin embargo, mostrarlos es suficiente para gestionar las compras solo si usas el [Paywall Builder](adapty-paywall-builder) para personalizar tus paywalls.

Si no usas el Paywall Builder, debes usar un método independiente 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 completen 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 se aplicará automáticamente solo si usas paywalls configurados con el Paywall Builder.

En otros casos, deberás [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 suponer cobrar el precio completo a usuarios que tienen derecho a 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 saltarte este paso.

**¿Buscas una guía paso a paso?** Consulta la [guía de inicio rápido](unity-implement-paywalls-manually) para instrucciones de implementación completas con todo el contexto.
:::

```csharp showLineNumbers
using AdaptySDK;

void MakePurchase(AdaptyPaywallProduct product) {
  Adapty.MakePurchase(product, (result, error) => {
    switch (result.Type) {
      case AdaptyPurchaseResultType.Pending:
        // handle pending purchase
        break;
      case AdaptyPurchaseResultType.UserCancelled:
        // handle purchase cancellation
        break;
      case AdaptyPurchaseResultType.Success:
        var profile = result.Profile;
        // handle successfull purchase
        break;
      default:
        break;
    }
  });
}
```

Parámetros de la solicitud:

| Parámetro   | Presencia | Descripción                                                                                           |
| :---------- | :------- |:------------------------------------------------------------------------------------------------------|
| **Product** | obligatorio | Un objeto [`AdaptyPaywallProduct`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall_product.html) obtenido del paywall. |

Parámetros de la respuesta:

| Parámetro | Descripción                                                                                                                                                                                                                                                                                                                                                                  |
|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **Profile** | <p>Si la solicitud fue exitosa, la respuesta incluye este objeto. Un objeto [AdaptyProfile](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_profile.html) proporciona información completa sobre los niveles de acceso, suscripciones y compras únicas del usuario dentro de la app.</p><p>Verifica el estado del nivel de acceso para confirmar si el usuario tiene el acceso requerido a la app.</p> |

:::warning
**Nota:** si todavía usas la versión de StoreKit de Apple inferior a v2.0 y la versión del SDK de Adapty inferior a v.2.9.0, debes proporcionar el [secreto compartido de App Store de Apple](app-store-connection-configuration#step-5-enter-app-store-shared-secret) en su lugar. 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 elige una nueva suscripción en lugar de renovar la actual, el funcionamiento depende del store:

- En el 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 una suscripción de otro, ambas suscripciones estarán activas al mismo tiempo.
- En Google Play, la suscripción no se actualiza automáticamente. Deberás gestionar el cambio en el código de tu app 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:

```csharp showLineNumbers
// Create subscription update parameters
var subscriptionUpdateParams = new AdaptySubscriptionUpdateParameters(
    "old_product_id", // Product ID of the current subscription
    AdaptySubscriptionUpdateReplacementMode.WithTimeProration
);

Adapty.MakePurchase(product, subscriptionUpdateParams, (profile, error) => {
  if(error != null) {
      // Handle the error
      return;
  }

  // successful cross-grade
});
```

Parámetro adicional de la solicitud:

| Parámetro                    | Presencia | Descripción                                                                                            |
| :--------------------------- | :------- |:-------------------------------------------------------------------------------------------------------|
| **subscriptionUpdateParams** | obligatorio | Un objeto [`AdaptySubscriptionUpdateParameters`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_subscription_update_parameters.html). |

Puedes leer más sobre suscripciones y 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. No se admiten degradaciones.
- Modo de reemplazo [`DEFERRED`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#DEFERRED()). Nota: el cambio real de suscripción 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';

<Details>
<summary>Sobre los códigos de oferta</summary>

Los códigos de oferta te permiten dar descuentos o períodos de prueba gratuitos a usuarios concretos. A diferencia de las ofertas habituales, que se aplican de forma automática, los códigos de oferta se distribuyen fuera de la app — por email, redes sociales o materiales impresos. Los usuarios los canjean introduciendo el código en el App Store, accediendo a una URL de canje o a través de un diálogo dentro de la app.

Para configurar códigos de oferta, abre una suscripción en App Store Connect y ve a su sección **Offer Codes**. Puedes crear [tres tipos](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-subscription-offer-codes) de códigos de oferta:

- **Free** — la suscripción es gratuita durante un período determinado y la siguiente renovación se cobra al precio completo.
- **Pay as you go** — el usuario paga un precio reducido en cada ciclo de facturación durante un período determinado y, después, la suscripción se renueva al precio completo.
- **Pay up front** — el usuario paga un precio único reducido por toda la duración de la oferta y, después, la suscripción se renueva al precio completo.

No es necesario añadir los códigos de oferta a Adapty. Apple etiqueta cada transacción durante el período de la oferta con la categoría del código de oferta. Esto incluye el canje inicial y todas las renovaciones con descuento posteriores. Adapty detecta la etiqueta y registra cada transacción con la categoría de oferta `offer_code`. Cuando termina el período de oferta y la suscripción se renueva al precio completo, la etiqueta deja de estar presente. Puedes filtrar los análisis por el tipo de oferta **Offer Code** en el [Adapty Dashboard](controls-filters-grouping-compare-proceeds).

#### Resolución de discrepancias en los ingresos \{#revenue-discrepancy-troubleshooting\}

Si observas que una transacción con código de oferta aparece en Adapty al precio completo del producto en lugar del precio reducido, verifica lo siguiente en App Store Connect:

- El código de oferta tiene los precios correctos configurados para todas las regiones donde los usuarios pueden canjearlo.
- El precio de la oferta está configurado para el país o región específica del usuario. Apple envía el precio regional en la transacción. Si no hay ningún precio regional configurado para la oferta, Apple puede enviar el precio completo del producto.

Puedes filtrar y verificar las transacciones con código de oferta en el [Adapty Dashboard](controls-filters-grouping-compare-proceeds) mediante los filtros de tipo de oferta **Offer Code** y **Offer Discount Type**.

#### Códigos promocionales heredados (obsoletos) \{#legacy-promo-codes-deprecated\}

<Callout type="warning">
Apple dejó obsoletos los códigos promocionales para compras in-app en marzo de 2026. Los códigos de oferta los sustituyen con más funcionalidades: elegibilidad configurable, fechas de expiración y hasta 1 millón de códigos por trimestre. Si antes usabas códigos promocionales para compras in-app, migra a los códigos de oferta en App Store Connect.
</Callout>

Los códigos promocionales heredados (limitados a 100 por app y versión) daban acceso gratuito a una suscripción. A diferencia de los códigos de oferta, Apple no incluía información de descuento en las transacciones con código promocional — enviaba el precio completo del producto en el recibo. Por ello, Adapty registraba estas transacciones al precio completo, lo que generaba discrepancias entre los análisis de Adapty y App Store Connect.

Si ves transacciones históricas al precio completo que deberían haber sido gratuitas, es probable que provengan de códigos promocionales heredados. Como estos códigos ya están obsoletos, migra a los códigos de oferta para un seguimiento preciso de los ingresos.

</Details>

Para mostrar la hoja de canje de códigos en tu app:

```csharp showLineNumbers
Adapty.PresentCodeRedemptionSheet((error) => {
  // handle the error
});
```

:::danger
Según nuestras observaciones, la hoja de canje de códigos de oferta puede no funcionar de forma fiable en algunas apps. Recomendamos redirigir al usuario directamente al App Store.

Para ello, debes abrir la URL con el siguiente formato:
`https://apps.apple.com/redeem?ctx=offercodes&id={apple_app_id}&code={code}`
:::

## Gestionar planes prepago (Android) \{#manage-prepaid-plans-android\}

Si los usuarios de tu app pueden comprar [planes prepago](https://developer.android.com/google/play/billing/subscriptions#prepaid-plans) (por ejemplo, comprar una suscripción no renovable por varios meses), puedes habilitar las [transacciones pendientes](https://developer.android.com/google/play/billing/subscriptions#pending) para planes prepago.

```csharp showLineNumbers title="Unity"
using UnityEngine;
using AdaptySDK;

var builder = new AdaptyConfiguration.Builder("YOUR_API_KEY")
    .SetGoogleEnablePendingPrepaidPlans(true);

Adapty.Activate(builder.Build(), (error) => {
    if (error != null) {
        // handle the error
        return;
    }
}); 
```