> For the complete documentation index, see [llms.txt](https://docs.allout.game/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.allout.game/all-out-docs/docs-es/conceptos-basicos-del-motor/purchasing-product-apis.md).

# API de compras/productos

Los jugadores pueden comprar productos (pases de juego + consumibles) por Sparks en tu juego. Cuando se realiza una compra, All Out llama a tu **controlador de compras** para que puedas otorgar el objeto o la función.

{% hint style="info" %}
Para crear productos y ver analíticas, consulta [Productos dentro del juego](/all-out-docs/docs-es/monetizacion/in-game-products.md).
{% endhint %}

### Tipos de productos (resumen rápido)

* **Pases de juego**: desbloqueos permanentes de una sola vez (pase de administrador, habilidad permanente, propiedad de una casa)
* **Consumibles**: se pueden comprar varias veces (poción, mejora temporal, paquete de monedas de una sola vez)

Los tipos de productos se configuran en el portal de creadores. Consulta [Productos dentro del juego](/all-out-docs/docs-es/monetizacion/in-game-products.md).

### Referencia de la API de compras

```go
Product :: struct {
    id: string;
    name: string;
    description: string;
    price: s64;
    consumable: bool;
    icon: Texture_Asset;
}

Purchasing :: struct {
    prompt_purchase :: proc(player: Player, id: string);
    owns_product    :: proc(player: Player, id: string) -> bool;
    get_product     :: proc(id: string) -> Product;
}
```

### Solicitar una compra

Para iniciar el flujo de compra, llama a `Purchasing.prompt_purchase` con un ID de producto.

```go
BUY_DOUBLE_JUMP_ID :: "prod_double_jump";

try_prompt_double_jump :: proc(player: Player) {
    Purchasing.prompt_purchase(player, BUY_DOUBLE_JUMP_ID);
}
```

{% hint style="info" %}
El ID del producto se muestra en la página de monetización/productos del portal de creadores (puedes hacer clic para copiarlo). Consulta [Productos dentro del juego](/all-out-docs/docs-es/monetizacion/in-game-products.md).
{% endhint %}

### Comprobar si un jugador posee un producto (pases de juego)

Para los pases de juego, puedes restringir funciones de juego comprobando la propiedad.

```go
ADMIN_PASS_ID :: "prod_admin";

is_admin :: proc(player: Player) -> bool {
    return Purchasing.owns_product(player, ADMIN_PASS_ID);
}
```

{% hint style="info" %}
Los consumibles se pueden comprar varias veces; no debería usarse owns\_product para otorgarlos. Los consumibles normalmente se otorgan en tu controlador de compras (monedas, objetos, mejoras, etc).
{% endhint %}

### Leer información del producto (nombre/precio/icono)

Si quieres mostrar una interfaz de “Comprar” o registrar información del producto, obtén la definición del producto por ID:

```go
product := Purchasing.get_product("prod_double_jump");
log_info("El producto % cuesta % Sparks", {product.name, product.price});
```

### El controlador de compras (otorgamiento)

Cuando un jugador compra un producto en tu juego, All Out llama a:

```go
ao_purchase_handler :: proc(player: Player, id: string) -> bool
```

Si tu juego no define `ao_purchase_handler`, los productos no consumibles se otorgan automáticamente para que funcionen con `Purchasing.owns_product`. Los productos consumibles siguen requiriendo un controlador y se marcan como fallos de otorgamiento sin uno.

Debes:

* Hacer un switch sobre el ID del producto
* Otorgar el objeto/la función
* Devuelve `true` si el otorgamiento tuvo éxito
* Devuelve `false` si el otorgamiento falló (inventario lleno, requisito previo faltante, etc)

```go
COIN_PACK_ID :: "prod_coin_pack_small";
DOUBLE_JUMP_ID :: "prod_double_jump";

ao_purchase_handler :: proc(player: Player, id: string) -> bool {
    switch id {
        case COIN_PACK_ID: {
            // Ejemplo: otorgar monedas (consumible)
            Economy.deposit_currency(player, "Coins", 500);
            Notifier.notify(player, "¡Gracias! +500 monedas");
            return true;
        }
        case DOUBLE_JUMP_ID: {
            // Ejemplo: desbloqueo de pase de juego (permanente)
            // Normalmente solo lo habilitas mediante comprobaciones owns_product() en otra parte.
            // Aun así, devuelve true para que la compra se considere otorgada.
            Notifier.notify(player, "¡Doble salto desbloqueado!");
            return true;
        }
    }

    // ID desconocido
    return false;
}
```

### Fallos de otorgamiento y reintentos

Si tu controlador de compras devuelve `false`, la compra se marca como un **fallo de otorgamiento**.

* Los fallos de otorgamiento se muestran en el portal de creadores
* Se reintentan automáticamente cuando el jugador entra hasta que tienen éxito
* Puedes volver a ejecutar manualmente un controlador de compras marcando una compra como “sin otorgar” en la interfaz de datos del jugador

Consulta:

* [Productos dentro del juego](/all-out-docs/docs-es/monetizacion/in-game-products.md) (“Controladores de compras / Fallos de otorgamiento”)
* [Editar/ver datos del jugador](/all-out-docs/docs-es/datos-y-persistencia/editing-viewing-player-data.md) (sección “Compras”)

### Entre juegos (hub + minijuegos)

Si usas la jerarquía de juegos, las compras se pueden compartir entre tus juegos. Consulta [Productos/datos entre juegos](/all-out-docs/docs-es/datos-y-persistencia/cross-game-products-data.md).
