> ## 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.

# Identificadores de entidad

> Administre las credenciales de PFEntityHandle, el recuento de referencias y la duración del token de entidad para las llamadas autenticadas de jugador y título en el SDK de C de PlayFab.

Un **PFEntityHandle** es su credencial principal para realizar llamadas al servicio de PlayFab. Representa una entidad autenticada, ya sea un jugador (title\_player\_account) o un título, y contiene el token de entidad que el SDK necesita para autorizar las solicitudes. Cada llamada de inicio de sesión o autenticación devuelve un **PFEntityHandle**, y cada llamada al servicio requiere uno.

## Obtención de un identificador de entidad

Los identificadores de entidad no se crean directamente. En su lugar, se obtiene uno como salida de una llamada de inicio de sesión o autenticación correcta.

**Inicio de sesión del jugador (ejemplo de Windows):**

```cpp theme={null}
PFAuthenticationLoginWithXUserRequest request{};
request.createAccount = true;
request.user = userHandle; // XUserHandle from XUserAddAsync

XAsyncBlock async{};
HRESULT hr = PFAuthenticationLoginWithXUserAsync(serviceConfigHandle, &request, &async);
hr = XAsyncGetStatus(&async, true);

PFEntityHandle entityHandle{ nullptr };
size_t bufferSize{};
hr = PFAuthenticationLoginWithXUserGetResultSize(&async, &bufferSize);

std::vector<char> loginResultBuffer(bufferSize);
PFAuthenticationLoginResult const* loginResult{};
hr = PFAuthenticationLoginWithXUserGetResult(
    &async, &entityHandle,
    loginResultBuffer.size(), loginResultBuffer.data(),
    &loginResult, nullptr);
```

**Entidad de título (servidor):**

Las entidades de título se autentican con una clave secreta en lugar de una credencial de usuario. El **PFEntityHandle** devuelto funciona de la misma manera, pero representa el título en lugar de un jugador. Consulte [Acceso a PlayFab con una entidad de título](/services/playfab/sdks/c/server) para obtener más detalles.

## Propiedad del identificador y recuento de referencias

**PFEntityHandle** usa recuento de referencias. Cuando recibe un identificador de una llamada de inicio de sesión, posee una referencia. Puede crear referencias adicionales con [**PFEntityDuplicateHandle**](/services/playfab/api-references/c/pfentity/functions/pfentityduplicatehandle) y liberarlas con [**PFEntityCloseHandle**](/services/playfab/api-references/c/pfentity/functions/pfentityclosehandle). El objeto de entidad subyacente solo se destruye cuando se cierra la última referencia.

**Reglas:**

* Cada llamada a una función `GetResult` de inicio de sesión o a **PFEntityDuplicateHandle** le proporciona un identificador que debe cerrar.
* Cerrar un identificador no invalida otros identificadores de la misma entidad.
* Cierre todos los identificadores antes de llamar a [**PFServicesUninitializeAsync**](/services/playfab/api-references/c/pfservices/functions/pfservicesuninitializeasync).

```cpp theme={null}
// Duplicate a handle for another component
PFEntityHandle secondHandle{ nullptr };
HRESULT hr = PFEntityDuplicateHandle(entityHandle, &secondHandle);

// Both handles are independently valid
// ...

// Each owner closes their own handle
PFEntityCloseHandle(secondHandle);
PFEntityCloseHandle(entityHandle);
```

## Obtención de información de la entidad

### Clave de entidad

La clave de entidad identifica la entidad (su tipo e identificador). Use el patrón de dos llamadas: obtenga primero el tamaño y, después, los datos.

```cpp theme={null}
size_t size{};
HRESULT hr = PFEntityGetEntityKeySize(entityHandle, &size);

std::vector<char> buffer(size);
PFEntityKey const* entityKey{};
hr = PFEntityGetEntityKey(entityHandle, buffer.size(), buffer.data(), &entityKey, nullptr);

// entityKey->type is "title_player_account" for players
// entityKey->id is the entity's unique ID
```

### Token de entidad

El token de entidad autoriza las llamadas al servicio. El SDK administra los tokens automáticamente, pero puede recuperar el actual si es necesario.

```cpp theme={null}
XAsyncBlock async{};
HRESULT hr = PFEntityGetEntityTokenAsync(entityHandle, &async);
hr = XAsyncGetStatus(&async, true);

size_t size{};
hr = PFEntityGetEntityTokenResultSize(&async, &size);

std::vector<char> buffer(size);
const PFEntityToken* entityToken{};
hr = PFEntityGetEntityTokenResult(&async, buffer.size(), buffer.data(), &entityToken, nullptr);

// entityToken->token is the token string
// entityToken->expiration is the optional expiration time (UTC)
```

### Comprobación del tipo de entidad

Use [**PFEntityIsTitlePlayer**](/services/playfab/api-references/c/pfentity/functions/pfentityistitleplayer) como comprobación rápida en lugar de inspeccionar la cadena de tipo de la clave de entidad:

```cpp theme={null}
bool isTitlePlayer{};
HRESULT hr = PFEntityIsTitlePlayer(entityHandle, &isTitlePlayer);
```

## Entidades de jugador frente a entidades de título

Tanto las entidades de jugador como las de título usan **PFEntityHandle**, pero difieren en lo que pueden hacer:

|                                                                                                          | Entidad de jugador                                                               | Entidad de título                             |
| -------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | --------------------------------------------- |
| **Cómo se obtiene**                                                                                      | Llamada de inicio de sesión (por ejemplo, `PFAuthenticationLoginWithXUserAsync`) | `PFAuthenticationGetEntityWithSecretKeyAsync` |
| **Tipo de entidad**                                                                                      | `title_player_account`                                                           | `title`                                       |
| [**PFEntityIsTitlePlayer**](/services/playfab/api-references/c/pfentity/functions/pfentityistitleplayer) | Devuelve `true`                                                                  | Devuelve `false`                              |
| [**PFEntityGetSecretKey**](/services/playfab/api-references/c/pfentity/functions/pfentitygetsecretkey)   | Produce un error con `E_PF_NOSECRETKEY`                                          | Devuelve la clave secreta                     |
| **API disponibles**                                                                                      | API con el prefijo Client y sin prefijo                                          | API con el prefijo Server y sin prefijo       |

Las API sin prefijo (por ejemplo, Inventory, Leaderboards, Data) generalmente pueden llamarlas tanto las entidades de jugador como las de título, a menos que se indique lo contrario en su documentación. Las API con el prefijo Client son solo para jugadores y las API con el prefijo Server son solo para títulos.

**PFEntityGetSecretKey** recupera la clave secreta asociada a una entidad de título. Produce un error en las entidades de jugador porque estas no tienen una.

```cpp theme={null}
size_t keySize{};
HRESULT hr = PFEntityGetSecretKeySize(entityHandle, &keySize);
if (SUCCEEDED(hr))
{
    std::vector<char> secretKey(keySize);
    hr = PFEntityGetSecretKey(entityHandle, secretKey.size(), secretKey.data(), nullptr);
}
```

<Note>
  **PFEntityGetSecretKey** solo está disponible en las plataformas Windows, Linux y macOS.
</Note>

## Controladores de eventos de token

El SDK actualiza automáticamente los tokens de entidad antes de que expiren. Puede registrar devoluciones de llamada para observar estos eventos.

### Token expirado

Si la actualización automática produce un error (por ejemplo, la credencial de inicio de sesión original ya no es válida), el SDK desencadena el evento de token expirado. Registre un controlador para proporcionar una nueva credencial y reintentar el inicio de sesión.

```cpp theme={null}
PFRegistrationToken registrationToken{};
HRESULT hr = PFEntityRegisterTokenExpiredEventHandler(
    nullptr,  // XTaskQueueHandle, or nullptr for default
    nullptr,  // optional context
    [](void* ctx, PFEntityKey const* entityKey)
    {
        // Re-authenticate the player with a fresh credential
        // See relogin.md for a complete example
    },
    &registrationToken);
```

### Token actualizado

Registre un controlador de token actualizado si quiere saber cuándo el SDK actualiza correctamente un token en segundo plano. Es informativo: no es necesario realizar ninguna acción.

```cpp theme={null}
PFRegistrationToken registrationToken{};
HRESULT hr = PFEntityRegisterTokenRefreshedEventHandler(
    nullptr,  // XTaskQueueHandle, or nullptr for default
    nullptr,  // optional context
    [](void* ctx, PFEntityKey const* entityKey, const PFEntityToken* newToken)
    {
        // Log the refresh or update cached token references
    },
    &registrationToken);
```

### Cuándo registrar y anular el registro

* **Registre** los controladores pronto, justo después de la inicialización del SDK y antes del inicio de sesión. Esto garantiza que no se pierda ningún evento.
* **Anule el registro** de los controladores durante el cierre, antes de cerrar los identificadores de entidad.

```cpp theme={null}
PFEntityUnregisterTokenExpiredEventHandler(expiredRegistrationToken);
PFEntityUnregisterTokenRefreshedEventHandler(refreshedRegistrationToken);
```

Para obtener un tutorial completo sobre el control de la expiración de tokens y el reinicio de sesión, consulte [Control de la expiración de tokens](/services/playfab/sdks/c/relogin).

## Descriptores de acceso de utilidad

Puede recuperar el punto de conexión de la API y el identificador del título a partir de un identificador de entidad. Estos proceden del **PFServiceConfigHandle** que se usó durante el inicio de sesión.

```cpp theme={null}
// Get API endpoint
size_t endpointSize{};
HRESULT hr = PFEntityGetAPIEndpointSize(entityHandle, &endpointSize);

std::vector<char> endpoint(endpointSize);
hr = PFEntityGetAPIEndpoint(entityHandle, endpoint.size(), endpoint.data(), nullptr);

// Get title ID
size_t titleIdSize{};
hr = PFEntityGetTitleIdSize(entityHandle, &titleIdSize);

std::vector<char> titleId(titleIdSize);
hr = PFEntityGetTitleId(entityHandle, titleId.size(), titleId.data(), nullptr);
```

## Ejemplo completo

En este ejemplo se muestra cómo crear, duplicar, consultar y cerrar identificadores de entidad:

```cpp theme={null}
#include <playfab/core/PFEntity.h>
#include <playfab/services/PFServices.h>

void EntityHandleExample(PFServiceConfigHandle serviceConfigHandle, XUserHandle userHandle)
{
    //
    // Log in and get an entity handle
    //
    PFAuthenticationLoginWithXUserRequest request{};
    request.createAccount = true;
    request.user = userHandle;

    XAsyncBlock asyncLogin{};
    HRESULT hr = PFAuthenticationLoginWithXUserAsync(serviceConfigHandle, &request, &asyncLogin);
    hr = XAsyncGetStatus(&asyncLogin, true);

    PFEntityHandle entityHandle{ nullptr };
    size_t resultSize{};
    hr = PFAuthenticationLoginWithXUserGetResultSize(&asyncLogin, &resultSize);

    std::vector<char> loginBuffer(resultSize);
    PFAuthenticationLoginResult const* loginResult{};
    hr = PFAuthenticationLoginWithXUserGetResult(
        &asyncLogin, &entityHandle,
        loginBuffer.size(), loginBuffer.data(),
        &loginResult, nullptr);

    //
    // Register token event handlers
    //
    PFRegistrationToken expiredToken{};
    hr = PFEntityRegisterTokenExpiredEventHandler(nullptr, nullptr,
        [](void* ctx, PFEntityKey const* entityKey)
        {
            // Handle re-authentication
        }, &expiredToken);

    PFRegistrationToken refreshedToken{};
    hr = PFEntityRegisterTokenRefreshedEventHandler(nullptr, nullptr,
        [](void* ctx, PFEntityKey const* entityKey, const PFEntityToken* newToken)
        {
            // Log token refresh
        }, &refreshedToken);

    //
    // Duplicate the handle for a subsystem
    //
    PFEntityHandle subsystemHandle{ nullptr };
    hr = PFEntityDuplicateHandle(entityHandle, &subsystemHandle);

    //
    // Query entity info
    //
    bool isTitlePlayer{};
    hr = PFEntityIsTitlePlayer(entityHandle, &isTitlePlayer);

    size_t keySize{};
    hr = PFEntityGetEntityKeySize(entityHandle, &keySize);

    std::vector<char> keyBuffer(keySize);
    PFEntityKey const* entityKey{};
    hr = PFEntityGetEntityKey(entityHandle, keyBuffer.size(), keyBuffer.data(), &entityKey, nullptr);

    //
    // ... make service calls with entityHandle or subsystemHandle ...
    //

    //
    // Cleanup: unregister handlers, then close all handles
    //
    PFEntityUnregisterTokenExpiredEventHandler(expiredToken);
    PFEntityUnregisterTokenRefreshedEventHandler(refreshedToken);

    PFEntityCloseHandle(subsystemHandle);
    PFEntityCloseHandle(entityHandle);
}
```

## Referencia de API

| Función                                                                                                                                            | Descripción                                                                                                                      |
| -------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| [PFEntityDuplicateHandle](/services/playfab/api-references/c/pfentity/functions/pfentityduplicatehandle)                                           | Duplica un identificador e incrementa el recuento de referencias. Ambos identificadores deben cerrarse de forma independiente.   |
| [PFEntityCloseHandle](/services/playfab/api-references/c/pfentity/functions/pfentityclosehandle)                                                   | Cierra un identificador y disminuye el recuento de referencias. La entidad se destruye cuando se cierra el último identificador. |
| [PFEntityGetEntityKeySize](/services/playfab/api-references/c/pfentity/functions/pfentitygetentitykeysize)                                         | Obtiene el tamaño de búfer necesario para almacenar la clave de entidad.                                                         |
| [PFEntityGetEntityKey](/services/playfab/api-references/c/pfentity/functions/pfentitygetentitykey)                                                 | Obtiene la clave de entidad (tipo e identificador) de la entidad.                                                                |
| [PFEntityGetEntityTokenAsync](/services/playfab/api-references/c/pfentity/functions/pfentitygetentitytokenasync)                                   | Recupera de forma asincrónica el token de entidad almacenado en caché.                                                           |
| [PFEntityGetEntityTokenResultSize](/services/playfab/api-references/c/pfentity/functions/pfentitygetentitytokenresultsize)                         | Obtiene el tamaño de búfer necesario para el resultado del token de entidad.                                                     |
| [PFEntityGetEntityTokenResult](/services/playfab/api-references/c/pfentity/functions/pfentitygetentitytokenresult)                                 | Obtiene el token de entidad de una llamada completada a PFEntityGetEntityTokenAsync.                                             |
| [PFEntityIsTitlePlayer](/services/playfab/api-references/c/pfentity/functions/pfentityistitleplayer)                                               | Devuelve si la entidad es una title\_player\_account.                                                                            |
| [PFEntityGetSecretKeySize](/services/playfab/api-references/c/pfentity/functions/pfentitygetsecretkeysize)                                         | Obtiene el tamaño de búfer necesario para la clave secreta. Produce un error si la entidad no es una entidad de título.          |
| [PFEntityGetSecretKey](/services/playfab/api-references/c/pfentity/functions/pfentitygetsecretkey)                                                 | Obtiene la clave secreta de una entidad de título. Solo está disponible en Windows, Linux y macOS.                               |
| [PFEntityGetAPIEndpointSize](/services/playfab/api-references/c/pfentity/functions/pfentitygetapiendpointsize)                                     | Obtiene el tamaño de búfer necesario para la cadena del punto de conexión de la API.                                             |
| [PFEntityGetAPIEndpoint](/services/playfab/api-references/c/pfentity/functions/pfentitygetapiendpoint)                                             | Obtiene el punto de conexión de la API a partir de la configuración de servicio asociada a la entidad.                           |
| **PFEntityGetTitleIdSize**                                                                                                                         | Obtiene el tamaño de búfer necesario para la cadena del identificador del título.                                                |
| **PFEntityGetTitleId**                                                                                                                             | Obtiene el identificador del título a partir de la configuración de servicio asociada a la entidad.                              |
| [PFEntityRegisterTokenExpiredEventHandler](/services/playfab/api-references/c/pfentity/functions/pfentityregistertokenexpiredeventhandler)         | Registra una devolución de llamada para cuando la actualización automática del token produce un error.                           |
| [PFEntityUnregisterTokenExpiredEventHandler](/services/playfab/api-references/c/pfentity/functions/pfentityunregistertokenexpiredeventhandler)     | Anula el registro de una devolución de llamada de token expirado.                                                                |
| [PFEntityRegisterTokenRefreshedEventHandler](/services/playfab/api-references/c/pfentity/functions/pfentityregistertokenrefreshedeventhandler)     | Registra una devolución de llamada para cuando el SDK actualiza correctamente un token.                                          |
| [PFEntityUnregisterTokenRefreshedEventHandler](/services/playfab/api-references/c/pfentity/functions/pfentityunregistertokenrefreshedeventhandler) | Anula el registro de una devolución de llamada de token actualizado.                                                             |

Para obtener la referencia de API completa, consulte [Miembros de PFEntity](/services/playfab/api-references/c/pfentity/pfentity_members).

## Consulte también

* [Control de la expiración de tokens](/services/playfab/sdks/c/relogin)
* [Acceso a PlayFab con una entidad de título](/services/playfab/sdks/c/server)
* [Ciclo de vida del SDK](/services/playfab/sdks/c/lifecycle)
* [Inicio rápido: Windows](/services/playfab/sdks/c/quickstart-gdk)
* [Inicio rápido: Win32](/services/playfab/sdks/c/quickstart-win32)
