iOS
本文旨在介绍如何设置 Discord 身份验证,让您的游戏可以使用 Player Network 登录鉴权服务通过 Discord 渠道登录。
从 2024 年春季开始,对于需更新或上传至 Apple App Store Connect 的应用,开发者需明确 注明使用原因,以展示该应用如何使用 required reason API(需提交使用原因的 API)。更多信息,请参见 即将发布的第三方 SDK 要求。
由于 Discord 的隐私清单尚未公布,目前 Player Network SDK 隐私清单中不包含对应的内容,详见 iOS 17 隐私清单。
前提条件
1. 在 Discord 开发者平台上配置应用
1.1 创建应用
- 在 Discord 官网注册并认证账号
- 进入 开发者平台,点击 New Application

- 输入应用名称,点击 Create
- 在 General Information 页面获取 APPLICATION ID

- 在 INTLConfig.ini 中配置 Discord App ID
1.2 申请 SDK 访问权限
1.3 配置 OAuth2
- 点击 OAuth2,打开 PUBLIC CLIENT 开关

- 配置 Redirects:
- Android/iOS:
discord-{YOUR_APP_ID}:/authorize/callback - PC:
http://127.0.0.1/callback - Web:
https://common-web.intlgame.com/jssdk/discordlogincallback.html、https://test-common-web.intlgame.com/jssdk/discordlogincallback.html
- Android/iOS:

对于多商店渠道包:
支持多商店渠道包需要单独的 REDIRECT_URL_SCHEME。一个 App ID 支持10个重定向 URL(约4个多商店渠道包)。如果游戏需要多于4个多商店渠道包,请申请更多 App ID。要使用多个应用程序 ID,游戏需要 在 INTLConfig.ini 中配置多个应用程序 ID 和 在 Player Network 上注册多个 Discord 应用程序。
移动端如果需要跳转回游戏的功能,则需配置 DeepLink:在 General Information → Deep Link URL 添加跳转 URL

1.4 配置 Rich Presence 资源
- 点击 Rich Presence
- 点击 Add Image(s) 上传图片资源

- 获取 Player Network 控制台登录账号。
- 为游戏创建新项目,或加入已有项目。
- 下载 SDK。
- 接入 SDK。
- 在 Player Network 控制台添加 Discord 为业务的登录鉴权方式。
步骤1:为 Discord 登录配置 SDK
Discord SDK 仅与 iOS 12.0 及更高版本兼容。
Unreal Engine 应首先在 Plugins/INTLSDK/Source/INTLCore/INTLCore.Build.cs 文件中找到捆绑资源路径:
AdditionalBundleResources.Add(new BundleResource(Path.Combine(ModuleDirectory, "Libs/iOS/INTLCore/INTLSDK.bundle"), bShouldLog: false));
1. 加载所需的权限和插件
- Unity
- Unreal Engine
打开 INTLDiscordKit.projmods 文件,并将 {INTL_DISCORD_APP_ID} 替换为游戏的 App ID。
"Info.plist":{
"LSApplicationQueriesSchemes":
[
"discord"
],
"NSAppTransportSecurity":
{
"NSAllowsArbitraryLoads":true
},
"CFBundleURLTypes" :
[
{
"CFBundleTypeRole":"Editor",
"CFBundleURLName":"Discord",
"CFBundleURLSchemes":["discord-{INTL_DISCORD_APP_ID}"]
}
]
}
- SDK 1.24 及之后版本
- SDK 1.24 之前版本
打开 INTLSDK/Source/INTLDiscord/Libs/iOS/INTLDiscord_UPL.xml 文件,并将 {INTL_DISCORD_APP_ID} 替换为游戏的 App ID。
<dict>
<key>CFBundleURLName</key>
<string>Discord</string>
<key>CFBundleURLSchemes</key>
<array>
<string>discord-{INTL_DISCORD_APP_ID}</string>
</array>
</dict>
打开 INTLSDK/Source/INTLConfig/Configs/iOS/Plist/INTLDiscord.plist 文件,并将 {INTL_DISCORD_APP_ID} 替换为游戏的 App ID。
<dict>
<key>CFBundleURLName</key>
<string>Discord</string>
<key>CFBundleURLSchemes</key>
<array>
<string>discord-{INTL_DISCORD_APP_ID}</string>
</array>
</dict>
iOS 使用说明
根据 iOS 权限要求,在申请敏感权限时,填写 使用说明,系统会弹出提示用户填写此信息。
- Unity
- Unreal Engine
-
在
Assets/INTLSDK/Editor/XUPorter/Mods~/INTLCoreKit.projmods,下列权限已升级:"NSPhotoLibraryUsageDescription"
"NSCameraUsageDescription"
"NSLocationWhenInUseUsageDescription"
"NSPhotoLibraryAddUsageDescription"
"NSMicrophoneUsageDescription"在接入时,用户可以根据需要修改内容。
-
在
Assets/INTLSDK/Editor/XUPorter/Mods~/INTLADTrackingKit.projmods,下列权限已升级:"NSUserTrackingUsageDescription"caution接入时,用户可以根据需要修改内容,并与法律团队确认内容是否合规。如果无修改, 将 INTLSample 替换为游戏名称。
-
在
Plugins/INTLSDK/Source/INTLConfig/Configs/iOS/Plist/INTLCore.plist中,下列权限已升级:<key>NSPhotoLibraryUsageDescription</key>
<key>NSCameraUsageDescription</key>
<key>NSLocationWhenInUseUsageDescription</key>
<key>NSPhotoLibraryAddUsageDescription</key>
<key>NSMicrophoneUsageDescription</key> -
在
Plugins/INTLSDK/Source/INTLConfig/Configs/iOS/Plist/INTLADTracking.plist中,下列权限已升级:<key>NSUserTrackingUsageDescription</key>caution接入时,用户可以根据需要修改内容,并与法律团队确认内容是否合规。如果无修改, 将 INTLSample 替换为游戏名称。
2. Swift SDK 适配器
如果模块使用到的是 Swift 版本的 SDK,这里会涉及到 iOS 的 Swift 和 Objective-C 的混编问题。 Xcode 为了兼容混编需要有一个 bridge 的桥接层对齐两种语言的类名等,需要如下操作。
-
新建文件,选择 Swift File 类型。

-
按照需求命名并确保文件后缀是 .swift,然后点击 Create。

-
点击 Create Bridging Header。
note请确保选择 Create Bridging Header。否则,Xcode 将不会创建桥接层文件。

-
确保 Xcode 工程中创建了两个文件(一份为第二步创建的 .swift 文件,另一份为自动创建的 project_name-Bridging-Header.h 文件)。
info文件内容无需更改。

- Unity
- Unreal Engine
不适用。
Unreal Engine 中无法直接增加 iOS 端 Swift 模块,需要修改引擎配置。
-
使用 Xcode 12 及以上版本时,需要在
/Plugins/INTLSDK/Source/INTLCore/INTLCore.Build.cs中添加以下的代码。PublicSystemLibraryPaths.Add("/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos");
PublicSystemLibraryPaths.Add("/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/iphoneos");note由于 Player Network SDK 已经提前进行了以下配置,使用其他版本的 Xcode 时可以省略这个步骤。

由于使用 Xcode 12 及以上版本的 Swift lib 在编译 Unreal Engine 时会报以下错误,只有使用 Xcode 12 及以上版本时需要这个步骤解决问题。

-
修改本地 Unreal Engine 的源代码。
在 /Your_UE_Installation_Path/Engine/Source/Programs/UnrealBuildTool/ProjectFiles/Xcode/XcodeProject.cs 的
private void AppendProjectBuildConfiguration(StringBuilder Content, string ConfigName, string ConfigGuid)函数中添加下面的代码。// Enable Swift
Content.Append("\t\t\t\tCLANG_ENABLE_MODULES = YES;" + ProjectFileGenerator.NewLine);
Content.Append("\t\t\t\tSWIFT_VERSION = 5.0;" + ProjectFileGenerator.NewLine);
Content.Append("\t\t\t\tLIBRARY_SEARCH_PATHS = \"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\";" + ProjectFileGenerator.NewLine);
if (ConfigName == "Debug")
{
Content.Append("\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";" + ProjectFileGenerator.NewLine);
}
Content.Append("\t\t\t\tALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;" + ProjectFileGenerator.NewLine);
Content.Append("\t\t\t\tEMBEDDED_CONTENT_CONTAINS_SWIFT = YES;" + ProjectFileGenerator.NewLine);
-
在 /Your_UE_Installation_Path/Engine/Source/Programs/UnrealBuildTool/Platform/IOS/IOSToolChain.cs 的
string GetLinkArguments_Global(LinkEnvironment LinkEnvironment)函数中添加下面的代码。
- Before XCode 12
- XCode 12 and later
// enable swift support
Result += " -rpath \"/usr/lib/swift\"";
Result += " -rpath \"@executable_path/Frameworks\"";
// /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/lib/swift/
String swiftLibPath = String.Format(" -L {0}Platforms/{1}.platform/Developer/SDKs/{1}{2}.sdk/usr/lib/swift",
Settings.Value.XcodeDeveloperDir, bIsDevice? Settings.Value.DevicePlatformName : Settings.Value.SimulatorPlatformName, Settings.Value.IOSSDKVersion);
Result += swiftLibPath;
Log.TraceInformation("Add swift lib path : {0}", swiftLibPath);
///Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos
swiftLibPath = String.Format(" -L {0}Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/{1}",
Settings.Value.XcodeDeveloperDir, bIsDevice? Settings.Value.DevicePlatformName.ToLower() : Settings.Value.SimulatorPlatformName.ToLower());
Result += swiftLibPath;
Log.TraceInformation("Add swift lib path : {0}", swiftLibPath);
///Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/iphoneos
swiftLibPath = String.Format(" -L {0}Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/{1}",
Settings.Value.XcodeDeveloperDir, bIsDevice? Settings.Value.DevicePlatformName.ToLower() : Settings.Value.SimulatorPlatformName.ToLower());
Result += swiftLibPath;

// 该行代码需要前置(前置的代码位置见下面示例图片)
// enable swift support, make sure '/usr/lib/swift' goes before '@executable_path/Frameworks'
Result += " -rpath \"/usr/lib/swift\"";

// enable swift support
Result += " -rpath \"@executable_path/Frameworks\"";
// /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/lib/swift/
String swiftLibPath = String.Format(" -L {0}Platforms/{1}.platform/Developer/SDKs/{1}{2}.sdk/usr/lib/swift",
Settings.Value.XcodeDeveloperDir, bIsDevice? Settings.Value.DevicePlatformName : Settings.Value.SimulatorPlatformName, Settings.Value.IOSSDKVersion);
Result += swiftLibPath;
Log.TraceInformation("Add swift lib path : {0}", swiftLibPath);
///Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos
swiftLibPath = String.Format(" -L {0}Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/{1}",
Settings.Value.XcodeDeveloperDir, bIsDevice? Settings.Value.DevicePlatformName.ToLower() : Settings.Value.SimulatorPlatformName.ToLower());
Result += swiftLibPath;
Log.TraceInformation("Add swift lib path : {0}", swiftLibPath);
///Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/iphoneos
swiftLibPath = String.Format(" -L {0}Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/{1}",
Settings.Value.XcodeDeveloperDir, bIsDevice? Settings.Value.DevicePlatformName.ToLower() : Settings.Value.SimulatorPlatformName.ToLower());
Result += swiftLibPath;
// Xcode 12 adds the swiftCompatibility51 library, so you need to add the following code
if (Settings.Value.IOSSDKVersionFloat >= 14.0f)
{
Result += String.Format(" -lswiftCompatibility51");
}

- 打开解决方案重新编译
/Users/intl/UE4/UE_4.25/Engine/Source/Programs/UnrealBuildTool/UnrealBuildTool.sln。
3. 完成 Player Network SDK 配置
- 打开项目的 INTLConfig.ini 文件:
[Discord channel configuration]
DISCORD_APP_ID = {INTL_DISCORD_APP_ID}
- 将
{INTL_DISCORD_APP_ID}替换为游戏的 Discord App ID。
- 将 Discord 添加到
Info.plist文件中。
- Unity
- Unreal Engine
使用 Unity 导出 Xcode 项目时,请确认 INTLDiscordKit.projmods 中已包含 Discord 回调 scheme 配置。
Player Network SDK 已经将配置写入 INTLDiscordKit.projmods 文件,因此游戏团队通常只需检查配置是否存在,无需手动添加。
"CFBundleURLTypes" :
[
{
"CFBundleTypeRole":"Editor",
"CFBundleURLName":"Discord",
"CFBundleURLSchemes":["discord-{INTL_DISCORD_APP_ID}"]
}
]
根据 SDK 版本打开对应的文件进行检查或修改:
- V1.24 及之后版本:
INTLSDK/Source/INTLDiscord/Libs/iOS/INTLDiscord_UPL.xml - V1.18 至 V1.23:
INTLSDK/Source/INTLConfig/Configs/iOS/Plist/INTLDiscord.plist
<key>CFBundleURLName</key>
<string>Discord</string>
<key>CFBundleURLSchemes</key>
<array>
<string>discord-{INTL_DISCORD_APP_ID}</string>
</array>
步骤2:添加 Discord 登录
Discord 登录前无需安装应用程序。如果已安装应用,会打开应用登录,否则会打开浏览器登录。
-
注册登录相关回调。
- Unity
- Unreal Engine
// Add callbacks
public void AddAuthObserver()
{
INTLAPI.AddAuthResultObserver(OnAuthResultEvent);
}
// Remove callbacks
public void RemoveAuthObserver()
{
INTLAPI.RemoveAuthResultObserver(OnAuthResultEvent);
}
// Process the INTLAuthResult callback
public void OnAuthResultEvent(INTLAuthResult AuthResult)
{
Debug.Log($"MethodID: {AuthResult.MethodId}");
string methodTag = "";
switch (AuthResult.MethodId)
{
case (int)INTLMethodID.INTL_AUTH_LOGIN:
methodTag = "Login";
break;
case (int)INTLMethodID.INTL_AUTH_BIND:
methodTag = "Bind";
break;
case (int)INTLMethodID.INTL_AUTH_AUTOLOGIN:
methodTag = "AutoLogin";
break;
case (int)INTLMethodID.INTL_AUTH_QUERY_USER_INFO:
methodTag = "QueryUserInfo";
break;
case (int)INTLMethodID.INTL_AUTH_GET_AUTH_RESULT:
methodTag = "GetAuthResult";
break;
}
}C++ Event Handling (above v1.15)
//configure callback
FINTLAuthEvent authEvent;
authEvent.AddUObject(this, &OnAuthResult_Implementation);
UINTLSDKAPI::SetAuthResultObserver(authEvent);
// Remove callbacks
UINTLSDKAPI::GetAuthResultObserver().Clear();void OnAuthResult_Implementation(FINTLAuthResult ret)
{
UE_LOG(LogTemp, Warning, TEXT("MethodID: %d"), ret.MethodId);
}Unreal Event Handling
void OnAuthResult_Implementation(FINTLAuthResult ret)
{
UE_LOG(LogTemp, Warning, TEXT("MethodID: %d"), ret.MethodId);
} -
调用
AutoLogin接口自动登录。- Unity
- Unreal Engine
INTLAPI.AutoLogin();UINTLSDKAPI::AutoLogin(); -
在自动登录失败时调用
Login接口使玩家手动登录。- Unity
- Unreal Engine
INTLAPI.Login(INTLChannel.Discord, "identify", "");
INTLAPI.Login(INTLChannel.Discord, "identify,relationships.read,activities.write", ""); //Friend functionsUINTLSDKAPI::Login(EINTLLoginChannel::Discord, "identify", "");
UINTLSDKAPI::Login(EINTLLoginChannel::Discord, "identify,relationships.read,activities.write", ""); //Friend functions -
与游戏后台同步客户端身份验证状态,等待最终验证结果。
步骤3:验收登录功能
在 Player Network SDK 日志中搜索关键字 "AuthResult" 确认渠道名称和 OpenID 是否正确返回。如果正确,则表明集成配置成功,登录功能已成功添加。
如果接入过程中遇到问题,请参见 常见问题。

