セッションと権限の管理
プレイヤーとその親が同意フローを完了した後(VPCウィジェットまたはカスタム年齢ゲートのいずれかを通じて)、ゲームはプレイヤーの権限を含むセッションを受け取ります。ただし、権限は時間の経過とともに変化する可能性があります:親がFamily Connectを通じて設定を調整したり、プレイヤーが誕生日を迎えて新しい年齢カテゴリに移動したり、誰かが追加機能へのアクセスをリクエストしたり、高リスク権限が解除前に年齢確認を必要としたりする可能性があります。
このガイドでは、これらの変更を検出し、適切に対応し、プレイヤーに明確に伝達して、常に現在の機能アクセスを理解できるようにする方法を説明します。
ゲームが閉じている間(または実行中でも)に権限が変更されると、機能が突然表示されたり消えたりすると、プレイヤーは混乱する可能性があります。明確な伝達がないと、これらの変更はバグのように見える可能性があり、親からの意図的な更新や年齢関連の調整とは見えません。
前提条件
始める前に、以下を確認してください:
- 完了した同意フロー:プレイヤーはVPCクイックスタートまたはカスタム年齢ゲートクイックスタートを完了してアクティブなセッションを持っている必要があります
- k-IDプロダクト:k-ID Compliance Studioでプロダクトを作成して設定
- APIキー:Compliance Studioのプロダクトの開発者設定ページからAPIキーを生成
- Webhookエンドポイント(推奨):セッションイベントを受信するためのセキュアなHTTPSエンドポイントを設定。詳細については、Webhooksを参照してください。
セッションとチャレンジの理解
プレイヤーが信頼できる大人からアクセスを許可されると、プロダクトごとに正確に1つのセッションを持ちます。権限が変更されると(親の変更、年齢アップイベント、または権限のアップグレードを介して)、同じセッションIDが新しい権限で更新されます。新しいセッションは作成されません。既存のセッションがプレイヤーのアクセスの現在の状態を反映します。ただし、セッションが取り消され、信頼できる大人が再度同意フローを実行すると、新しいセッションIDを持つ新しいセッションが作成されます。
チャレンジは、親の承認を必要とする同意リクエストです。チャレンジが正常に完了すると(PASS)、セッションが作成されるか、付与された権限で更新されます。逆に、セッションが削除されると、そのプレイヤーのすべての未完了のチャレンジが自動的にFAILに設定されます。チャレンジの詳細については、Challenges概念ガイドを参照してください。
権限が変更される方法
権限の変更は、いくつかの理由で発生する可能性があります:
| 変更タイプ | 説明 | 検出方法 |
|---|---|---|
| 親が権限を変更 | 親がFamily Connectを使用して機能を有効または無効にする | Webhookまたはセッション比較 |
| プレイヤーが年齢アップ | 誕生日によりプレイヤーが新しい年齢カテゴリに移動。プレイヤーが親の同意を必要としなくなる年齢に達すると、権限のmanagedByがPLAYERに設定され、プレイヤーが直接制御できるようになります | セッション比較のみ |
| 高リスク権限が解除 | プレイヤーが verifiedAgeThreshold を持つ権限(ブラジルのルートボックスなど)の年齢保証を完了。権限が enabled: false から enabled: true に変わる | Webhook(Session.ChangePermissions)またはセッション比較 |
| セッション削除 | 親がFamily Connectを通じてアクセスを取り消し、セッションが削除される(400を返す) | Webhookまたはセッション比較(400を返す) |
これらのシナリオを理解することで、適切な検出戦略を実装できます。
ステップ1:検出アプローチを選択
権限の変更を検出するには、2つのアプローチがあります。ほとんどの実装では、両方を使用し、Webhookを主要な方法として、セッション比較をフォールバックとして使用する必要があります。
アプローチA:Webhookベースの検出(推奨)
HTTPコールバックを受信できるサーバーがある場合は、Webhookを使用してください。
このアプローチでは、親が権限を変更すると、k-IDがすぐにサーバーに通知します。サーバーは独自の状態を更新し、ゲームは次回の起動時または機能アクセス時に更新された状態を読み取ります。
利点:
- 変更の検出に遅延のないリアルタイム通知
- 一定のポーリングよりもリソース使用量が少ない
- プレイヤーへの積極的な通知を可能にする
仕組み:
アプローチB:再起動時のセッション比較
Webhookがない場合、またはWebhookと併用してフォールバックとして使用する場合は、セッション比較を使用してください。
このアプローチでは、ゲームが最後に知られているセッションをキャッシュし、各再起動時(またはゲームプレイ中に定期的に)k-IDからの現在のセッションと比較します。
利点:
- Webhook設定が不要
- 年齢アップの変更をキャッチ(Webhookをトリガーしない)
- 実装が簡単
仕組み:
ステップ2:Webhookベースの検出を実装
ゲームにサーバーがある場合は、リアルタイムの権限更新のためにWebhookベースの検出を実装します。
すべてのk-ID API呼び出しは、クライアント側のコードではなく、サーバーから行う必要があります。APIキーをゲームクライアントに公開してはいけません。このガイドの例は、サーバー側のコード(Node.jsとExpress)を示しています。ゲームクライアントは独自のサーバーと通信し、そのサーバーがk-ID APIを呼び出します。
Webhookエンドポイントを設定
Compliance Studioで、プロダクトの開発者設定の下にWebhook URLを設定します。エンドポイントが以下を受信できることを確認してください:
Session.ChangePermissions:親が権限を変更したときに発火Session.Delete:セッションが削除されたときに発火
Session.ChangePermissions Webhookを処理
k-IDがこのWebhookを発火したら、サーバーの状態を更新して、セッションが変更されたことをフラグ付けします:
app.post("/webhook/k-id", (req, res) => {
const { eventType, data } = req.body;
switch (eventType) {
case "Session.ChangePermissions":
// Flag this session as having changed permissions
markSessionAsChanged(data.id, {
changeType: "permissions_updated",
changedAt: new Date().toISOString()
});
break;
case "Session.Delete":
// Parent revoked access - session has been deleted
// Note: All incomplete challenges for this player are automatically set to FAIL
markSessionAsDeleted(data.id);
break;
}
res.status(200).send("OK");
});
権限を取得して比較
ゲームクライアントがサーバーに接続したら、変更フラグを確認し、k-IDから更新されたセッションを取得し、保存されたバージョンと比較して、何が変更されたかを判断します:
// Server-side endpoint that your game client calls
app.get("/api/check-permissions/:sessionId", async (req, res) => {
const { sessionId } = req.params;
const changeInfo = await getChangeFlag(sessionId);
if (!changeInfo.hasChanged) {
return res.json({ hasChanged: false });
}
const cachedSession = await getStoredSession(sessionId);
const response = await fetch(
`https://game-api.k-id.com/api/v1/session/get?sessionId=${sessionId}`,
{ headers: { "Authorization": `Bearer ${process.env.KID_API_KEY}` } }
);
const { session: newSession } = await response.json();
const changes = comparePermissions(cachedSession, newSession);
await storeSession(sessionId, newSession);
await clearChangeFlag(sessionId);
res.json({
hasChanged: true,
changes: changes,
session: newSession
});
});
comparePermissions関数(ステップ3で示す)は、どの権限が変更されたかを正確に識別し、プレイヤーに特定のメッセージを表示できるようにします。
ステップ3:セッション比較を実装
フォールバック(またはWebhookがない場合は主要な方法)としてセッション比較を実装します。このアプローチは、Webhookをトリガーしない年齢アップの変更を検出するためにも不可欠です。
Session.ChangePermissions Webhookは、権限が変更されたことを通知しますが、何が変更されたかは含まれません。どの特定の権限が有効または無効になったかを判断するには、更新されたセッションを取得し、キャッシュされたバージョンと比較する必要があります。この比較ロジックは、Webhookまたはポーリングのいずれを使用する場合でも必要です。
セッションを保存
セッションを受け取ったら、サーバーに保存します(データベース、キャッシュ、またはプレイヤーに関連付けられたその他の永続ストレージに):
// Server-side session storage
async function storeSession(sessionId, session) {
await db.sessions.upsert({
sessionId: sessionId,
session: session,
updatedAt: new Date().toISOString()
});
}
async function getStoredSession(sessionId) {
const record = await db.sessions.findOne({ sessionId });
return record?.session || null;
}
ゲーム開始時にセッションを比較
ゲームクライアントが起動したら、サーバーを呼び出してセッションの変更を確認する必要があります。サーバーはk-IDから現在のセッションを取得し、比較します:
// Server-side endpoint that your game client calls on startup
app.get("/api/session/:sessionId", async (req, res) => {
const { sessionId } = req.params;
const cachedSession = await getStoredSession(sessionId);
if (!cachedSession) {
return res.json({ needsConsent: true });
}
const response = await fetch(
`https://game-api.k-id.com/api/v1/session/get?sessionId=${sessionId}&etag=${cachedSession.etag}`,
{ headers: { "Authorization": `Bearer ${process.env.KID_API_KEY}` } }
);
if (response.status === 304) {
return res.json({ hasChanged: false, session: cachedSession });
}
const { session: currentSession } = await response.json();
const changes = comparePermissions(cachedSession, currentSession);
await storeSession(sessionId, currentSession);
res.json({
hasChanged: changes.length > 0,
changes: changes,
session: currentSession
});
});
権限の違いを検出
古いセッションと新しいセッションを比較して、特定の変更を識別します:
function comparePermissions(oldSession, newSession) {
const changes = [];
for (const newPerm of newSession.permissions) {
const oldPerm = oldSession.permissions.find(p => p.name === newPerm.name);
if (!oldPerm) {
changes.push({ type: "added", permission: newPerm.name, enabled: newPerm.enabled });
} else if (oldPerm.enabled !== newPerm.enabled) {
changes.push({
type: newPerm.enabled ? "enabled" : "disabled",
permission: newPerm.name,
previousState: oldPerm.enabled
});
} else if (oldPerm.managedBy !== newPerm.managedBy) {
changes.push({
type: "management_changed",
permission: newPerm.name,
previousManagedBy: oldPerm.managedBy,
newManagedBy: newPerm.managedBy
});
}
}
if (oldSession.ageStatus !== newSession.ageStatus) {
changes.push({
type: "age_status_changed",
previousStatus: oldSession.ageStatus,
newStatus: newSession.ageStatus
});
}
return changes;
}
プレイヤーが年齢アップし、親の同意を必要としなくなると、k-IDはWebhook通知を送信しません。ただし、セッションを比較すると、以前はmanagedBy: "GUARDIAN"だった権限がmanagedBy: "PLAYER"に変更されていることに気づくでしょう。
権限がプレイヤー管理になると、プレイヤーは親の同意なしで直接制御できます。親に依頼するのではなく、プレイヤー自身がこれらの権限を有効または無効にできるようにUIを更新する必要があります。プレイヤーが/session/upgrade APIを介してPLAYER管理の権限を有効にすることをリクエストすると、チャレンジを作成せずに自動的に有効になります。ステップ4のupdateFeatureAccess関数は、UIでPLAYER管理の権限を処理する方法を示しています。
ステップ4:変更をプレイヤーに伝達
変更を検出したら、機能が変更された理由をプレイヤーに明確に伝達します。これは重要です:プレイヤーが何かが壊れていると思ってはいけません。
権限の変更を伝達し、無効な機能を表示し、権限リクエストを処理するための詳細な設計推奨事項については、UXガイドラインを参照してください。
情報提供ダイアログを表示
クライアント側で、何が変更されたか、なぜ変更されたかを説明するダイアログを表示します(サーバーから返されたchanges配列を使用):
function showPermissionChangeDialog(changes) {
const disabledFeatures = changes
.filter(c => c.type === "disabled")
.map(c => getFeatureDisplayName(c.permission));
const enabledFeatures = changes
.filter(c => c.type === "enabled")
.map(c => getFeatureDisplayName(c.permission));
const ageChanged = changes.find(c => c.type === "age_status_changed");
let message = "";
if (ageChanged) {
// Player aged up
message = "Happy birthday! 🎉 Your permissions have been updated based on your new age.";
} else if (disabledFeatures.length > 0 && enabledFeatures.length === 0) {
// Parent restricted features
message = "Your parent has updated your permissions. " +
"The following features are no longer available:\n\n" +
disabledFeatures.map(f => `• ${f}`).join("\n");
} else if (enabledFeatures.length > 0 && disabledFeatures.length === 0) {
// Parent enabled features
message = "Great news! Your parent has enabled new features:\n\n" +
enabledFeatures.map(f => `• ${f}`).join("\n");
} else {
// Mixed changes
message = "Your permissions have been updated.";
if (enabledFeatures.length > 0) {
message += "\n\nNow available:\n" + enabledFeatures.map(f => `• ${f}`).join("\n");
}
if (disabledFeatures.length > 0) {
message += "\n\nNo longer available:\n" + disabledFeatures.map(f => `• ${f}`).join("\n");
}
}
showDialog({
title: "Permissions Updated",
message: message,
buttons: [{ text: "OK", action: "dismiss" }]
});
}
function getFeatureDisplayName(permissionName) {
const displayNames = {
"voice-chat": "Voice Chat",
"text-chat-private": "Private Messages",
"text-chat-public": "Public Chat",
"in-game-purchases": "In-Game Purchases",
"multiplayer": "Online Multiplayer",
// Add all your permissions here
};
return displayNames[permissionName] || permissionName;
}
無効な機能を適切に処理
クライアント側で、機能が無効になっている場合、UIがこれを明確に反映するようにします(サーバーから返されたセッションデータを使用):
function updateFeatureAccess(session) {
for (const permission of session.permissions) {
const featureElement = document.querySelector(`[data-feature="${permission.name}"]`);
if (!featureElement) continue;
if (!permission.enabled) {
featureElement.classList.add("feature-disabled");
if (permission.managedBy === "GUARDIAN") {
// 親の同意が必要
featureElement.setAttribute("data-disabled-reason", "parent");
featureElement.querySelector(".disabled-message").textContent =
"Ask a parent to enable this feature";
} else if (permission.managedBy === "PROHIBITED") {
// 利用不可:管轄区域の禁止またはプレイヤーの年齢がverifiedAgeThresholdを下回っている
featureElement.setAttribute("data-disabled-reason", "prohibited");
featureElement.querySelector(".disabled-message").textContent =
"This feature is not available";
} else if (permission.managedBy === "PLAYER" && permission.verifiedAgeThreshold) {
// プレイヤー管理だが最初に年齢確認が必要(ブラジルのルートボックスなど)
featureElement.setAttribute("data-disabled-reason", "age-verification");
featureElement.querySelector(".disabled-message").textContent =
"Age verification required to enable this feature";
featureElement.addEventListener("click", () => requestAgeVerification(permission.name));
} else if (permission.managedBy === "PLAYER") {
// プレイヤーが直接有効にできる:同意や確認は不要
featureElement.setAttribute("data-disabled-reason", "player-choice");
featureElement.querySelector(".disabled-message").textContent = "Tap to enable";
featureElement.addEventListener("click", () => togglePlayerPermission(permission.name));
}
} else {
featureElement.classList.remove("feature-disabled");
if (permission.managedBy === "PLAYER") {
featureElement.setAttribute("data-managed-by", "player");
}
}
}
}
managedByがPLAYERの場合、プレイヤーは親の同意なしで権限を直接制御できます。これは通常、プレイヤーが年齢アップした後に発生します。プレイヤーがこれらの権限を有効または無効にできるトグルやボタンなどのUIコントロールを提供する必要があります。プレイヤーが/session/upgrade APIを介してPLAYER管理の権限を有効にすることをリクエストすると、チャレンジを作成せずに自動的に有効になります(親の同意は不要です)。
ステップ5:セッション削除を処理
親がFamily Connectを通じてプレイヤーのプロダクトへのすべてのアクセスを取り消すと、セッションは最終ステップとして削除されます。セッションは単に消えます:クエリはHTTP 400を返します。これが発生した場合(Webhookまたはセッション比較中に検出)、プレイヤーは再度アクセスを取得するために年齢ゲートと同意フローを完了する必要があります。
セッション削除の理解
親がゲームまたはプロダクトへのアクセスを取り消すと:
- セッションが削除される - 最終ステップとして、セッションが削除されます。クエリはHTTP 400を返し、セッションが存在しなかったかのように見えます
- すべての未完了のチャレンジが失敗する - そのプレイヤーの保留中のチャレンジはすべて自動的に
FAILに設定されます - Webhookイベントが送信される - 削除に関するWebhook通知を受信します
k-ID APIは、有効なセッションステータスとしてACTIVEまたはHOLDのみを返します。親がアクセスを取り消すと、セッションが削除され、APIは400(見つからない)を返します。これは意図的です:セッションが削除されると、存在しなくなったものとして扱う必要があります。削除されたセッションは、プレイヤーがゲームにアクセスできなくなったため、実質的に「見つからない」ものです。
削除されたセッションを検出
Webhook経由(サーバー側):
case "Session.Delete":
await deleteStoredSession(data.id);
await markSessionAsDeleted(data.id);
break;
セッションを取得する際のAPI経由(サーバー側):
const response = await fetch(
`https://game-api.k-id.com/api/v1/session/get?sessionId=${sessionId}`,
{ headers: { "Authorization": `Bearer ${process.env.KID_API_KEY}` } }
);
if (response.status === 400) {
const error = await response.json();
if (error.error === "NOT_FOUND") {
await deleteStoredSession(sessionId);
return res.json({ sessionDeleted: true });
}
}
セッションをクエリする際のNOT_FOUNDエラーを含む400レスポンスは、以下を意味する可能性があります:
- セッションが作成されなかった
- セッションが削除された
- セッションIDが無効
アプリケーションは、これらのすべてのケースを同じ方法で処理する必要があります:根本的な理由に関係なく、プレイヤーがアクセス権を持っていないことを示すものとして扱います。ポーリングのみに依存するのではなく、Webhookを使用してセッション削除に関するリアルタイム通知を受信します。
年齢ゲートにリダイレクト
ゲームクライアントがサーバーからsessionDeleted: trueレスポンスを受信したら、年齢ゲートフローを再開します:
// Client-side handling
async function checkSession(sessionId) {
const response = await fetch(`/api/session/${sessionId}`);
const data = await response.json();
if (data.sessionDeleted || data.needsConsent) {
// Show explanation to the player
showDialog({
title: "Session Ended",
message: "Your session has ended. Please complete age verification to continue playing.",
buttons: [{
text: "Continue",
action: () => navigateToAgeGate()
}]
});
}
}
ステップ6:新しい権限のアップグレードパスを提供
プレイヤーは、親の同意または年齢確認を必要とする機能へのアクセスをリクエストしたい場合があります。/session/upgrade APIは、このフローを可能にします。
アップグレードタイプを確認
アップグレードプロンプトを表示する前に、権限に必要なアップグレードの種類を確認します。このロジックは、サーバーから返されたセッションデータを使用してクライアント側で実行されます:
// Client-side check using session data from your server
function getUpgradeType(session, permissionName) {
const permission = session.permissions.find(p => p.name === permissionName);
if (!permission || permission.enabled) return null;
if (permission.managedBy === "PROHIBITED") {
// アップグレード不可:管轄区域の禁止またはプレイヤーが若すぎる
return null;
}
if (permission.managedBy === "GUARDIAN") {
// 親の同意が必要:CHALLENGE_SESSION_UPGRADEが返される
return "guardian-consent";
}
if (permission.managedBy === "PLAYER" && permission.verifiedAgeThreshold) {
// プレイヤー管理だが年齢確認が必要:CHALLENGE_SESSION_UPGRADE_BY_AGE_ASSURANCEが返される
return "age-assurance";
}
if (permission.managedBy === "PLAYER") {
// チャレンジ不要:アップグレード呼び出しで即座に有効
return "player-direct";
}
return null;
}
権限がPROHIBITEDになるのは、プレイヤーの管轄区域で禁止されているか、プレイヤーの年齢がverifiedAgeThresholdを下回って現在の年齢では満たせない場合です。たとえば、ブラジルのルートボックス権限は確認済み年齢18歳が必要です。この閾値を下回るプレイヤーには権限がPROHIBITEDとして表示され、どのアップグレードフローでも有効にすることはできません。詳細については、高リスク権限と年齢保証を参照してください。
権限のアップグレードをリクエスト
プレイヤーが機能をリクエストすると、ゲームクライアントがサーバーを呼び出し、サーバーがk-IDセッションアップグレードAPIを呼び出します。レスポンスは権限タイプによって異なります:
// Server-side endpoint
app.post("/api/request-permission", async (req, res) => {
const { sessionId, permissionName, platformAgeSignal } = req.body;
const upgradeRequest = {
sessionId: sessionId,
requestedPermissions: [{ name: permissionName }]
};
// プラットフォーム年齢シグナルが利用可能な場合(Apple iOSやGoogle Playなど)、
// 含めることで別の確認チャレンジなしに年齢確認閾値を満たせる可能性があります。
if (platformAgeSignal) {
upgradeRequest.platformAgeSignal = platformAgeSignal;
}
const response = await fetch(
"https://game-api.k-id.com/api/v1/session/upgrade",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KID_API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify(upgradeRequest)
}
);
const result = await response.json();
if (result.status === "PASS") {
// 権限が即座に有効:プレイヤー管理で閾値なし、
// またはプラットフォーム年齢シグナルがverifiedAgeThresholdを満たした
await storeSession(sessionId, result.session);
return res.json({ success: true, session: result.session });
} else if (result.status === "CHALLENGE") {
const challengeType = result.challenge.type;
if (challengeType === "CHALLENGE_SESSION_UPGRADE") {
// 保護者管理の権限:親が承認する必要がある
return res.json({
success: false,
requiresParentConsent: true,
challenge: result.challenge
});
} else if (challengeType === "CHALLENGE_SESSION_UPGRADE_BY_AGE_ASSURANCE") {
// verifiedAgeThreshold権限:プレイヤーがAgeKit+で年齢を確認する必要がある
// プレイヤー(親ではなく)をchallenge.urlに誘導する
return res.json({
success: false,
requiresAgeAssurance: true,
challenge: result.challenge
});
}
}
});
オプションA:セッションアップグレードウィジェットを使用(推奨)
セッションアップグレードウィジェットは、親が権限リクエストを確認して承認するための完全な、事前構築されたインターフェースを提供します。Webベースのゲームを構築している場合、またはiframeを表示できる場合、これは最も簡単なアプローチです。
セッションアップグレードウィジェットは、親がGUARDIAN管理の権限を承認する必要があるCHALLENGE_SESSION_UPGRADEチャレンジのためのものです。CHALLENGE_SESSION_UPGRADE_BY_AGE_ASSURANCEチャレンジ(verifiedAgeThresholdを持つ高リスク権限)の場合、プレイヤーはAgeKit+で年齢確認を完了するためにchallenge.urlに誘導されます:親のウィジェットは使用されません。
セッション権限管理ウィジェットは、親が認証されたセッションでのみホストする必要があります。ウィジェットは独自の親認証を提供しないため、未成年者に直接提示してはいけません。ウィジェットが認証された親または信頼できる大人にのみ表示されるように常に確認してください。
CHALLENGE_SESSION_UPGRADEが返されたら、ウィジェットURLを生成して親に表示します:
// Server-side endpoint to generate the widget URL
app.post("/api/permission-widget", async (req, res) => {
const { sessionId, parentEmail } = req.body;
const response = await fetch(
"https://game-api.k-id.com/api/v1/widget/generate-manage-session-permissions-url",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KID_API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
sessionId: sessionId,
email: parentEmail
})
}
);
const { url } = await response.json();
res.json({ widgetUrl: url });
});
クライアント側でiframeにウィジェットを表示します:
<iframe
id="permission-widget"
src="WIDGET_URL"
width="100%"
height="600"
allow="camera;payment;publickey-credentials-get;publickey-credentials-create"
frameborder="0">
</iframe>
ウィジェットは、親の検証と権限承認を含む完全な同意フローを処理します。フローが完了したらWidget.ExitReview DOMイベントをリッスンし、サーバーからセッションを更新します。
オプションB:年齢保証チャレンジを処理
CHALLENGE_SESSION_UPGRADE_BY_AGE_ASSURANCEの場合、プレイヤー(親ではなく)がAgeKit+で年齢を確認する必要があります。プレイヤーをchallenge.urlに誘導します:
// Client-side: handle age assurance challenge
function handleAgeAssuranceChallenge(challenge) {
showDialog({
title: "Age Verification Required",
message: "To access this feature, you need to verify your age.",
buttons: [
{
text: "Verify Age",
action: () => {
// AgeKit+の年齢保証フローを開く
// 完了後、セッションを更新して権限が有効になったか確認する
window.open(challenge.url, "_blank");
}
},
{ text: "Not Now", action: "dismiss" }
]
});
}
プレイヤーがフローを完了または閉じた後、サーバーを介してセッションを更新して権限の変更を反映させます。
オプションC:カスタム同意フローを構築
UIを完全にコントロールする必要がある場合、またはiframeを使用できない場合は、CHALLENGE_SESSION_UPGRADEのカスタム同意フローを構築します。親が同意を提供するためのオプションを提示します:
// Client-side UI
function showConsentRequest(challenge) {
showDialog({
title: "Ask a Parent",
message: "A parent needs to approve this feature. How would you like to reach them?",
options: [
{
label: "Send an email",
action: () => showEmailInput(challenge.challengeId)
},
{
label: "Show QR code",
action: () => showQRCode(challenge.url)
},
{
label: "Show code",
sublabel: `Go to asktoplay.com and enter: ${challenge.oneTimePassword}`,
action: () => showCodeDisplay(challenge.oneTimePassword)
}
]
});
}
カスタム同意フローを処理する詳細については、カスタム年齢ゲートクイックスタートを参照してください。
ベストプラクティス
パフォーマンスの推奨事項
- 可能な限りWebhookを優先:ポーリングよりも効率的で、リアルタイムの更新を提供するため
etagパラメータを使用:/session/getを呼び出す際に、不要なデータ転送を避けるため- セッションをローカルにキャッシュ:必要な場合にのみ更新を取得
- 頻繁にポーリングしない:ポーリングする必要がある場合は、ゲームプレイ中は少なくとも30秒間隔でリクエストを待つか、ゲーム開始時のみチェック
エッジケースの処理
- オフラインプレイヤー:セッションをキャッシュし、キャッシュされた権限を適用します。接続が復帰したら更新を確認します。
- 複数のデバイス:プレイヤーが複数のデバイスを使用できる場合、一貫性を確保するために、アカウントに関連付けられたクラウドストレージにセッションを保存します。
- ゲームプレイ中の年齢アップ:長時間のゲームプレイセッションでは、誕生日によってトリガーされた変更をキャッチするために、定期的なセッション更新を検討します。
次のステップ
セッションと権限の管理を実装したので、これらのリソースを探索してください:
- Sessions:セッションのライフサイクルと構造の詳細
- Challenges:同意チャレンジ、ステータス処理、ベストプラクティスの完全なガイド
- Permissions:権限タイプと管理に関する詳細情報
- 高リスク権限と年齢保証:
verifiedAgeThreshold権限の仕組みと解除方法 - 高リスク機能のための年齢保証:閾値を下回るプレイヤーの完全な回復フロー
- Webhooks:Webhook実装と検証の完全なガイド
Session.ChangePermissions:Webhookイベントリファレンス- Best practices:追加の実装ガイダンス