iOS
本文旨在介绍如何设置 Discord 身份验证,让您的游戏可以使用 Player Network 登录鉴权服务通过 Discord 渠道登录。
由于 Discord SDK 已停止维护拉起 Discord App 的授权方式,后续可能会对 Discord App 授权造成影响。为确保 Discord 授权稳定可用,推荐使用 WebView 进行网页授权,详见配置 DISCORD_LOGIN_USING_WEB。
从 2024 年春季开始,对于需更新或上传至 Apple App Store Connect 的应用,开发者需明确 注明使用原因,以展示该应用如何使用 required reason API(需提交使用原因的 API)。更多信息,请参见 即将发布的第三方 SDK 要求。
由于 Discord 的隐私清单尚未公布,目前 Player Network SDK 隐私清单中不包含对应的内容,详见 iOS 17 隐私清单。
前提条件
1. 在 Discord 开发者平台 上配置应用
1. 创建 Discord 应用
创建 Discord 应用程序之前,请在 Discord 官方网站 上注册一个账号,并根据提示完成账号认证(通过电子邮件)。
进入 Discord 开发者平台。
首次登录时,用户可能需要验证自己不是机器人。您可以在电子邮件验证后完成。在 Applications 页面右上角,点击 New Application。
在弹出的应用程序创建窗口中,输入应用程序名称,然后点击 Create。
在 General Information 页面,查看 APPLICATION ID。
用户必须在 INTLConfig.ini 文件中配置 App ID。
2. 配置应用
在 Applications 页面,单击要配置的应用程序。
点击左侧导航栏中的 OAuth2,然后转到 OAuth2 > General。
在 Redirects 下配置下列重定向 URL,用于在 Discord 网页进行授权后接收回调,可点击 Add Another 增加单元格:
- https://common-web.intlgame.com/jssdk/discordlogincallback.html
- https://test-common-web.intlgame.com/jssdk/discordlogincallback.html
注意在移动端如果想要使用 Discord app 而非 Discord 网页进行授权,还需要填写一个重定向 URL 用于 Discord app 授权后回调。 重定向 URL 规则:
- 全部使用小写。
- 方案应以 "intl" 开头。
- URL 应包括主机和路径。
例子: intlmoba://auth/callback
注意对于 INTLConfig.ini 的
DISCORD_UNIVERSAL_LINK_IOS
- 配置 打开游戏的通用链接。
- 将链接添加至 Redirect URL
注意对于多商店渠道包:需要单独的
REDIRECT_URL_SCHEME
。支持多商店渠道包需要单独的
REDIRECT_URL_SCHEME
。一个 App ID 支持 10 个重定向 URL(约 4 个多商店渠道包)。如果游戏需要多于 4 个多商店渠道包,请申请更多 App ID。要使用多个应用程序 ID,游戏需要在INTLConfig.ini
中配置多个应用程序 ID 和 在 Player Network 上注册多个 Discord 应用程序。点击左侧导航栏中的 Rich Presence,进入 Rich Presence Art Assets 页面。
点击 Add Image(s),配置应用程序的图片资源。
说明应用程序中使用的所有图片资源都必须在此页面进行配置,包括好友邀请函的封面照片。
步骤1:为 Discord 登录配置 SDK
Discord SDK 仅与 iOS SDK 11 及更高版本兼容。
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
XUPorter 从 Unity 导出 Xcode 的时候,可以自动化配置 Xcode 工程,添加依赖库和源码文件,便于打包操作。
Player Network SDK 在原来的 XUPorter 基础上做了优化。如果业务也使用了 XUPorter 方案,Player Network SDK 的方案和业务的方案不会冲突。
- 添加了
INTLSDKEditor
命名空间,避免其他组件也使用 XUPorter 时命名重复。 - 更改了搜索 mods 文件的路径,让 Player Network SDK XUPorter 只搜索
Asset/INTLSDK/
目录下的 mods 文件,不会重复添加其他组件的配置。 - 在
UnityAppController.mm
中增加生命周期。
Player Network SDK XUPorter 方案
INTL{Plugin}Kit.projmods
是 Player Network SDK 的 Info.plist
配置文件。Player Network SDK 通过读取 INTLSDK/Editor/XUPorter/Mods
目录中的 INTL{Plugin}Kit.projmods
文件,在 Xcode 中增加所导入的 bundle,framework 等依赖包。
每个插件都有一个对应的 INTL{Plugin}Kit.projmods
文件,游戏要根据所需的插件配置对应的文件,并以 INTLConfig.ini 配置文件中的值替换 {占位符} 文本。
例如,根据需求更新 INTLDiscordKit.projmods
。
"Info.plist":{
"LSApplicationQueriesSchemes":
[
"com.hammerandchisel.discord"
],
"NSAppTransportSecurity":
{
"NSAllowsArbitraryLoads":true
},
"CFBundleURLTypes" :
[
{
"CFBundleTypeRole":"Editor",
"CFBundleURLName":"Discord",
"CFBundleURLSchemes":["{INTL_DISCORD_REDIRECT_SCHEME}"]
}
]
}
在配置文件中添加 Player Network SDK 相关配置,根据您的游戏修改 Discord 相关配置。
- Player Network SDK 1.18 及之后版本
- Player Network SDK 1.18 之前版本
根据 SDK 版本打开对应的文件进行修改:
- V1.24 及之后版本:
INTLSDK/Source/INTLDiscord/Libs/iOS/INTLDiscord_UPL.xml
- V1.18 至 V1.23:
INTLSDK/Source/INTLConfig/Configs/iOS/Plist/INTLDiscord.plist
<key>CFBundleURLSchemes</key>
<array>
<string>{YOUR_DISCORD_REDIRECT_SCHEME}</string>
</array>
业务需到 Unreal Engine > Settings > Project Settings > Platforms > iOS > Extra Plist Data 修改配置,在 Plist 文件中添加 SDK。
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>Discord</string>
<key>CFBundleURLSchemes</key>
<array>
<string>{YOUR_DISCORD_REDIRECT_SCHEME}</string>
</array>
</dict>
</array>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>com.hammerandchisel.discord</string>
</array>
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"
警告接入时,用户可以根据需要修改内容,并与法律团队确认内容是否合规。如果无修改, 将 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>
警告接入时,用户可以根据需要修改内容,并与法律团队确认内容是否合规。如果无修改, 将 INTLSample 替换为游戏名称。
2. Swift SDK 适配器
如果模块使用到的是 Swift 版本的 SDK,这里会涉及到 iOS 的 Swift 和 Objective-C 的混编问题。 Xcode 为了兼容混编需要有一个 bridge 的桥接层对齐两种语言的类名等,需要如下操作。
新建文件,选择 Swift File 类型。
按照需求命名并确保文件后缀是 .swift,然后点击 Create。
点击 Create Bridging Header。
注意请确保选择 Create Bridging Header。否则,Xcode 将不会创建桥接层文件。
确保 Xcode 工程中创建了两个文件(一份为第二步创建的 .swift 文件,另一份为自动创建的 project_name-Bridging-Header.h 文件)。
说明文件内容无需更改。
- 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");注意由于 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}
DISCORD_REDIRECT_URL = {INTL_DISCORD_REDIRECT_URL}
DISCORD_UNIVERSAL_LINK_IOS = {INTL_DISCORD_UNIVERSAL_LINK_IOS}
- 将
{INTL_DISCORD_APP_ID}
替换为游戏的 Discord App ID。 - 将
{INTL_DISCORD_REDIRECT_URL}
替换为平台上配置的 Redirect URL。 - 将
{INTL_DISCORD_UNIVERSAL_LINK_IOS}
替换为在开发者平台上配置的 重定向 通用链接。
- 将 Discord 添加到
Info.plist
文件中。
- Unity
- Unreal Engine
使用 Unity 导出 Xcode 项目时,请配置 .projmods 文件。
Player Network SDK 已经将这些配置写入了 INTLCoreKit.projmods
文件,因此游戏团队只需检查配置即可。
{
"group": "INTL",
"Info.plist":{
"CFBundleURLTypes" :
[
{
"CFBundleTypeRole":"Editor",
"CFBundleURLName":"Discord",
"CFBundleURLSchemes":["{INTL_DISCORD_REDIRECT_SCHEME}"]
}
]
},
}
- Player Network SDK 1.18 及之后版本
- Player Network SDK 1.18 之前版本
根据 SDK 版本打开对应的文件进行修改:
- V1.24 及之后版本:
INTLSDK/Source/INTLDiscord/Libs/iOS/INTLDiscord_UPL.xml
- V1.18 至 V1.23:
INTLSDK/Source/INTLConfig/Configs/iOS/Plist/INTLDiscord.plist
<key>CFBundleURLSchemes</key>
<array>
<string>{INTL_DISCORD_REDIRECT_SCHEME}</string>
</array>
业务需到 Unreal Engine > Settings > Project Settings > Platforms > iOS > Extra Plist Data 修改配置,在 PLIST 文件中添加 SDK。
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>Discord</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>{INTL_DISCORD_REDIRECT_SCHEME}</string>
</array>
</dict>
</array>
将 {INTL_DISCORD_REDIRECT_SCHEME}
替换为重定向 URL 中配置的方案。
例如,如果在 Discord Developer Platform 上配置的 Redirect URL 是 intlsample://auth/callback
:
{INTL_DISCORD_REDIRECT_SCHEME}
= intlsample
步骤2:添加 Discord 登录
Discord 登录前无需安装应用程序。如果已安装应用,会打开应用登录,否则会打开 Web 界面登录。
Discord 登录 permission
需要添加 identify
。如果需要集成 Discord 共享功能,则也需添加 relationships.read,activities.write
。
注册登录相关回调。
- 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 ret)
{
Debug.Log($"MethodID: {ret.MethodId}");
string methodTag = "";
if (authRet.MethodId == (int)INTLMethodID.INTL_AUTH_LOGIN)
{
methodTag = "Login";
}
else if (authRet.MethodId == (int)INTLMethodID.INTL_AUTH_BIND)
{
methodTag = "Bind";
}
else if (authRet.MethodId == (int)INTLMethodID.INTL_AUTH_AUTOLOGIN)
{
methodTag = "AutoLogin";
}
else if (authRet.MethodId == (int)INTLMethodID.INTL_AUTH_QUERY_USER_INFO)
{
methodTag = "QueryUserInfo";
}
else if (authRet.MethodId == (int)INTLMethodID.INTL_AUTH_GET_AUTH_RESULT)
{
methodTag = "GetAuthResult";
}
}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 是否正确返回。如果正确,则表明集成配置成功,登录功能已成功添加。
如果接入过程中遇到问题,请参见 常见问题。