# Apple

> Provide an Apple sign-in option to enable players to authenticate using their Apple accounts on iOS and macOS.

###### SDK 最低版本：2.0.0##minimum-sdk-version-200

本文将引导您完成以下场景，为您游戏中使用 Apple 帐户的玩家设置身份验证：

* 设置 Apple 登录。
* 回归用户登录或创建新用户。
* 将用户从匿名登录更新为通过 Apple 帐户进行平台登录。

> **Warning:**
>
> **重要**：在 Unity Authentication SDK 中通过 Apple 支持进行登录这种方式，只适用于具有 iOS 平台 ID 令牌的单一 Bundle ID。它不支持玩家通过 Service ID 进行 Apple 登录，也不支持通过 Android 平台授权码登录。

要为您的游戏玩家提供 Apple 登录选项，请对您的应用进行设置以启用 Apple 登录。

> **Note:**
>
> **注意**：下方代码示例的前提为，您已经有玩家的 Apple ID 令牌。

## 设置 Apple 登录##set-up-an-apple-sign-in

1. 设置您的应用以[启用 Apple 登录](https://developer.apple.com/help/account/)。**注意**：Unity Authentication 仅支持基于 **Bundle ID** 的登录，不支持 Service ID。
2. 将 Unity Authentication 中的 ID 提供商设置为 Apple：
   1. 在 Unity 编辑器菜单中，访问 **Edit（编辑）**> **Project Settings…（项目设置…）**，然后从导航菜单中选择 **Services（服务）**> **Authentication（身份验证）**。
   2. 将 **ID Providers（ID 提供商）** 设置为 **Sign-in with Apple（通过 Apple 登录）**，然后选择 **Add（添加）**。
   3. 在 Apple 开发者控制台中找到 **Bundle ID**，输入到 **App ID** 文本字段中，然后选择 **Save（保存）**。Bundle ID 示例：**com.something.somethingelse**。
3. 要在您的 Unity 项目中集成 Apple 登录功能，我们建议您利用 Unity Asset Store 中的 SDK 库软件包，例如 [Sign in with Apple Unity Plugin（通过 Apple Unity 插件登录）](https://assetstore.unity.com/packages/tools/integration/sign-in-with-apple-unity-plugin-152088)。
   1. 要安装软件包，请遵照软件包文件中给出的[步骤](https://github.com/lupidan/apple-signin-unity#perform-sign-in-with-apple)。
   2. 注意：参考的软件包并非由 Unity 开发、拥有或运营。请参考关于使用非 Unity 软件包的最佳实践。
   3. 以下代码片段展示了如何在您的 Unity 项目中利用该软件包示例启用 Apple 登录。

```cs
using System.Text;
using UnityEngine;

// External dependencies
using AppleAuth;
using AppleAuth.Enums;
using AppleAuth.Interfaces;
using AppleAuth.Native;

public class AppleExampleScript : MonoBehaviour
{
    IAppleAuthManager m_AppleAuthManager;
    public string Token { get; private set; }
    public string Error { get; private set; }

    public void Initialize()
    {
        var deserializer = new PayloadDeserializer();
        m_AppleAuthManager = new AppleAuthManager(deserializer);
    }

   public void Update()
   {
      if (m_AppleAuthManager != null) 
      {
         m_AppleAuthManager.Update();
      }
   }

    public void LoginToApple()
    {
        // Initialize the Apple Auth Manager
        if (m_AppleAuthManager == null)
        {
            Initialize();
        }

        // Set the login arguments
        var loginArgs = new AppleAuthLoginArgs(LoginOptions.IncludeEmail | LoginOptions.IncludeFullName);

        // Perform the login
        m_AppleAuthManager.LoginWithAppleId(
            loginArgs,
            credential =>
            {
                var appleIDCredential = credential as IAppleIDCredential;
                if (appleIDCredential != null)
                {
                    var idToken = Encoding.UTF8.GetString(
                        appleIDCredential.IdentityToken,
                        0,
                        appleIDCredential.IdentityToken.Length);
                    Debug.Log("Sign-in with Apple successfully done. IDToken: " + idToken);
                    Token = idToken;
                }
                else
                {
                    Debug.Log("Sign-in with Apple error. Message: appleIDCredential is null");
                    Error = "Retrieving Apple Id Token failed.";
                }
            },
            error =>
            {
                Debug.Log("Sign-in with Apple error. Message: " + error);
                Error = "Retrieving Apple Id Token failed.";
            }
        );
    }
}
```

## 回归玩家登录或创建新玩家##sign-in-a-returning-player-or-create-new-player

您可以使用 `SignInWithAppleAsync` 方法执行以下操作之一：

* 通过 Apple 凭据创建新的 Unity Authentication 玩家帐户。
* 通过 Apple 凭据登录现有玩家帐户。

如果您的项目中没有与凭据关联的 Unity Authentication 玩家帐户，`SignInWithAppleAsync` 将创建新的玩家帐户。如果您的项目中具有与凭据关联的 Unity Authentication 玩家帐户，`SignInWithAppleAsync` 将登录该玩家帐户。该功能不考虑缓存的玩家帐户，`SignInWithAppleAsync` 会替换缓存的玩家帐户。

```cs
async Task SignInWithAppleAsync(string idToken)
{
    try
    {
        await AuthenticationService.Instance.SignInWithAppleAsync(idToken);
        Debug.Log("SignIn is successful.");
    }
    catch (AuthenticationException ex)
    {
        // Compare error code to AuthenticationErrorCodes
        // Notify the player with the proper error message
        Debug.LogException(ex);
    }
    catch (RequestFailedException ex)
    {
        // Compare error code to CommonErrorCodes
        // Notify the player with the proper error message
        Debug.LogException(ex);
    }
}
```

## 将玩家帐户从匿名更新为 Apple 帐户##update-a-player-from-anonymous-to-an-apple-account

在您设置完匿名身份验证后，如果匿名玩家想升级为 Apple 帐户，并通过 Apple 登录，您应在游戏中引导玩家触发 Apple 登录并从 Apple 获取 ID 令牌。然后，调用 `LinkWithAppleAsync` API，将玩家帐户与 Apple ID 令牌关联。

如果 SDK 上有缓存的玩家帐户，您可以将缓存的玩家帐户与 Apple 帐户关联。

1. 通过 `SignInAnonymouslyAsync` 登录缓存玩家的帐户。
2. 通过 `LinkWithAppleAsync` 将缓存的玩家帐户与 Apple 帐户关联。

```cs
async Task LinkWithAppleAsync(string idToken)
{
    try
    {
        await AuthenticationService.Instance.LinkWithAppleAsync(idToken);
        Debug.Log("Link is successful.");
    }
    catch (AuthenticationException ex) when (ex.ErrorCode == AuthenticationErrorCodes.AccountAlreadyLinked)
    {
        // Prompt the player with an error message.
        Debug.LogError("This user is already linked with another account. Log in instead.");
    }
    catch (AuthenticationException ex)
    {
        // Compare error code to AuthenticationErrorCodes
        // Notify the player with the proper error message
        Debug.LogException(ex);
    }
    catch (RequestFailedException ex)
    {
        // Compare error code to CommonErrorCodes
        // Notify the player with the proper error message
        Debug.LogException(ex);
    }
}
```

如果玩家通过登录或创建新玩家配置文件而触发 Apple 登录，并且您已收到 Apple ID 令牌，调用以下 API 来对玩家进行身份验证。

```cs
async Task SignInWithAppleAsync(string idToken)
{
    try
    {
        await AuthenticationService.Instance.SignInWithAppleAsync(idToken);
        Debug.Log("SignIn is successful.");
    }
    catch (AuthenticationException ex)
    {
        // Compare error code to AuthenticationErrorCodes
        // Notify the player with the proper error message
        Debug.LogException(ex);
    }
    catch (RequestFailedException ex)
    {
        // Compare error code to CommonErrorCodes
        // Notify the player with the proper error message
        Debug.LogException(ex);
    }
}
```

## 实现 Apple 登录身份验证##unlink-apple-account

如果玩家通过登录或创建新玩家配置文件而触发 Apple 登录，并且您已收到 Apple ID 令牌，调用以下 API 来对玩家进行身份验证：`SignInWithAppleAsync(string idToken).`

## 取消 Apple 帐户关联

使用 `UnlinkAppleAsync` API 可以取消玩家帐户与其 Apple 帐户的关联。一旦取消关联，如果玩家帐户不再关联到任何其他身份，则会转换为匿名帐户。

```cs
async Task UnlinkAppleAsync(string idToken)
{
   try
   {
       await AuthenticationService.Instance.UnlinkAppleAsync(idToken);
       Debug.Log("Unlink is successful.");
   }
   catch (AuthenticationException ex)
   {
       // Compare error code to AuthenticationErrorCodes
       // Notify the player with the proper error message
       Debug.LogException(ex);
   }
   catch (RequestFailedException ex)
   {
       // Compare error code to CommonErrorCodes
       // Notify the player with the proper error message
       Debug.LogException(ex);
   }
}
```
