为新权限请求同意
当玩家已经获得会话权限后,他们可能希望启用其他权限。权限可能被禁用的原因包括:
- 玩家未达到权限默认启用的年龄门槛。
- 玩家未达到权限的绝对最低年龄要求。
- 该权限只能通过家长/监护人的同意启用,但在初始同意流程中未被启用。
/session/upgrade
API
/session/upgrade
API 可用于启用其他权限。任何 managedBy
字段设置为 PLAYER
的权限将立即启用。如果某些权限的 managedBy
设置为 GUARDIAN
,则会为家长/监护人创建一个挑战,以完成同意流程来更改权限。
请求家长同意
当需要家长同意以启用权限时,响应中将包含一个 challenge
。可以通过类似于初始年龄门的方式共享此挑战,例如使用二维码、一次性密码(OTP)或电子邮件。
一个改进用户体验的功能是,可以使用 /challenge/send-email
API 而无需指定电子邮件地址,该 API 将发送邮件至最近一次为玩家批准权限的家长/监护人。这使玩家可以请求更改权限,而无需自行指定电子邮件地址。如果未找到关联的电子邮件地址,/challenge/send-email
API 将返回 INVALID_EMAIL
错误代码,此时需要切换到其他方法,例如提供二维码或 OTP,或者要求玩家输入家长/监护人的电子邮件地址。
示例
在 Unreal C++ 中升级会话
// 如果权限由 GUARDIAN 管理,则创建一个新的同意挑战;
// 如果成功,则调用 EnableFeature 回调参数,可在游戏中启用该功能
void UKidWorkflow::UpgradeSession(const FString &FeatureName, TFunction<void()> EnableFeature)
{
TSharedPtr<FJsonObject> JsonObject = MakeShareable(new FJsonObject());
JsonObject->SetStringField(TEXT("sessionId"), SessionInfo->GetStringField(TEXT("sessionId")));
TSharedPtr<FJsonObject> PermJsonObject = MakeShareable(new FJsonObject());
PermJsonObject->SetStringField(TEXT("name"), FeatureName);
TArray<TSharedPtr<FJsonValue>> JsonArray;
JsonArray.Add(MakeShareable(new FJsonValueObject(PermJsonObject)));
JsonObject->SetArrayField(TEXT("requestedPermissions"), JsonArray);
FString ContentJsonString;
TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&ContentJsonString);
FJsonSerializer::Serialize(JsonObject.ToSharedRef(), Writer);
HttpRequestHelper::PostRequestWithAuth(BaseUrl + TEXT("/session/upgrade"), ContentJsonString, AuthToken,
[this, EnableFeature, FeatureName](FHttpResponsePtr Response, bool bWasSuccessful)
{
if (bWasSuccessful)
{
TSharedPtr<FJsonObject> JsonResponse;
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(Response->GetContentAsString());
if (FJsonSerializer::Deserialize(Reader, JsonResponse))
{
if (JsonResponse->HasField(TEXT("challenge")))
{
TSharedPtr<FJsonObject> Challenge = JsonResponse->GetObjectField(TEXT("challenge"));
FString ChallengeId = Challenge->GetStringField(TEXT("challengeId"));
FString OneTimePassword = Challenge->GetStringField(TEXT("oneTimePassword"));
FString QRCodeUrl = Challenge->GetStringField(TEXT("url"));
SaveChallengeId(ChallengeId);
ShowConsentChallenge(ChallengeId, ConsentTimeoutSeconds, OneTimePassword, QRCodeUrl,
[this, EnableFeature, FeatureName](bool bConsentGranted, const FString &SessionId)
{
ClearChallengeId();
if (bConsentGranted)
{
GetSessionPermissions(SessionId, TEXT(""));
EnableFeature();
}
else
{
// 请求启用功能被拒绝,不执行任何操作
UE_LOG(LogTemp, Warning, TEXT("Feature request denied for feature %s."), *FeatureName);
}
});
}
else if (JsonResponse->HasField(TEXT("session")))
{
SessionInfo = JsonResponse->GetObjectField(TEXT("session"));
SaveSessionInfo();
EnableFeature();
}
}
}
});
}