> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Operaciones básicas de la tienda

> Implemente una tienda del juego con las API de XStore, incluidas la determinación de lo que los usuarios pueden comprar, la comprobación de derechos y la finalización de compras.

Una tienda del juego normalmente implica tres operaciones básicas:

1. [Determinar lo que los usuarios pueden comprar](#1-determining-what-users-can-purchase)
2. [Evaluar qué productos posee el usuario o a cuáles tiene derecho](#2-evaluating-what-products-the-user-owns-or-is-entitled-to)
3. [Comprar productos aptos](#3-purchasing-eligible-products)

En este artículo se muestra código de ejemplo para cada operación, derivado del ejemplo InGameStore, que se actualiza continuamente para reflejar los procedimientos recomendados.

## Preparación para llamar a las API de XStore

Todas las API de `XStore` funcionan sobre un `XStoreContextHandle` creado mediante [XStoreCreateContext](/reference/system/xstore/xstore_members).

Este contexto le permite realizar operaciones de la tienda en el contexto del usuario especificado en la consola y del usuario predeterminado disponible en un PC. En la consola, un evento de suspensión o de reanudación rápida invalida el contexto. Para controlar estas condiciones de forma segura, cierre el `XStoreContextHandle` y vuelva a crearlo cada vez que el juego se reanude desde un estado suspendido.

## 1. Determinar lo que los usuarios pueden comprar

Lo que un juego suele ofrecer para su compra son sus complementos. El código siguiente muestra la llamada básica a la API [XStoreQueryAssociatedProductsAsync](/reference/system/xstore/xstore_members) necesaria para que el juego sepa qué productos están disponibles.

Esta consulta devuelve automáticamente solo los complementos **que se pueden comprar** asociados al juego. Los productos no relacionados asociados al mismo publicador (es decir, configurados con la misma cuenta de Partner Center) también pueden devolverse en esta llamada siempre que el juego tenga establecida una relación de tipo "can sell" con ese producto en la sección **Product relationship setup** de Partner Center.

Para obtener más información sobre cómo configurar relaciones de productos, consulte [Configurar relaciones de productos para un juego](/publishing/game-publishing/tutorial-xbox-managed/how-to-create-product-relationships).

```cpp theme={null}
bool CALLBACK ProductEnumerationCallback(const XStoreProduct* product, void* context)
{
    // Handle adding the product to the game

    printf("%s %s %u\n", product->title, product->storeId, product->productKind);

    return true;
}

void QueryCatalog()
{
    auto async = new XAsyncBlock{};
    async->queue = m_asyncQueue;
    async->callback = [](XAsyncBlock* async)
    {
        XStoreProductQueryHandle queryHandle = nullptr;

        HRESULT hr = XStoreQueryAssociatedProductsResult(async, &queryHandle);
        if (SUCCEEDED(hr))
        {
            hr = XStoreEnumerateProductsQuery(queryHandle, async->context, ProductEnumerationCallback);

            if (SUCCEEDED(hr))
            {
                // TODO: Check for more pages to process
                printf("Enumeration complete\n");
            }

            XStoreCloseProductsQueryHandle(queryHandle);
            delete async;
        }
    };

    XStoreProductKind typeFilter =
        XStoreProductKind::Consumable |
        XStoreProductKind::Durable |
        XStoreProductKind::Game;

    HRESULT hr = XStoreQueryAssociatedProductsAsync(
        m_xStoreContext,
        typeFilter,
        UINT8_MAX,  // placeholder maximum, see Paging
        async)

    if (FAILED(hr))
    {
        delete async;
    }
}
```

### Aspectos que se deben tener en cuenta

* Con `XStoreQueryAssociatedProductsAsync` solo se devuelven los productos que se pueden comprar; los productos que solo se conceden en lotes o que, por otros motivos, no están configurados para poder comprarse de forma independiente no se devuelven. Para estos últimos, use `XStoreQueryProductsAsync`.
* No se conoce de antemano el número de productos que se devuelven, por lo que el recuento debe acumularse.

### Paginación

El control de la paginación no es opcional al consultar productos asociados o derechos. El número de páginas devuelto por el servicio, y el número de elementos devueltos por página, pueden variar según el entorno y la carga del servicio. Para ver un ejemplo de cómo controlar la paginación, consulte [XStoreQueryAssociatedProductsAsync](/reference/system/xstore/xstore_members).

### Otras opciones

[XStoreQueryProductsAsync](/reference/system/xstore/xstore_members) se puede usar para consultar productos específicos, si se conoce el `storeId` o si se desean otros `actionFilters`. Las "acciones" son escenarios de uso que se aplican a un producto e incluyen verbos como `Purchase`, `License`, `Gift` y `Redeem`.

[XStoreQueryAssociatedProductsForStoreIdAsync](/reference/system/xstore/xstore_members) se puede usar para consultar los productos asociados de otros juegos, lo que puede ser útil para hacer ventas cruzadas de los complementos de otro título.

[XStoreQueryProductForCurrentGameAsync](/reference/system/xstore/xstore_members) sirve para consultar únicamente el producto del juego que se está ejecutando actualmente.

[XStoreShowAssociatedProductsUIAsync](/reference/system/xstore/xstore_members) lleva al usuario a la aplicación Microsoft Store, a una vista de los productos asociados, filtrados por tipo de producto. Esta API es una alternativa a tener que enumerar los productos disponibles para presentarlos en una interfaz del juego.

<img src="https://mintcdn.com/microsoft-4404708b/hprF_XHEe0cnRr8N/images/xstore/addonsforthisgame.webp?fit=max&auto=format&n=hprF_XHEe0cnRr8N&q=85&s=63d12502a1154059b4041a6556f4773e" alt="Complementos para este juego" width="1914" height="1061" data-path="images/xstore/addonsforthisgame.webp" />

## 2. Evaluar qué productos posee el usuario o a cuáles tiene derecho

Este paso implica gran parte del mismo código mostrado anteriormente, pero con estos reemplazos:

* [XStoreQueryAssociatedProductsAsync](/reference/system/xstore/xstore_members) → [XStoreQueryEntitledProductsAsync](/reference/system/xstore/xstore_members)
* [XStoreQueryAssociatedProductsResult](/reference/system/xstore/xstore_members) → [XStoreQueryEntitledProductsResult](/reference/system/xstore/xstore_members)

Las API `QueryEntitledProducts` devuelven los productos a los que el usuario tiene derecho. Tener derecho significa que el usuario posee directamente el producto, satisface el derecho a través de otros productos (como lotes y suscripciones) u obtiene el derecho mediante un derecho compartido de otro usuario.

Además, los resultados de [XStoreQueryAssociatedProductsAsync](/reference/system/xstore/xstore_members) (y funciones relacionadas) determinan el derecho. La estructura [XStoreProduct](/reference/system/xstore/xstore_members) contiene un campo `isInUserCollection` que se establece en true cuando el usuario tiene derecho.

### Propiedad de consumibles

La cantidad de consumibles se indica en `XStoreProduct.skus[i].collectionData.quantity`. Normalmente, solo hay una SKU para un producto consumible.

También puede usar [XStoreQueryConsumableBalanceRemainingAsync](/reference/system/xstore/xstore_members) para consultar la cantidad, pero evite usarlo individualmente para un gran número de consumibles, ya que cada llamada implica una llamada al servicio.

Para mantener la integridad de los ecosistemas basados en consumibles, use la validación y el canje de consumibles en el lado del servicio. Para obtener más información, consulte [Ecosistemas basados en consumibles](/publishing/xstore-commerce/xstore-consumables).

### Propiedad de duraderos

No basta con comprobar si la cuenta posee el producto para determinar que debería tener derecho a usar el producto dentro del juego. Los productos duraderos deben cumplir la directiva de uso compartido de contenido que se describe en [Modelo de uso compartido de productos para juegos](/publishing/xstore-commerce/xstore-product-sharing).

Use [XStoreAcquireLicenseForPackageAsync](/reference/system/xstore/xstore_members) para un **duradero con un paquete** a fin de determinar si se puede licenciar según las reglas de uso compartido de contenido.

Use [XStoreAcquireLicenseForDurablesAsync](/reference/system/xstore/xstore_members) para un **duradero sin un paquete** con el mismo fin.

Use [XStoreQueryAddOnLicensesAsync](/reference/system/xstore/xstore_members) para un juego con licencia **digital** a fin de devolver la lista de productos duraderos sin paquete que se pueden licenciar.

Para obtener más información, consulte [Administrar y licenciar contenido descargable](/publishing/xstore-commerce/xstore-dlc) y [Cómo usar un duradero sin un paquete](/publishing/xstore-commerce/xstore-dwob).

## 3. Comprar productos aptos

Para mostrar el flujo de compra de un producto que se puede comprar, pase el `storeId` a la API [XStoreShowPurchaseUIAsync](/reference/system/xstore/xstore_members):

```cpp theme={null}
void MakePurchase(const char* storeId)
{
    auto async = new XAsyncBlock{};
    async->context = &storeId;
    async->queue = m_asyncQueue;
    async->callback = [](XAsyncBlock *async)
    {
        const char* = reinterpret_cast<const char*>(async->context);

        HRESULT hr = XStoreShowPurchaseUIResult(async);
        if (SUCCEEDED(hr))
        {
            printf("Purchase succeeded (%s)\n", storeId);

            // Refresh ownership and update game
        }
        else
        {
            printf("Purchase failed (%s) 0x%x\n", storeId, hr);

            if (hr == E_GAMESTORE_ALREADY_PURCHASED)
            {
                printf("Already own this\n");
            }
        }

        delete async;
    };

    HRESULT hr = XStoreShowPurchaseUIAsync(
        m_xStoreContext,
        storeId,
        nullptr,    // Can be used to override the title bar text
        nullptr,    // Can be used to provide extra details to purchase
        async);

    if (FAILED(hr))
    {
        delete async;
        printf("Error calling XStoreShowPurchaseUIAsync : 0x%x\n", hr);
        return;
    }
}
```

Los jugadores también pueden realizar compras fuera del juego cambiando explícitamente a Microsoft Store, en Xbox.com, PC, aplicaciones móviles u otros puntos de venta. Por lo tanto, proporcione un lugar en su juego que actualice de forma confiable la propiedad de los productos a petición. El flujo inicial de inicio de sesión es un lugar perfecto, pero agregue también la actualización como parte de la transición a la tienda del juego o en algún lugar de la configuración.

## Documentación de referencia de la API

* [XStore (contenido de la API)](/reference/system/xstore/xstore_members)
  * Funciones
    * [XStoreCreateContext](/reference/system/xstore/xstore_members)
    * [XStoreQueryAssociatedProductsAsync](/reference/system/xstore/xstore_members)
    * [XStoreQueryProductsAsync](/reference/system/xstore/xstore_members)
    * [XStoreQueryAssociatedProductsForStoreIdAsync](/reference/system/xstore/xstore_members)
    * [XStoreQueryProductForCurrentGameAsync](/reference/system/xstore/xstore_members)
    * [XStoreShowAssociatedProductsUIAsync](/reference/system/xstore/xstore_members)
    * [XStoreQueryEntitledProductsAsync](/reference/system/xstore/xstore_members)
    * [XStoreQueryAssociatedProductsResult](/reference/system/xstore/xstore_members)
    * [XStoreQueryEntitledProductsResult](/reference/system/xstore/xstore_members)
    * [XStoreQueryConsumableBalanceRemainingAsync](/reference/system/xstore/xstore_members)
    * [XStoreAcquireLicenseForPackageAsync](/reference/system/xstore/xstore_members)
    * [XStoreAcquireLicenseForDurablesAsync](/reference/system/xstore/xstore_members)
    * [XStoreQueryAddOnLicensesAsync](/reference/system/xstore/xstore_members)
    * [XStoreShowPurchaseUIAsync](/reference/system/xstore/xstore_members)
  * Estructuras
    * [XStoreProduct](/reference/system/xstore/xstore_members)

## Consulte también

[Información general sobre comercio](/publishing/xstore-commerce/xstore-commerce-overview)

[Habilitación del desarrollo y las pruebas de XStore](/publishing/xstore-commerce/xstore-product-testing-setup)

[Referencia de la API de XStore](/reference/system/xstore/xstore_members)


## Related topics

- [XStoreQueryConsumableBalanceRemainingAsync](/es/reference/system/xstore/functions/xstorequeryconsumablebalanceremainingasync.md)
- [XStoreQueryAddOnLicensesAsync](/es/reference/system/xstore/functions/xstorequeryaddonlicensesasync.md)
- [XStoreQueryProductForCurrentGameAsync](/es/reference/system/xstore/functions/xstorequeryproductforcurrentgameasync.md)
- [XStoreQueryAssociatedProductsResult](/es/reference/system/xstore/functions/xstorequeryassociatedproductsresult.md)
- [XStoreCreateContext](/es/reference/system/xstore/functions/xstorecreatecontext.md)
