跳到主要内容

已验证家长关联 (VPL)

已验证家长关联 (VPL) 让玩家可以主动邀请自己的家长进入您的产品。玩家发出邀请,家长完成身份验证后,即可查看并设置该玩家的各项控制。邀请处于等待状态期间,您的产品不会阻断任何内容;即使家长始终没有接受,也不会有任何东西出问题。

本指南完整介绍整个流程:创建会话、发送邀请、跟踪状态、取消邀请,以及处理任一方发起的解除关联。

请先阅读

已验证家长关联 (VPL) 解释了 VPL 为何是关联而不是门禁,以及它为何与 VPC 互斥。那里说明的资格规则决定了本指南中的调用是否会成功。

前提条件

开始之前,您需要:

  1. 一个 k-ID 产品:在 Compliance Studio创建并配置您的产品
  2. API 密钥:在产品的 Developer Settings 页面生成。本指南中的所有调用都是服务器到服务器的调用。参见身份验证
  3. 一个 webhook 端点:用于接收 Challenge.StateChangeSession.Unlink 的 HTTPS 端点。参见 Webhooks
  4. 订阅您要处理的事件:端点只会收到它已订阅的事件类型,其余的 k-ID 会直接丢弃,既不尝试投递也不返回错误。请在 Compliance Studio 中该产品的 Developer Settings 页面上,为该端点选中 Challenge.StateChangeSession.Unlink
  5. 您的组织已启用 VPL:请联系 k-ID 为您的组织开启此功能。

所有示例使用生产环境基础 URL https://game-api.k-id.com/api/v1Content-Type: application/json 以及 Authorization: Bearer <api-key> 请求头。测试模式请使用 https://game-api.test.k-id.com/api/v1

第 1 步:创建玩家的会话

调用 POST /age-gate/check 为玩家创建会话。

POST /age-gate/check
{
"jurisdiction": "US-CA",
"age": 17
}

agedateOfBirthkuid(针对您已缓存 kuid 的回访玩家)中最多传入一个。传入多个会返回 400。该端点还接受哪些年龄信号,请参见 /age-gate/check

成功的响应中包含会话:

{
"status": "PASS",
"session": {
"sessionId": "b1a6482d-5242-4b4a-aa88-3fa52595a672",
"status": "ACTIVE",
"managedBy": "PLAYER",
"hasApproverEmail": false
}
}

请把 sessionId 保存到您自己的用户记录上。本指南中的每个调用都以它为键,并且它在关联、解除关联和重新关联之间保持不变。

如果状态是 CHALLENGE 而不是 PASS,说明玩家未达其司法管辖区的访问年龄,需要父母同意。请把他们引导到 VPC,不要调用邀请端点,因为并不存在可供邀请家长的会话。

即使返回了 PASS,如果会话带有由 GUARDIAN 管理的权限,它仍然不符合 VPL 的条件。在展示邀请入口之前检查会话的 permissions[],或者在第 3 步处理 FEATURE_DISABLED 错误。

第 2 步:展示邀请入口

把它放在适合您产品的位置,例如设置、玩家资料页或引导流程。玩家点击后,收集家长的邮箱地址。

由于 VPL 是可选的且不会阻断任何内容,这只是一个普通的产品入口,而不是插屏。玩家可以一直忽略它。

第 3 步:发送邀请

调用 POST /challenge/invite-parent

POST /challenge/invite-parent
{
"sessionId": "b1a6482d-5242-4b4a-aa88-3fa52595a672",
"parentEmail": "parent@example.com",
"playerName": "Alex",
"locale": "en"
}
字段必填说明
sessionId第 1 步中的会话
parentEmail邀请的发送地址
playerName玩家的显示名称,1 到 63 个字符。会在邀请邮件中展示给家长。省略时家长会看到通用占位内容
locale邀请邮件的 IETF BCP 47 标签。省略时,如果 k-ID 已经认识这位家长,会先使用该家长自己保存的语言,然后回退到产品的主要语言,最后回退到英语
{
"status": "CHALLENGE",
"challenge": {
"challengeId": "ae6d4729-af32-42ea-8ef2-ff46c7664802",
"type": "CHALLENGE_PARENT_INVITE"
}
}

一次调用即完成创建挑战、绑定到会话并发送邮件。无需再调用其他接口来触发邮件,而且 /challenge/send-email 会拒绝家长邀请类挑战。

请把 challengeId 与会话一起保存。它在 webhook、状态端点和取消调用中用于标识这次邀请。

在您持有某个待处理邀请的 challengeId 期间,请勿就同一会话向另一个邮箱再发一封邀请。

链接的有效期

邀请邮件中的链接在生产模式下有效期为 14 天,在测试模式下为 7 分钟,便于您无需等待即可验证过期行为。

需要处理的错误

错误以 HTTP 400 返回,具体代码在响应体的 error 字段中。

代码出现时机处理方式
FEATURE_DISABLEDVerified parent linking is not enabled。您的组织未启用 VPL联系 k-ID
FEATURE_DISABLEDVerified parent linking is not available for this player。玩家未达访问年龄,或会话带有由 GUARDIAN 管理的权限回退到 VPC。不要为该会话展示邀请入口
NOT_FOUND会话不存在重新核对您保存的 sessionId
INVALID_INPUT会话的司法管辖区未在您的产品中配置在 Compliance Studio 中修正产品配置
INVALID_EMAILSession is not eligible for a new invite。会话已关联家长改为展示当前的关联状态

第 4 步:等待,但不要阻断

邀请处于等待状态期间,请让产品保持完全可用。玩家已经通过了年龄门禁,邀请本身并不改变他们能做什么。

家长完成流程后,k-ID 会向您的 webhook 端点发送 Challenge.StateChange

{
"eventType": "Challenge.StateChange",
"data": {
"id": "ae6d4729-af32-42ea-8ef2-ff46c7664802",
"productId": 12345,
"type": "CHALLENGE_PARENT_INVITE",
"status": "PASS",
"sessionId": "b1a6482d-5242-4b4a-aa88-3fa52595a672",
"approverEmail": "parent@example.com",
"kuid": "12b9fa0e-6d6d-4903-a1fc-f2233027b71d"
}
}

收到后:

  • data.iddata.sessionId 匹配回您保存的玩家记录。
  • 缓存 kuid。它告诉您这个会话已关联了一位家长。
  • 在界面上显示家长已连接。

邀请被取消时,同一事件会以 status: FAIL 发出,但 FAIL 的负载中不包含 sessionId。请用 data.id 与您保存的 challengeId 匹配,而不是 data.sessionId,否则您的处理逻辑会漏掉每一次取消。将其视为没有家长连接。玩家可以再发一次邀请。

如果家长始终没有接受,就不会再有事件,也不会有任何变化。

第 5 步:按需查询当前状态

webhook 是状态变更的权威来源,但您经常需要在不等待事件的情况下获知当前状态,例如玩家重新打开应用时。

现在是否有家长关联

sessionId 调用 GET /session/get,读取两个字段:

  • 家长处于关联状态期间 hasApproverEmailtrue,其余情况为 false。应当据以分支的是它。
  • kuid 标识该会话所关联的儿童档案。

上一次邀请怎么样了

用保存的 challengeId 调用 GET /challenge/get-status

状态含义建议的界面
PENDING邀请已创建且邮件已发送,但家长尚未打开显示邀请处于等待中,并标明 parentEmail
IN_PROGRESS家长已打开链接并开始流程显示邀请处于等待中,并标明 parentEmail
PASS家长已完成,会话已关联显示家长已连接
FAIL邀请被取消或已终止显示没有家长连接,并提供再次邀请

结合使用

渲染玩家资料页时:

  1. 调用 /session/get。若 hasApproverEmailtrue,显示家长已连接,并提供第 7 步的解除关联入口。
  2. 否则用最近的 challengeId 调用 /challenge/get-status
    • PENDINGIN_PROGRESS:把邀请显示为等待中,并提供取消。
    • PASS/session/get 仍未显示家长:这是短暂的竞态。按等待中处理,稍后重新查询。
    • FAIL,或没有保存的 challengeId:展示邀请入口。

第 6 步:取消等待中的邀请

如果家长仍在验证过程中而玩家想撤回邀请,调用 POST /challenge/cancel-invite

POST /challenge/cancel-invite
{
"challengeId": "ae6d4729-af32-42ea-8ef2-ff46c7664802"
}
{ "cancelled": true }

该挑战会带着 failureReason: "cancelled-by-initiator" 转为 FAIL,您会收到 status: FAILChallenge.StateChange,而已经打开验证组件的家长会看到已取消的状态。

对已取消的邀请再次取消是安全的,仍会返回 cancelled: true

代码出现时机
NOT_FOUND该产品下不存在此挑战
INVALID_INPUTInvalid challenge type。此端点只能取消家长邀请类挑战
INVALID_INPUTInvite already accepted。取消到达前家长已完成
FEATURE_DISABLED您的组织未启用 VPL

出现 FAIL 之后,该会话可以立即接受新的邀请。

第 7 步:处理解除关联

任一方都可以随时结束这段关系。家长可以在 Family Connect 中解除,您也可以在产品中为玩家提供解除入口。

解除关联会让会话回到未关联状态:kuid 与家长关联被清除,家长设置的额度与各项控制也会被移除。会话本身仍为 ACTIVE,玩家的权限与已推送的数据保持不变。玩家继续使用同一个 sessionId

在您的产品中解除关联

POST /session/unlink-parent
{
"sessionId": "b1a6482d-5242-4b4a-aa88-3fa52595a672",
"locale": "en"
}
{
"unlinked": true,
"unlinkedAt": "2026-04-20T18:42:11Z"
}

当本次调用(或之前的某次调用)结束了家长关联时,unlinkedtrue。若该会话从未关联过家长,则为 false,此时会省略 unlinkedAtlocale 用于指定 k-ID 发给家长、告知关联已结束的通知邮件所用的语言。省略时,如果 k-ID 已经认识这位家长,会先使用该家长自己保存的语言,然后回退到产品的主要语言,最后回退到英语。

该调用对 sessionId 是幂等的。关联已被解除后再次调用会返回 200 和原来的 unlinkedAt,而不是这次重复调用的时间。

代码出现时机
NOT_FOUND会话不存在
INVALID_INPUT会话的司法管辖区未在您的产品中配置
FEATURE_DISABLEDUnlink is only available for VPL-linked sessions。该会话不在 VPL 路径上,或您的组织未启用 VPL

只要关联结束,无论来自哪一方,k-ID 都会发送 Session.Unlink

{
"eventType": "Session.Unlink",
"data": {
"sessionId": "b1a6482d-5242-4b4a-aa88-3fa52595a672",
"productId": 12345,
"unlinkedBy": "player",
"unlinkedAt": "2026-04-20T18:42:11Z"
}
}

若解除来自您的 API,unlinkedByplayer;若家长在 Family Connect 中解除,则为 parent

收到后,不再显示家长处于已连接状态。玩家可以随时发送新的邀请。

下一步是什么?

已验证家长关联接好之后,可以通过以下资源进一步深入:

  • 已验证家长关联 (VPL):本指南背后的概念:关联与门禁的区别,以及 VPL 与 VPC 为何互斥
  • 会话sessionIdkuid 在关联、解除关联、重新关联之间的行为
  • Session.Unlink:在任一方结束关联时通知您的 webhook
  • Webhooks:webhook 订阅、投递与签名验证的完整指南
  • 发布前检查清单:上线前需要核对的要求