# Authorization

这份文档只讲授权验证。

目标：

- 游戏侧只配 `IGPConfig.appId`
- 从 desktop 启动游戏时自动完成授权
- 游戏自己启动时自动连 desktop，必要时自动拉起，再完成授权
- 授权失败时 SDK 给出统一失败状态
- 游戏方可以自己接管失败提示和后续处理

## 1. 你需要做什么

正常接入只做一件事：

- 在 `IGPConfig` 里填 `appId`

不要再额外手填授权票据、公钥或离线许可参数。

## 2. 启动时会怎么走

### 路径 A：desktop 启动游戏

1. desktop 启动游戏
2. SDK 读取本次授权管道
3. SDK 自动完成授权
4. 授权通过后再继续后面的房间和联机链路

### 路径 B：游戏自己启动

1. SDK 先尝试附着 desktop
2. 如果 desktop 没开，SDK 会按配置自动拉起 desktop
3. 连上后，SDK 向 desktop 请求本次授权
4. SDK 自动完成授权
5. 授权通过后再继续后面的房间和联机链路

如果当前游戏不要求授权，SDK 会直接跳过这一步。

## 3. 运行时能看到什么状态

`IGPRuntimeManager` 现在会对外暴露这些状态：

- `IsAuthorized`
- `AuthorizationState`
- `IsAuthorizationRequired`
- `LastAuthorizationFailure`

授权状态有这几种：

- `Pending`
- `AuthorizedOnline`
- `AuthorizedOffline`
- `Failed`
- `Skipped`

## 4. 失败时怎么处理

授权失败时，SDK 会同时做这几件事：

- 把状态标成失败
- 记录最近一次失败原因
- 触发 `onAuthorizationFailed`
- 同时触发 `onError`
- 默认显示一个 SDK 自带的保底提示层

SDK 不会直接替你关游戏。

如果你什么都不接，玩家至少也能看到这个默认提示层。

## 5. 游戏方怎么接管失败提示

如果你要自己做提示、遮罩、跳转或退出，直接监听事件即可：

如果你不想用 SDK 自带的保底提示层，可以在运行时关掉：

```csharp
runtimeManager.ShowAuthorizationFailureFallback = false;
```

如果你想先沿用 SDK 的默认展示，但把文案换成自己游戏里的说法，也可以直接改：

```csharp
runtimeManager.AuthorizationFailureFallbackTitle = "Unable to start the game";
runtimeManager.AuthorizationFailureFallbackMessage = "We could not confirm your access right now.";
runtimeManager.AuthorizationFailureFallbackHint = "Open IGP Desktop, sign in again, and retry.";
runtimeManager.AuthorizationFailureFallbackButtonText = "Close";
```

```csharp
using UnityEngine;
using IGP.UnitySDK;

public sealed class AuthorizationGate : MonoBehaviour
{
    [SerializeField] private IGPRuntimeManager runtimeManager;

    private void Awake()
    {
        runtimeManager ??= FindObjectOfType<IGPRuntimeManager>();
    }

    private void OnEnable()
    {
        if (runtimeManager == null)
        {
            return;
        }

        runtimeManager.onAuthorizationFailed.AddListener(HandleAuthorizationFailed);
        runtimeManager.onAuthorizationStateChanged.AddListener(HandleAuthorizationStateChanged);
    }

    private void OnDisable()
    {
        if (runtimeManager == null)
        {
            return;
        }

        runtimeManager.onAuthorizationFailed.RemoveListener(HandleAuthorizationFailed);
        runtimeManager.onAuthorizationStateChanged.RemoveListener(HandleAuthorizationStateChanged);
    }

    private void HandleAuthorizationFailed(string message)
    {
        Debug.LogError($"Authorization failed: {message}");
        runtimeManager.ShowAuthorizationFailureFallback = false;
        // 在这里接你的 UI、遮罩、跳转或退出逻辑
    }

    private void HandleAuthorizationStateChanged(IGPAuthorizationState state)
    {
        Debug.Log($"Authorization state: {state}");
    }
}
```

## 6. 离线模式怎么理解

如果在线授权暂时不可用，但本地已经有有效的离线许可，SDK 会进入：

- `AuthorizedOffline`

如果本地离线许可无效、过期、被篡改，或者和当前游戏 / 当前设备不匹配，SDK 会直接失败。

## 7. 排查顺序

如果授权没过，优先看这些：

1. `IGPConfig.appId` 是否正确
2. 当前游戏是否真的已经在 desktop 安装库里
3. desktop 是否已登录
4. 游戏是不是通过正确的可执行文件路径附着到 desktop
5. `LastAuthorizationFailure` 和 `onError` 里拿到的具体错误
