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

# 处理令牌过期

> 在 C SDK 中处理 PlayFab 实体令牌过期、后台令牌刷新和手动重新登录，包括 GDK 挂起和恢复流程。

PlayFab Services SDK 包含一个后台令牌刷新机制，帮助保持玩家会话的活动状态。理解此机制如何工作——以及游戏何时需要采取行动——非常重要，尤其是对支持挂起和恢复的游戏开发工具包（GDK）游戏而言。

## 自动令牌刷新如何工作

SDK 运行一个后台工作程序，定期检查玩家的实体令牌。如果令牌**仍然有效但即将过期**（在到期前一小时内），SDK 会使用原始登录调用的凭据自动重新进行身份验证。如果此刷新成功，令牌会被透明地更新，**PFEntityHandle** 继续有效。你的游戏无需采取任何行动。

你可以通过注册 [**PFEntityRegisterTokenRefreshedEventHandler**](/services/playfab/api-references/c/pfentity/functions/pfentityregistertokenrefreshedeventhandler) 回调来观察这些静默的令牌刷新（请参阅 [透明刷新](#transparent-refresh)）。

## 何时你的游戏必须处理令牌过期

在某些情况下，SDK **无法**自动刷新令牌：

* **令牌已经过期。** 自动刷新仅在令牌仍然有效时才有效。如果令牌完全过期——例如，在长时间挂起/恢复周期之后——SDK 不会尝试自动重新登录。相反，它会通过 **TokenExpiredHandler** 通知你的游戏。
* **原始登录凭据不再有效。** 如果最初提供给登录请求的句柄或令牌不再有效，自动刷新会失败并调用 **TokenExpiredHandler**。

<Info>
  建议所有游戏都注册 [**PFEntityTokenExpiredEventHandler**](/services/playfab/api-references/c/pfentity/functions/pfentitytokenexpiredeventhandler)，对于支持挂起和恢复的 GDK 游戏而言更是**必不可少**。没有此处理程序，你的游戏无法从过期的令牌中恢复。
</Info>

### 注册 TokenExpiredHandler

使用 [**PFEntityRegisterTokenExpiredEventHandler**](/services/playfab/api-references/c/pfentity/functions/pfentityregistertokenexpiredeventhandler) 注册回调，并使用 **PFAuthenticationReLoginWith\*Async** 在令牌过期时重新进行身份验证。

```cpp theme={null}
    PFRegistrationToken registrationTokenExpired{};
    hr = PFEntityRegisterTokenExpiredEventHandler(nullptr, nullptr, [](void* ctx, PFEntityKey const* entityKey)
    {
        PFAuthenticationLoginWithXUserRequest request{};
        request.createAccount = true;
        request.user = user; // An XUserHandle obtained from XUserAddAsync

        XAsyncBlock async{};
        HRESULT hr = PFAuthenticationReLoginWithXUserAsync(GlobalState()->entityHandle, &request, &async); // This assumes the entity handle was stored in the game's global state
        hr = XAsyncGetStatus(&async, true); // This is doing a blocking wait for completion, but you can use the XAsyncBlock to set a callback instead for async style usage

        // After login we could potentially get back a new player entity with a new entity key
        PFEntityKey const* pEntityKey{};
        std::vector<char> entityKeyBuffer;
        size_t size{};
        hr = PFEntityGetEntityKeySize(GlobalState()->entityHandle, &size); // Add your own error handling when FAILED(hr) == true

        entityKeyBuffer.resize(size);
        hr = PFEntityGetEntityKey(GlobalState()->entityHandle, entityKeyBuffer.size(), entityKeyBuffer.data(), &pEntityKey, nullptr);
    }, &registrationTokenExpired);
```

## GDK：挂起、恢复和 Quick Resume

在 GDK 平台上（XBOX 主机和带有 GDK 的 Windows），游戏可能被长时间挂起，例如当玩家切换到另一个游戏，稍后通过 Quick Resume 返回时。在挂起期间，实体令牌可能过期。由于挂起期间没有代码运行，SDK 的周期性后台刷新无法保持令牌存活。

### 恢复时会发生什么

当你的游戏恢复时，SDK 会**立即**检测到恢复状态并检查实体令牌。它不会等待下一个周期性刷新周期。如果令牌在挂起期间过期：

1. SDK 检测到过期的令牌。
2. 调用 **TokenExpiredHandler** 回调。
3. 你的游戏必须从该处理程序调用 **PFAuthenticationReLoginWith\*Async** 以获取新令牌。

<Note>
  恢复时的令牌检查在网络连接恢复后立即触发。如果恢复后网络需要一些时间重新初始化，SDK 会等待连接性再检查令牌。不会丢失任何令牌检查。
</Note>

## 透明刷新

如果你希望游戏在 SDK 自动刷新玩家实体令牌时得到通知，可以注册回调。当 SDK 成功刷新一个即将过期的令牌时，会调用此处理程序——你的游戏无需采取任何行动。

```cpp theme={null}
    PFRegistrationToken registrationTokenRefreshed{};
    hr = PFEntityRegisterTokenRefreshedEventHandler(nullptr, nullptr, [](void* ctx, PFEntityKey const* entityKey, const PFEntityToken* newToken)
    {
        // Perform any logging or other desired actions on token refresh
    }, &registrationTokenRefreshed);
```

## 取消注册处理程序

当关闭 PlayFab 或想停止接收令牌过期和刷新回调时，调用相应的取消注册函数。

```cpp theme={null}
    PFEntityUnregisterTokenExpiredEventHandler(registrationTokenExpired);
    PFEntityUnregisterTokenRefreshedEventHandler(registrationTokenRefreshed);
```

## 参考

[API 参考文档](/services/playfab/api-references/c/pfauthentication/pfauthentication_members)
