PlayFab GDPR - 删除和导出玩家数据

PlayFab 符合一般数据保护条例 (GDPR) 标准 - 作为服务提供商,确保提供使玩家可以查看或删除围绕他们所存储的数据所需的挂钩。

我们无法为提供法律建议—我们鼓励寻求法律顾问以确保遵守 GDPR—但还是很乐意帮助履行 GDPR 规定的义务。

PlayFab 有三个可用的 API,可帮助响应玩家数据请求:

  • GetPlayedTitleList - 调用此 API 可获取具有与给定玩家关联的数据的 TitleId 列表。 此列表由 PublisherID 确定范围,表示在删除或导出此玩家数据时会受影响的游戏集。
  • DeleteMasterPlayerAccount - 调用此 API 可删除给定玩家的记录。
  • ExportMasterPlayerData - 调用此 API 可导出给定玩家的所有关联数据和记录。

确保找到所有数据

使用DeleteMasterPlayerAccountExportMasterPlayerData API 之前,必须注意,玩家可能通过工作室创建了多个主玩家帐户。

当玩家使用不同设备或不同凭据玩游戏时,可能会发生这种情况。 因为他们提供不同的不相关凭据(例如,电子邮件地址或社交媒体帐户),所以我们会将他们解释为唯一的玩家。

玩家可能具有多个主玩家帐户的另一种方式是将工作室配置为使用多个发布者 ID 时;但是,具有多个发布者 ID 并不常见。

可以在每个“标题”设置菜单的 API 功能 选项卡上的 PlayFab Game Manager 中检查游戏的“发布者 ID”。

PlayFab - Settings -“API”选项卡

了解自己的游戏以及游戏如何对玩家进行身份验证。 调用 DeleteMasterPlayerAccountExportMasterPlayerData 之前,请确保从玩家收集正确的设备 ID 和/或凭剧集。

借助这些凭据,我们可以标识每个 主玩家帐户的 PlayFabId。

以下 API 可帮助从凭据转换为PlayFabId

注意

所有这些 API 都特定于游戏。 前两个是管理员 API,后两个是服务器 API。

即使玩家只有一个 PlayFabId,他们可能会使用该 ID 玩多个游戏。 这意味着其数据请求可能会跨多个游戏。

若要获取此游戏列表,请对每个 PlayFabId 调用 GetPlayedTitleList。 你可能希望告知玩家,其请求会影响返回的游戏列表。

此外,GetPlayedTitleList会返回TitleIds不是Title Names - 在确认页面中显示这些信息之前,请考虑将这些 ID 转换为Title Names

下面是一些伪代码,可更好地表达我们的意思...

//Here you would iterate through a request of known Ids, Emails, linked accounts  
//or other PlayFab searchable info on the player that you have.
//and store it in user credentials for that player.
user {
  credentials: (email/ids/linked accounts)
}

//create a variable to hold a list of all the PlayFabIds you want to remove.
PlayFabIdList

//create a list of affected titles
AffectedTitles


//Keep track of all your titles, this is important
//and should include all titles across all your namespaces.
foreach(title in <all my titles>){

    //each user record you have for the player, you should have a list of credentials for that player
    //so you can find them in PlayFab
    foreach(cred in user.credentials){
      //There are a few helper Admin and Server API's that help you do this part.
      //See below this pseudo code block for some tips!
      pfid = <find PlayFabId in Title using the credential>
      PlayFabIdList.add(pfid)
    }

    //go through the list of PlayFabIds that you have and fine all titles that
    //performing the action would affect
    foreach(pfid in PlayFabIdList){
      AffectedTitles = title.GetPlayedTitleList(pfid)
    }
}

下面是有关如何使用GetPlayedTitleList的快速示例。

public static async void StartFindTitlesExample(Action<PlayFabError> callback)
{

    var task = await PlayFabAdminAPI.GetPlayedTitleListAsync(new GetPlayedTitleListRequest() {
        PlayFabId = PlayFabId
    });

    if(task.Error != null)
    {
        callback(task.Error);
        return;
    }

    var TitleList = task.Result.TitleIds;
    foreach (var title in TitleList)
    {
        Console.WriteLine(string.Format("Title Found: {0}", title));
    }
    callback(null);
}

此时具有此玩家的PlayFabIds列表(基于其共享的凭据)和每个PlayFabId的游戏列表。 现在该怎么办?

现在已准备好进行删除或导出!

删除主玩家帐户

可以使用新的DeleteMasterPlayerAccount管理员 API(在所有 SDK 中可用)来实现主玩家帐户的删除。 请确保阅读上面一节,其中详细说明了如何确保获得玩家的所有 PlayFabId。

请求删除玩家时,PlayFab 会首先将玩家的个人信息从我们的核心系统中快速移除,然后将请求发送给队列处理代理,该代理会从辅助系统和子处理器中移除有关玩家的任何其余信息。

此 API 立即返回并提供 JobReceiptId,应该将它存储到记录中。 JobReceiptId 是验证 PlayFab 是否收到了删除玩家的请求。

删除完成后,会向为游戏配置的通知电子邮件地址发送电子邮件。 它包含最初从 API 返回的相同 JobReceiptId。 任务的完成也会触发 PlayStream 事件。

使用我们的 WebHook 功能可以进行注册,从而在所选终结点上接收这些事件并根据需要进行处理。 事件包含一个具有 JobReceiptId 的 JSON Blob。

下面的示例介绍如何将管理员 API 与 C# SDK 结合使用。 如果要使用其他 SDK,请从 PlayFab SDK 列表中选择一个。

public static async void StartDeleteMasterPlayerExample(Action<PlayFabError> callback)
{
    var task = await PlayFabAdminAPI.DeleteMasterPlayerAccountAsync(new DeleteMasterPlayerAccountRequest()
    {
        PlayFabId = PlayFabId
    });

    if(task.Error != null)
    {
        callback(task.Error);
    }

    var jobReceiptId = task.Result.JobReceiptId;
    var AffectedTitleList = task.Result.TitleIds;
    foreach (var title in AffectedTitleList)
    {
        Console.WriteLine(string.Format("Delete Player - Title Affected: {0}", title));
    }

}

注意

由于这种删除 无法撤销,我们建议与玩家确认,他们是否对其删除请求的范围和影响感到满意。

因此,一旦确认了操作... 回到伪代码。

//Make sure we are 100% sure we want to do this.
if ( confirm successful ) {
   //create a variable to store a list of titles the player has already been removed from.
   listOfTitlesRemovedFrom
   //Hang on to the receipts from successful deletes.
   listOfReceipts
   foreach(title in <all my titles>){

       //You only need to remove the Master Player once per namespace, so check that you have not
       //already performed this action in the namespace, or you will get an error that
       //the player is already queued for deletion.
       if(title not in listOfTitlesRemovedFrom){
           foreach(pfid in PlayFabIdList){

              //Note: you should do some error handling around this API call.
              response = title.DeleteMasterPlayerAccount(pfid)
              foreach(titleId in response.titleids){
                listOfTitlesRemoved.add(titleId)
              }
              listOfReceipts.add(response.jobreceiptid)
           }
       }
   }

   //Save listOfReceipts somewhere as proof of deletion.

}

导出主玩家帐户数据

请求导出玩家数据时,请求会发送给队列处理代理 (与删除玩家类似)。

ExportMasterPlayerData API 会导出与给定 PlayFabId 关联的所有数据,包括跨所有游戏的数据,如:

  • 统计信息
  • 自定义数据
  • 库存
  • 购买
  • 玩家创建的物品/UGC
  • 交易历史记录
  • 虚拟货币余额
  • 角色
  • 组成员资格
  • 发布者数据
  • 凭据数据
  • 帐户链接
  • 好友列表
  • PlayFab 事件历史记录

请确保阅读上面第一节,其中详细说明了如何确保获得玩家的所有 PlayFabId。

此 API 立即返回 JobReceiptId,应将它存储在记录中以供将来参考。 可能需要经过一段时间才能下载导出。

导出完成时,会向为游戏配置的通知电子邮件地址发送包含用于下载导出转储的 URL 的电子邮件。

完成任务也会触发 player_data_exported PlayStream 事件。 事件包含作为属性的 JobReceiptId,以及提供对导出数据的访问权限的 ExportDownloadUrl 属性。 将自动化规则与 Azure 函数Webhook 配合使用,可以根据需要在选择和处理的终结点上注册以接收这些事件。

下面的示例介绍如何将管理员 API 与 C# SDK 结合使用。 如果要使用其他 SDK,请从 PlayFab SDK 列表中选择一个。

public static async void ExportMasterPlayerExample(Action<PlayFabError> callback)
{
    var task = await PlayFabAdminAPI.ExportMasterPlayerDataAsync(new ExportMasterPlayerDataRequest()
    {
        PlayFabId = PlayFabId
    });

    if(task.Error != null)
    {
        callback(task.Error);
    }

    var jobReceiptId = task.Result.JobReceiptId;

    Console.WriteLine(string.Format("Export Player Request Received - Receipt: {0}", jobReceiptId));

    callback(null);
}

注意

URL 会在导出完成之后的最多 30 天内可用。 此时间过后会删除文件,需要发起 导出请求。

已导出数据的格式

已导出的数据打包在 ZIP 存档中,其名称包含 JobReceiptId 和 导出时间。 该存档包含组织成目录结构的多个文件。

文件路径 说明
/master_player_export.json

包含 PlayFab 中记录的玩家数据的 JSON 文件。 这包括玩家参与的每个游戏的数据。

JSON 文档的架构作为 OpenAPI 规范提供。 请参阅 https://<your_title_id>.playfabapi.com/Swagger/MasterPlayerDataExport.swagger.json 中的对象 MasterPlayerDataExport

/CustomFiles/MasterPlayerFiles/* 包含与玩家的 master_player_account 实体关联的自定义实体文件
/CustomFiles/TitlePlayerFiles/<TitlePlayerAccountId>/*

包含与玩家的 title_player_account 实体关联的自定义实体文件

该文件按玩家参与的游戏组织到一个子目录中。 每个子目录的名称是游戏中玩家的 title_player_account 实体 ID。

/TitlePlayerEvents/<TitleId>/event-history_1.jsonl
...
/TitlePlayerEvents/<TitleId>/event-history_<N>.jsonl

记录的有关玩家的 PlayStream 和遥测事件。

该文件按玩家参与的游戏组织到一个子目录中。 每个子目录的名称是游戏 ID。

每个子目录包含一个或多个 event-history 文件,具体取决于玩家在给定游戏中拥有的数据量。 这些文件包含序列化为 JSON 对象的事件,每行一个事件。

其他注意事项

使用这些 API 容易造成伤害。 对错误玩家导出数据或进行删除可能会非常具有破坏性,并且是永久性的

由游戏开发者负责验证凭据是否与由请求导出或删除其玩家数据的玩家匹配。 PlayFab 在使用这些 API 时 提供任何类型的验证。

不过 PlayFab 提供一个电子邮件验证功能。 但是我们的解决方案不是进行验证的唯一选项。 也可以创建自己的 过程。

无论使用何种技术,建议在执行其中任何操作之前进行某种验证。

我们完成了吗?

请求完成时,应收到电子邮件。 如果出于某种原因从未收到该电子邮件 (因为在数字世界中有时会发生这种情况),请通过privacy@playfab.com与我们取得联系并请求验证。

请在该电子邮件中提供JobReceiptId,我们会回复,了解该作业的状态。